1

我将 JPA 2 与 Hibernate 版本一起使用。4.1.7.Final 作为 JPA 实现。我也在使用 Spring framework v. 3.1.2.RELEASE 来明确。这是我的问题。

我已经编写了一种方法来添加/更新我的用户实体。

@Override
@Transactional
public void saveUser(UserForm userForm) {
    User user;

    if (userForm.getId() == null) { // new user
        user = new User();
        user.setCreationDate(new Date());
        entityManager.persist(user); // !!!
    } else {
        user = entityManager.find(User.class, userForm.getId());
    }

    user.setFirstName(userForm.getFirstName());
    user.setLastName(userForm.getLastName());
    user.setMiddleName(userForm.getMiddleName());

    user.setEmail(userForm.getEmail());

    user.setRole(entityManager.find(Role.class, 1));//TODO

    user.setLogin(userForm.getLogin());
    user.setPassword(userForm.getPassword1());

    entityManager.flush();
}

我正在测试添加用户(userForm.getId() == null)。上面的代码不起作用,报错:

javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: Column 'first_name' cannot be null
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1377)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1300)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1306)
at org.hibernate.ejb.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.java:989)
...

但。如果我在 flush() 之前将调用 persist() 移到最后,一切正常:

@Override
@Transactional
public void saveUser(UserForm userForm) {
    User user;

    if (userForm.getId() == null) { // new user
        user = new User();
        user.setCreationDate(new Date());
    } else {
        user = entityManager.find(User.class, userForm.getId());
    }

    user.setFirstName(userForm.getFirstName());
    user.setLastName(userForm.getLastName());
    user.setMiddleName(userForm.getMiddleName());

    user.setEmail(userForm.getEmail());

    user.setRole(entityManager.find(Role.class, 1));//TODO

    user.setLogin(userForm.getLogin());
    user.setPassword(userForm.getPassword1());

    entityManager.persist(user);// !!!
    entityManager.flush();
}

我认为发生的情况是在第一种(问题)情况下,它尝试存储在持久调用时存在的用户对象数据,尽管在刷新()期间执行的实际保存(更新。错误。它试图在持久( ) 称呼)。让我这么想的原因是,当我尝试调试时,我发现它仍然尝试在内部某处插入正确的 creation_date,但其他值是空值。

但我发誓,在几年前我一直在从事的另一个项目中,这工作得很好,尽管后来我使用了 Oracle 而不是 MySQL(我不认为这是原因)和旧版本的框架。

这里可能是什么问题?也许 Hibernate 有一些配置选项会影响这个?

或者这是正确的行为和我对 JPA API 的误解?

UPD。我在用着

@Id
@GeneratedValue
@Column(columnDefinition="INT")
private int id;

用于用户条目中的 id 字段。我相信这意味着生成策略 = AUTO,这适用于 mysql auto_increment 键。

4

2 回答 2

1

您将用户名设置为 null ( user.setFirstName(userForm.getFirstName());),因为userForm.getFirstName()返回 null,并且您的错误显示:Column 'first_name' cannot be null

您应该检查为什么userForm.getFirstName()返回 null 或允许用户的名字为 null,因为您当前的实体配置不允许这样做。

也许您可以向我们展示用户实体?

于 2012-10-08T20:22:23.680 回答
1

那是正确的行为。在您第一次调用 persist() 时,用户的 firstName 为空。尽管您在这一点之后设置了名字,但在刷新之前,JPA/Hibernate 准备的命令将类似于,

在持久化时,用户对象的状态可以说,user@version1 从 user@version1 对象插入用户值(id、creationdate、null、null..)

现在存在一个新的用户版本 user@version2

冲水的时候,

检查是否有任何挂起的插入/更新.. 将所有对象带到 version1,这是最后一次持久化的时间。

请注意,flush 可能会或可能不会在 DB 中进行物理插入操作,但对象会被带到正确的状态,这意味着非持久性更改将丢失。

不要担心它之前是否可以正常工作,可能是在休眠 3 中,并且在您迁移到休眠 4 时开始无法正常工作。我有几个问题,休眠 3 没有问题,但在没有额外修复的情况下无法在休眠 4 上工作。

于 2012-10-09T08:04:32.583 回答