2012-07-30 84 views
3

我正在使用mysql和hibernate插入和更新表中的行。我使用saveOrUpdate調用。現在,當我嘗試更新表中的一行時,我收到一個異常。異常狀態表明我的列requestTime不能爲空。顯然它是真正的,因爲我已經設置列屬性爲NotNull。休眠saveOrUpdate,更新需要原始行的所有字段

我可以添加該行。但是,當更新2列的值時,我會得到這個異常。

我假設當我更新時,我需要讀取表中的行,並更新整個行。真的嗎 ?我有點希望,休眠saveOrUpdate會爲我做。所以我有一個Object,當我插入一個新行時,所有列都有getter。但是當我更新時,我有一個只有主鍵和新列的getter的對象。

Transaction txD; 
Session session; 
session = currentSession(); 
txD = session.beginTransaction(); 
session.saveOrUpdate(dataStore); 
txD.commit(); 

異常

749368 [Thread-2] DEBUG org.hibernate.internal.util.EntityPrinter - com.mcruiseon.carpool.concrete.SubscribeProviderConcrete{acceptedTime=Mon Jul 30 03:39:23 UTC 2012, requestTime=null, subscriberIdentityHash=1218553253, requestIdentity=167093126, subscribedProviderHash=-284086361, isAccepted=true} 
749375 [Thread-2] DEBUG org.hibernate.SQL - update carPoolSubscribedProvider set subscriberIdentityHash=?, requestTime=?, subscribedProviderHash=?, isAccepted=?, acceptedTime=? where requestIdentity=? 
749398 [Thread-2] DEBUG org.hibernate.engine.jdbc.spi.SqlExceptionHelper - Column 'requestTime' cannot be null [n/a] 
com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Column 'requestTime' cannot be null 

SELECT * FROM carPoolSubscribedProvider

+-----------------+------------------------+---------------------+------------------------+------------+--------------+ 
| requestIdentity | subscriberIdentityHash | requestTime   | subscribedProviderHash | isAccepted | acceptedTime | 
+-----------------+------------------------+---------------------+------------------------+------------+--------------+ 
| 167093126  | -284086361    | 2012-07-27 16:13:19 | 1218553253    |   0 | NULL   | 
+-----------------+------------------------+---------------------+------------------------+------------+--------------+ 

編輯:

| carPoolSubscribedProvider | CREATE TABLE `carPoolSubscribedProvider` (
    `requestIdentity` varchar(50) NOT NULL DEFAULT '', 
    `subscriberIdentityHash` varchar(100) NOT NULL, 
    `requestTime` datetime NOT NULL, 
    `subscribedProviderHash` varchar(100) DEFAULT NULL, 
    `isAccepted` tinyint(1) DEFAULT '0', 
    `acceptedTime` datetime DEFAULT NULL, 
    PRIMARY KEY (`requestIdentity`), 
+0

我是否需要有代碼更新VS插入不同的流量?像if(update){row = getColumn(primaryKey),appendValues(row,newValues)} else else insert? – Siddharth 2012-07-30 11:47:38

回答

2

Hibernate無法弄清楚你想怎麼用空值屬性來treted。它不能使情況之間的區別在哪裏:

  1. 一些屬性爲空 - >應設置爲空數據庫
  2. 一些屬性爲空 - >不應該更新這樣的屬性。

將以前非null屬性的設置值設置爲null意味着屬性的值應該改變。

如果您想讓列從不成爲update語句的一部分,則可以在@Column註釋中將updatable屬性設置爲false。根據它定義的文檔:是否列包含在由持久化提供程序生成的SQL UPDATE語句中

+1

如果更新爲null,我可以讓hibernate忽略列值嗎? – Siddharth 2012-07-30 11:52:35

+0

至少我不知道如何在null的情況下忽略它。如果適用,您可以使其不會成爲更新的一部分。 – 2012-07-30 12:13:49

+0

我知道它晚了,但謝謝。 – Siddharth 2012-10-31 06:33:55

1

如果你編寫你的表定義會更容易。

有兩種情況下,你的NOT NULL列:

  1. 你有一個 「默認值」。
 
    create table t1 
    (
     id integer not null, 
     column1 char not null default 'Y', 
     column2 date not null default sysdate, 
     column3 varchar2(30) not null default user, 
     intcol integer not null default 12 
    ); 

,如果你不是在INSERT指定或更新此列,甲骨文將自動把默認值表。

  1. 不要有一個「默認值」。
 
    create table t1 
    (
     id integer not null, 
     column1 char not null, 
     column2 date not null , 
     column3 varchar2(30) not null, 
     intcol integer default 12 
    ); 

,如果你不是在INSERT指定或更新此列,Oracle將自動拋出你的錯誤消息。

這是關於數據庫不是空的理論,讓我們去休眠:

你可以把列註釋是這樣的:

insert="false", update="false" 

然後數據庫將使用默認值,但如果您的表定義默認值未指定,則此字段的值應始終不爲空。編輯:

所以我現在看到你有3列「NOT NULL」。 對於列,你有一個definied默認「requestIdentity」您可以使用動態更新,或dynami插入:http://www.mkyong.com/hibernate/hibernate-dynamic-update-attribute-example/

但對他們的休息,你必須把值變量:

private Date requestTime = new Date(); 

private String subscriberIdentityHash = "someDefaultHashHere"; 
+0

謝謝,我用表格定義編輯了問題,我應該在哪裏放註釋? – Siddharth 2012-07-30 14:52:03

+0

更新了我的回覆。 – chris 2012-07-31 08:01:40

0

OUP =更新的行與空字段& ODB =行從數據庫中讀取的更新時間

public static <T> T updateChanges(T oDb, T oUp) { 
    try { 
     java.lang.reflect.Field[] fields = oDb.getClass().getDeclaredFields(); 
     for (Field field : fields) { 
      field.setAccessible(true); 
      if (field.get(oUp) != null) { 
       field.set(oDb, field.get(oUp)); 
      } 
     } 
    } catch (IllegalAccessException e) { 
     e.printStackTrace(); 
    } 
    return oDb; 
}