【问题标题】:Hibernate saveOrUpdate, update needs all fields of original rowHibernate saveOrUpdate,更新需要原行的所有字段
【发布时间】:2012-07-28 02:01:15
【问题描述】:

我正在使用 mysql 和 hibernate 在表中插入和更新行。我使用 saveOrUpdate 调用。现在,当我尝试更新表中的一行时,出现异常。异常指出我的列 requestTime 不能为空。显然它是正确的,因为我已将列属性设置为 NotNull。

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

我假设当我更新时,我需要从表中读取行,并更新整行。真的吗 ?我有点希望hibernate saveOrUpdate 能为我做这件事。因此,当我插入新行时,我有一个对象,该对象具有所有列的 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

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

【问题讨论】:

  • 更新和插入是否需要不同的代码流?类似 if (update) { row=getColumn(primaryKey), appendValues(row, newValues) } else insert ?

标签: java mysql hibernate


【解决方案1】:

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;
}

【讨论】:

    【解决方案2】:

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

    您的非空列有两种情况:

    1. 您有一个“默认值”。
    创建表 t1 ( id 整数不为空, column1 char 不为空,默认为 'Y', column2 日期不为空默认 sysdate, column3 varchar2(30) 不为空默认用户, intcol 整数 不为空 默认 12 );

    如果您没有在 INSERT 或 UPDATE 中指定此列,oracle 会自动将默认值放入表中。

    1. 没有有“默认值”。
    创建表 t1 ( id 整数不为空, column1 char 不为空, column2 日期不为空, column3 varchar2(30) 不为空, intcol 整数 默认 12 );

    如果您没有在 INSERT 或 UPDATE 中指定此列,oracle 会自动向您抛出错误消息。

    这是关于数据库中不为空的理论,让我们去Hibernate:

    您可以在列注释中添加如下内容:

     insert="false", update="false"
    

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

    编辑:

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

    但对于其他人,你必须将值放入变量中:

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

    【讨论】:

    • 谢谢,我已经用表格定义编辑了问题,我应该把注释放在哪里?
    【解决方案3】:

    Hibernate 无法确定您希望如何处理具有空值的属性。它无法区分以下情况:

    1. 某些属性为空 -> 应在数据库中设置为空
    2. 某些属性为空 -> 不应更新此类属性。

    将之前非空属性的值设置为空意味着应该更改属性的值。

    如果您想让列永远不会成为更新语句的一部分,您可以在@Column 注释中将可更新属性设置为 false。根据它定义的文档:该列是否包含在持久性提供程序生成的 SQL UPDATE 语句中

    【讨论】:

    • 如果更新时为空,我可以让休眠模式忽略列值吗?
    • 至少我不知道在null的情况下如何忽略它。如果适用,您可以让它永远不会成为更新的一部分。
    猜你喜欢
    • 1970-01-01
    • 2021-07-03
    • 2023-03-05
    • 2017-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多