spring data jpa with hibernate 6 -为什么jpa保存()方法在我试图更新一个不存在的记录时插入?

tcomlyy6  于 2023-08-06  发布在  Spring
关注(0)|答案(1)|浏览(117)

我有一个“测试”实体:

@Entity
@Table(name = "TEST")
@lombok.Data
public class Test { 
    
    @Id
    @jakarta.persistence.GeneratedValue(generator = "test_id_gen_key")
    @org.hibernate.annotations.GenericGenerator(name="test_id_gen_key", type=org.hibernate.id.IdentityGenerator.class)
    @Column(name="id", nullable = false)
    private Integer id;
    
    @Column(name="name", nullable = true, length = 10)
    private String name;
    
}

字符串
以及TestRepository:

@Repository
public interface TestRepository extends JpaRepository<Test, Integer> {

}


当我尝试在TestService中进行如下更新时:

var test = new Test(10, "any name");  // the id value : 10 does not exist in the databse 

testRepository.save(test);


然后hibernate执行merge()方法:
1.使用id值查询数据库:10人;
1.从步骤1中什么也没有得到,然后它执行一个插入SQL来生成一个新的记录。
但是在这种情况下我想要的是抛出一个异常,CrudRepository#保存方法也说“如果实体被假设存在但不存在于数据库中,也会抛出”:

/**
     * Saves a given entity. Use the returned instance for further operations as the save operation might have changed the
     * entity instance completely.
     *
     * @param entity must not be {@literal null}.
     * @return the saved entity; will never be {@literal null}.
     * @throws IllegalArgumentException in case the given {@literal entity} is {@literal null}.
     * @throws OptimisticLockingFailureException when the entity uses optimistic locking and has a version attribute with
     *           a different value from that found in the persistence store. **Also thrown if the entity is assumed to be
     *           present but does not exist in the database**.
     */
    <S extends T> S save(S entity);


处理这种情况的最佳方法是什么?
我扩展了SimpleJpaRepository的实现,并添加了一个update方法来调用org.hibernate.Session#update()方法,它像我预期的那样工作,但该方法已经被弃用了,我不认为这是一个完美的解决方案:

@SuppressWarnings("deprecation")
    @Override
    public T update(T entity) {     
        session().update(entity);
        
        return entity;
    }

bpsygsoo

bpsygsoo1#

这是JPA保存函数的实现:

@Transactional
    public <S extends T> S save(S entity) {
        if (this.entityInformation.isNew(entity)) {
            this.em.persist(entity);
            return entity;
        } else {
            return this.em.merge(entity);
        }
    }

字符串
因此,正如您所看到的,JPA会检查实体是否存在。如果是,那么它将更新,否则JPA将插入一条新记录。如果你不想在实体不存在的情况下插入,你可以先调用findById(),如果实体不存在抛出异常,然后再调用保存()。请不要尝试修改JPA的默认行为,因为这可能会在未来导致更多问题。

相关问题