2012-05-18 31 views
5

Có một bực bội vấn đề với Hibernate 3.6.9. MS SQL Server 2008. Lưu ý ngoại lệ và tham chiếu chỉ mục cột lẻ.ngoại lệ hibernate Null giá trị đã được gán cho một tài sản của nguyên thủy loại setter

Các HQL Query bản thân:

Select r from DataStoreReference r join fetch r.container c where r.hash=:hash and r.state=0 

Các stack trace:

2012-05-16 00:01:22,184 [BackgroundDeletionThread] ERROR org.hibernate.util.JDBCExceptionReporter - The value supplied cannot be converted to BIGINT. 
2012-05-16 00:01:22,186 [BackgroundDeletionThread] ERROR org.hibernate.util.JDBCExceptionReporter - The value supplied cannot be converted to BIGINT. 
2012-05-16 00:01:22,188 [BackgroundDeletionThread] ERROR org.hibernate.util.JDBCExceptionReporter - Invalid column index 14. 
2012-05-16 00:01:22,190 [BackgroundDeletionThread] ERROR org.hibernate.util.JDBCExceptionReporter - The value supplied cannot be converted to BIGINT. 
2012-05-16 00:01:22,193 [BackgroundDeletionThread] ERROR org.hibernate.util.JDBCExceptionReporter - The value supplied cannot be converted to BIGINT. 
2012-05-16 00:01:22,194 [BackgroundDeletionThread] ERROR org.hibernate.util.JDBCExceptionReporter - Invalid column index 14. 
2012-05-16 00:01:22,194 [BackgroundDeletionThread] ERROR com.flipper.utils.ServerErrorHandlerStrategy - reportError: Db :: com.flipper.datastore.workers.BackgroundDeletionThread.executeWork:87 :: EXCEPTION : com.flipper.datastore.exceptions.DBStoreException: Null value was assigned to a property of primitive type setter of com.flipper.datastore.model.DataStoreReference.usage com.flipper.datastore.exceptions.DBStoreException: Null value was assigned to a property of primitive type setter of com.flipper.datastore.model.DataStoreReference.usage 
    at com.flipper.datastore.impl.hib.HibernateDBStore.getAllReferences(HibernateDBStore.java:301) 
    at com.flipper.datastore.workers.BackgroundDeletionThread.processEntry(BackgroundDeletionThread.java:165) 
    at com.flipper.datastore.workers.BackgroundDeletionThread.processSet(BackgroundDeletionThread.java:138) 
    at com.flipper.datastore.workers.BackgroundDeletionThread.executeWork(BackgroundDeletionThread.java:84) 
    at com.flipper.datastore.workers.BackgroundDeletionThread.run(BackgroundDeletionThread.java:60) 
Caused by: org.hibernate.PropertyAccessException: Null value was assigned to a property of primitive type setter of com.flipper.datastore.model.DataStoreReference.usage 
    at org.hibernate.property.BasicPropertyAccessor$BasicSetter.set(BasicPropertyAccessor.java:109) 
    at org.hibernate.tuple.entity.AbstractEntityTuplizer.setPropertyValues(AbstractEntityTuplizer.java:583) 
    at org.hibernate.tuple.entity.PojoEntityTuplizer.setPropertyValues(PojoEntityTuplizer.java:229) 
    at org.hibernate.persister.entity.AbstractEntityPersister.setPropertyValues(AbstractEntityPersister.java:3847) 
    at org.hibernate.engine.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:152) 
    at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:982) 
    at org.hibernate.loader.Loader.doQuery(Loader.java:857) 
    at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:274) 
    at org.hibernate.loader.Loader.doList(Loader.java:2542) 
    at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2276) 
    at org.hibernate.loader.Loader.list(Loader.java:2271) 
    at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:459) 
    at org.hibernate.hql.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:365) 
    at org.hibernate.engine.query.HQLQueryPlan.performList(HQLQueryPlan.java:196) 
    at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1268) 
    at org.hibernate.impl.QueryImpl.list(QueryImpl.java:102) 
    at com.flipper.message.dao.DataStoreDao.getAllReferencesByHash(DataStoreDao.java:136) 
    at com.flipper.datastore.impl.hib.HibernateDBStore.getAllReferences(HibernateDBStore.java:298) 
    ... 4 more 
Caused by: java.lang.IllegalArgumentException 
    at sun.reflect.GeneratedMethodAccessor556.invoke(Unknown Source) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
    at java.lang.reflect.Method.invoke(Method.java:597) 
    at org.hibernate.property.BasicPropertyAccessor$BasicSetter.set(BasicPropertyAccessor.java:66) 
    ... 21 more 

