3

我正在使用 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`),
4

3 回答 3

2

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

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

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

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

于 2012-07-30T11:51:26.237 回答
1

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

您的非空列有两种情况:

  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";
于 2012-07-30T13:51:06.927 回答
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;
}
于 2013-10-22T13:00:38.577 回答