Hibernate saveOrUpdate,update需要原始行的所有字段

时间:2012-07-30 11:45:15

标签: java mysql hibernate

我正在使用mysql和hibernate来插入和更新表中的行。我使用saveOrUpdate调用。现在,当我尝试更新表中的行时,我得到一个异常。异常表明我的列requestTime不能为null。显然它是真的,因为我已将column属性设置为NotNull。

我可以添加行。但是当用更多列的值更新它时,我得到了这个例外。

我假设当我更新时,我需要从表中读取行,并更新整行。真的吗 ?我有点希望hibernate saveOrUpdate会为我做这件事。所以当我插入一个新行时,我有一个对所有列都有getter的Object。但是当我更新时,我有一个只有主键和新列的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

从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`),

3 个答案:

答案 0 :(得分:2)

Hibernate无法弄清楚你想要如何处理具有null值的属性。在以下情况之间无法区分:

  1. 某些属性为null - >应在数据库中设置为null
  2. 某些属性为null - >不应该更新这样的属性。
  3. 将先前为非null的属性的值设置为null意味着应更改属性的值。

    如果要使列永远不属于update语句,可以在@Column注释中将updatable属性设置为false。根据它定义的文档:该列是否包含在由持久性提供程序生成的SQL UPDATE语句中

答案 1 :(得分:1)

如果你写你的表定义会更容易。

您的非空列有两种情况:

  1. 您有“默认值”。
  2.  
        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或UPDATE这个列中指定,oracle会自动将默认值放在表中。

    1. 具有“默认值”。
    2.     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或UPDATE中指定此列,oracle会自动向您发送错误消息。

      这是关于数据库中不为null的理论,让我们转到Hibernate:

      你可以把列注释放在这样的东西:

       insert="false", update="false"
      

      然后数据库将使用默认值,但如果未在表定义中指定default,则此字段的值应始终不为null。

      编辑:

      所以我现在看到你有3列“NOT NULL”。 对于您具有默认默认“requestIdentity”的列,您可以使用动态更新或动态插入:http://www.mkyong.com/hibernate/hibernate-dynamic-update-attribute-example/

      但是对于其他人,你必须把价值放在变量中:

      private Date requestTime = new Date();
      
      private String subscriberIdentityHash = "someDefaultHashHere";
      

答案 2 :(得分: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;
}