【问题标题】:How to force EntityManager.persist() to do only insert and not update如何强制 EntityManager.persist() 只插入而不更新
【发布时间】:2017-09-06 22:18:06
【问题描述】:

我正在尝试将数据插入到具有列 (NAME, VALUE)

的表中

EntityManager.persist()。

当我持久化像 ('xx', 'value1') 这样的实体时,它会在该实体的表中插入一条新记录。但是,如果我想保留一个像 ('xx', 'value2') 这样的新实体,该实体将保留在现有记录的位置。

问题是:

  • 为什么以及如何发生?
  • 有没有办法也插入 ('xx', 'value2')?

我发现了一个类似的问题here,但这个问题没有真正的答案。

非常感谢。

更新:第一列不是主键。相反,第二个是。

这里是实体:

@Entity
@Table(name = "TEST_DATA")
public class TestDataEntity implements Serializable {
    private static final long serialVersionUID = 1L;

    @Column(name = "NAME", nullable = false)
    private String name;

    @Id
    @Column(name = "VALUE", nullable = false)
    private String value;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }
}

这里是持久化代码:

@Transactional
public static void storeTestData(EntityManager em, String name, String value) {
    TestDataEntity entity = new TestDataEntity();
    entity.setName(name);
    entity.setValue(value);

    em.persist(entity);
}

另外还有一个问题,描述为here.

【问题讨论】:

  • 列是主键,不是值
  • @Armine:所以当你第一次调用storeTestData(entityManager, "xx", "value1"); 然后storeTestData(entityManager, "xx", "value2"); 它实际上覆盖了之前持久化实体的主键并将其更改为“value2”?这确实很奇怪,我无法解释为什么会这样。
  • @OHGODSPIDERS:是的,和你描述的完全一样。这就是为什么我无法理解原因:(。

标签: java hibernate jpa


【解决方案1】:

问题是这样解决的:

@Transactional
public static void storeTestData(EntityManager em, String name, String value) {
    EntityTransaction transaction = em.getTransaction();

    try {
        transaction.begin();

        TestDataEntity entity = new TestDataEntity();
        entity.setName(name);
        entity.setValue(value);

        em.persist(entity);

        transaction.commit();
    } catch (RuntimeException re) {
        if (transaction != null && transaction.isActive())  {
            transaction.rollback();
        }

        throw re;
    }

这意味着,如果没有提供显式事务,则如果现有记录具有与实体对象中相应字段值匹配的任何值,则会更新现有记录。

恕我直言,这真的很奇怪而且不简单,因为它会抛出一个更好的

javax.persistence.TransactionRequiredException

就像更新/删除语句一样。

【讨论】:

    【解决方案2】:

    检查你的实体是否正确实现了equals()和hashCode(),通常这样可以解决问题

    【讨论】:

    • 其实我并没有重载这些方法,因此两个实体不应该相等,对吧?
    • @Armine 您是否每次都通过构造函数创建新的实体及其内容?如果您只是修改一个已经存在和持久化的实体,然后尝试再次持久化它,这可能是问题所在。否则,如果不提供一些实体类代码示例以及如何持久化它,就很难知道发生了什么。
    • @OHGODSPIDERS:请查看更新后的问题。我确实每次都通过新的构造函数创建实体。
    猜你喜欢
    • 2012-06-15
    • 2020-01-09
    • 2016-09-12
    • 1970-01-01
    • 2015-01-10
    • 1970-01-01
    • 1970-01-01
    • 2021-10-20
    • 1970-01-01
    相关资源
    最近更新 更多