2012-07-30 82 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; 
}