Bây giờ, tôi muốn hiểu được điều này từ logic (và từ googling) nếu sau là không đúng sự thật

a) mọi instantiation của DataStoreReference được theo sau bởi một setUsage của System.currentTimeMillis) b) mục được đánh dấu không null trong ánh xạ (xem bên dưới) c) bảng được xuất chỉ hiển thị các giá trị rỗng trong cột f_external. Cột sử dụng có số lượng dài hoàn toàn hợp lý.

Các POJO:

DataStoreReference

private long id; 


private String hash;  
private long date; 
private long sze; 
private long usage; 

private int state; 
private String external; 
private DataStoreContainer container; 

Tiếp theo generic chưa sửa đổi getter/setters.

Các tập tin bản đồ:

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 
<hibernate-mapping package="com.flippr.datastore.model"> 
    <class name="DataStoreReference" table="t_dsref"> 
    <id name="id"> 
     <column name="ds_reference_id"/> 
     <generator class="native"/> 
    </id> 
    <property name="hash" not-null="true" column="f_hash" lazy="false" index="idx_hash_dsr" type="string" length="128" /> 
    <property name="state" not-null="true" column="f_state" lazy="false" index="idx_hash_dsr,idx_size_dsr,idx_usage_dsr" type="integer"/> 
    <!-- hibernate hates the name size --> 
    <property name="sze" not-null="true" column="f_size" lazy="false" index="idx_size_dsr" type="long"/> 
    <property name="date" not-null="true" column="f_date" lazy="false" type="long"/>  
    <property name="usage" not-null="true" column="f_usage" lazy="false" index="idx_usage_dsr" type="long"/> 
    <property name="external" not-null="false" column="f_ext" lazy="false" type="string" length="160" /> 

    <many-to-one name="container" class="com.flipper.datastore.model.DataStoreContainer" 
    column="entity_id" foreign-key="fk_ds_container_id_dsr" not-found="ignore" not-null="true"/> 
    </class> 
</hibernate-mapping> 

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 
<hibernate-mapping package="com.flipper.datastore.model"> 
  <class name="DataStoreContainer" table="t_dscnt"> 
    <id name="id"> 
      <column name="ds_container_id"/> 
      <generator class="native"/> 
    </id> 
    <property name="containerType" column="f_type" index="idx_containerType_dsc" lazy="false" type="integer"/> 
    <property name="fileCount" column="f_fc" lazy="false" type="long"/> 
    <property name="deletedCount" column="f_dc" lazy="false" type="long"/> 
    <property name="path" column="f_path" length="255" lazy="false"  type="string"/> 
    <set cascade="save-update,delete,delete-orphan,all-delete-orphan" inverse="true" name="documents"> 
      <key column="entity_id" /> 
      <one-to-many class="com.flipper.datastore.model.DataStoreReference"/> 
    </set> 
  </class> 
</hibernate-mapping> 
+0

Oh đây là đoạn code thực tế mà gây nên vấn đề: \t \t \t Query q = this.session.createQuery (Hib) \t \t \t .setString ("băm", băm); \t \t \t @SuppressWarnings ("không được chọn") \t \t \t Danh sách reference = q.list(); // boom – MJB

+0

Hibernate đang tìm nạp này trong một phép nối, vì vậy tôi nghĩ rằng vì chỉ mục là 14, cột có lẽ nằm trong 'DataStoreContainer'. – dasblinkenlight

+0

hợp lý nhưng cột được đề cập trong ngăn xếp là cách sử dụng, chỉ có trong DataStoreReference. Tôi đã cập nhật câu hỏi để bao gồm tệp ánh xạ khác – MJB

Trả lời

2

Hóa ra đó là lỗi với phương ngữ Hibernate 3.6 MS SQL nâng cao. Nếu bạn mở rộng SQLServer2005 hoặc SQLServer2008 phương ngữ, bạn sẽ có vấn đề này. Sử dụng phương ngữ SQLServer cũ hơn (đó là khá nhiều những gì được vận chuyển với Hibernate 3.3x) bạn thì không. Có lẽ một cái gì đó để làm với hỗ trợ phân trang giới thiệu. Sigh

22

Các lỗi thông điệp là rõ ràng: Trong ít nhất một dòng các f_usage cột có một giá trị null. Giá trị null này không thể được đưa vào một kiểu nguyên thủy như dài, bởi vì các kiểu nguyên thủy không thể đại diện cho null.

