首页 > 解决方案 > 在 Hibernate/JPA Generated UPDATE Query 的 Where 子句中包含附加列

问题描述

我正在使用休眠/JPA。

当我执行entity.save()orsession.update(entity)时,hibernate 会生成这样的查询:-

update TABLE1 set COL_1=? , COL_2=? , COL_3=? where COL_PK=?

我可以通过实体中的任何注释在 WHERE 子句中包含一个附加列,因此它可以导致如下查询:-

update TABLE1 set COL_1=? , COL_2=? , COL_3=? where COL_PK=? **AND COL_3=?**

这是因为我们的数据库是基于分片的COL_3,这需要出现在 where 子句中

我希望能够使用session.update(entity)or entity.save()only 来实现这一点。

标签: mysqlhibernatespring-data-jpaspring-datasharding

解决方案


如果我理解正确,基本上你所描述的是你希望休眠就像你有一个复合主键一样,即使你的数据库有一个单列主键(你也有一个 @Version 列来执行乐观锁定) .

严格来说,你的休眠模型不需要完全匹配你的数据库模式。您可以将实体定义为具有复合主键,确保所有更新都基于这两个值的组合。这里的缺点是您的加载操作稍微复杂一些。

考虑以下实体:

@Entity
@Table(name="test_entity", uniqueConstraints = { @UniqueConstraint(columnNames = {"id"})  })
public class TestEntity implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id", nullable = false, unique = true)
    private Long id;

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

    @Column(name = "value", nullable = true)
    private String value;

    @Version
    @Column(nullable = false)
    private Integer version;

    ... getters & setters

}

然后你可以有以下方法(在我的例子中,我创建了一个简单的 JUnit 测试)

@Test
public void test() {

    TestEntity test = new TestEntity();
    test.setCol_3("col_3_value");
    test.setValue("first-value");

    session.persist(test);

    long id = test.getId();
    session.flush();
    session.clear();

    TestEntity loadedTest = (TestEntity) session
            .createCriteria(TestEntity.class)
            .add(Restrictions.eq("id", id))
            .uniqueResult();

    loadedTest.setValue("new-value");
    session.saveOrUpdate(loadedTest);
    session.flush();

}

这会生成以下 SQL 语句(启用 Hibernate 日志记录)

Hibernate: 
    call next value for hibernate_sequence
Hibernate: 
    insert 
    into
        test_entity
        (value, version, id, col_3) 
    values
        (?, ?, ?, ?)
Hibernate: 
    select
        this_.id as id1_402_0_,
        this_.col_3 as col_2_402_0_,
        this_.value as value3_402_0_,
        this_.version as version4_402_0_ 
    from
        test_entity this_ 
    where
        this_.id=?
Hibernate: 
    update
        test_entity 
    set
        value=?,
        version=? 
    where
        id=? 
        and col_3=? 
        and version=?

如您所见,这会使加载稍微复杂一些 - 我在这里使用了一个标准,但它满足您的标准,即您的更新语句始终在“where”子句中包含列 col_3。


推荐阅读