Thuộc tính không null trong mệnh đề thuộc tính không có hiệu lực khi đã có giá trị null trong cơ sở dữ liệu. Thuộc tính không null chỉ được sử dụng cho thế hệ dmd. Nhưng cột f_usage của bảng cơ sở dữ liệu của bạn t_dsref có thể cho phép các giá trị null (kiểm tra với desc t_dsref trong sql).

Giải pháp: Trao đổi lâu với Long:

private Long usage; 

và khi sử dụng các giá trị mà bạn có để xử lý các tình trạng null, ví dụ

if (usage != null) { 
    return usage.longValue(); 
else 
    return -1; 

(Bạn đang sử dụng getter và setter để truy cập với hibernate, vì vậy codelet này không nên ở trong getter, bởi vì trong cơ sở dữ liệu giá trị null sẽ tiếp tục là null sau khi cập nhật, nhưng bạn có thể làm điều đó trong một getter thứ hai mà bạn sử dụng ở mọi nơi khác hoặc bạn truy cập trường cho hibernate .)

Đề xuất chung của tôi: Các kiểu dữ liệu nguyên thủy chỉ nên được sử dụng cho các thuộc tính ngủ đông nếu cột được đánh dấu là NOT NULL trong cơ sở dữ liệu.

+1

Đồng ý. Cách tốt nhất khi sử dụng hibernate, không sử dụng kiểu dữ liệu nguyên thủy (thay đổi giá trị 'long' và' int' thành 'Long' và' Integer') –

+3

Đây là cách thực hành tốt nhất. Sử dụng nguyên thủy khi cột không rỗng. Sử dụng trình bao bọc khi nó không có giá trị. –

+1

lời khuyên tốt nhưng --- Như tôi đã lưu ý, tệp ánh xạ có cách sử dụng là không-null = true. Cơ sở dữ liệu được tạo ra từ HIBERNaTE bằng cách sử dụng các tiện ích lược đồ dựng sẵn. Ngoài ra dữ liệu đã được kiểm tra. Không có giá trị NULL trong cột sử dụng. Cơ sở dữ liệu được tạo ra từ đầu bằng cách sử dụng hibernate và hibernate chỉ có dân cư nó. – MJB

1

Hibernate cần một số sửa đổi để phù hợp với các tình huống thực tế của sự phát triển doanh nghiệp. Sử dụng các đối tượng thay vì các nguyên thủy dẫn đến nhiều vấn đề hơn những gì được giải quyết trong ngữ cảnh này.

Tôi đã mã hóa các ứng dụng doanh nghiệp Java EE từ năm 2002. Giải pháp tốt nhất cho trường hợp sử dụng này, có tính đến việc bạn có thể có nhiều bảng tham chiếu bảng mã với giá trị null là cập nhật cơ sở dữ liệu nếu có thể. Ví dụ: nếu bạn có bảng người có tham chiếu đến bảng mã thế hệ để biểu thị các tiêu đề như junior, Senior, v.v ... và nhiều mục không có giá trị, hãy cập nhật bảng mã để có tham chiếu chưa biết và sau đó cập nhật dữ liệu bảng cho tất cả các giá trị rỗng để trỏ đến tham chiếu đó. Vì hầu hết các ứng dụng Java EE lớn và không mã hóa, bạn có thể thử và cập nhật các điểm vào cho các bảng này nhưng rất có thể đó là một mớ hỗn độn và có thể có tất cả các điểm nhập từ các công việc cron, dịch vụ web, v.v. DB để bắt các null và mặc định chúng vào mục không xác định và lưu tự đau đầu của bạn. Nếu tòa nhà của bạn từ đầu này cũng là một đống lộn xộn với hibernate vì nó không phải là rất dễ dàng từ những gì tôi có thể nói để nói hibernate là cố gắng của bạn để gọi một setter với nguyên thủy, và nó null chỉ cần làm cho nó 0 hoặc -1 nhưng sau đó một lần nữa tôi có ít hơn 20 giờ trải nghiệm ngủ đông. Tôi chỉ đọc lên trên các loại người dùng vì vậy tôi sẽ phải đọc thêm một chút và xem cách họ làm việc.

Đối tượng trong các ứng dụng Java EE lớn là một cơn ác mộng khi chạy với chất lượng của các lập trình viên trên thị trường hiện nay.

1

Lỗi như vậy xảy ra trong Hibernate khi bạn sử dụng các kiểu nguyên thủy cho một số cột nhưng các trường đó là null trong DB. giải pháp:

giải pháp Một: sử dụng các lớp Wrapper (Số nguyên cho int ...) giải pháp Hai: xác định giá trị mặc định cho cột.

Các vấn đề liên quan