spring Hibernate updatable = false UUID字段已更新

8oomwypt  于 2023-10-15  发布在  Spring
关注(0)|答案(3)|浏览(150)

我正在使用Spring Data JPA和Hibernate,并且在@Column注解上遇到了updatable=false属性的问题。
我为所有@Entity对象创建了一个基类,并使用UUID定义如下:

@MappedSuperclass
@Getter @Setter @EqualsAndHashCode(of= {"uuid"})
public abstract class AbstractEntity implements Persistable<Long> {

    @Id
    @GeneratedValue(strategy = AUTO)
    @Column(unique = true, updatable = false)
    private Long id;

    @Column(unique = true, updatable = false)
    private UUID uuid = UUID.randomUUID();

}

注意updatable = false注解。
为了验证UUID字段实际上是不可更新的,我写了这个测试:

@Test
public void testChangeUUID() {

    User user = userRepo.findOne(1L);

    assertNotNull(user);
    assertEquals(USER_UUID, user.getUuid().toString());

    final UUID newUuid = UUID.randomUUID();

    user.setUuid(newUuid);

    user = userRepo.save(user);

    assertEquals(newUuid, user.getUuid());

    User user2 = userRepo.findOne(1L);
    assertNotNull(user2);
    assertEquals("UUID should not have changed", USER_UUID, user2.getUuid().toString());
}

我实际上希望在调用userRepo.save(user)时抛出一个异常,但这并没有发生。相反,最终的assertEquals()失败了,这意味着UUID实际上正在更新。
这是预期的行为吗?有什么方法可以防止UUID被更改吗?

cig3rfwq

cig3rfwq1#

我遇到了一个类似的问题,我想使用@Column(updatable = false),然后仅在特定情况下手动更新字段。
作为解决方案之一,您可以使用注解,然后在调用userRepo.findOne(1 L)之前尝试清除会话。这将如上所述的工作。
我不太喜欢清除和使用更多的查询,所以我的解决方案是-重写你的保存方法,不使用Hibernate,而是在你的仓库中使用一个原生的SQL脚本。注解只影响Hibernate,但对本机脚本没有影响。Imo,一个更好的方法来做到这一点。

vs91vp4v

vs91vp4v2#

根据documentationupdatable属性决定该列是否是update语句的一部分。这意味着Hibernate在向数据库发送更新时会忽略它。因此,内存中状态和数据库状态将不同。
要验证这一点,请尝试在调用User user2 = userRepo.findOne(1L)之前清除会话(逐出

zzwlnbp8

zzwlnbp83#

虽然最初的问题已经得到了回答,但我想强调一个重要的观点对于那些刚接触Hibernate的人,因为它可能有助于避免一些混乱。
@Column注解的javadoc of Hibernate 5.4表示其可选元素Updatable:
(可选)该列是否包含在持久性提供程序生成的SQL UPDATE语句
如果你使用HQL或使用CriteriaUpdate对你用@Column(updatable = false)标注的字段发出更新语句,你的更新语句将被执行
当你使用Hibernate的update或JPA的merge方法时,@Column(updatable = false)可以工作。
不会抛出任何异常(与例如:@Column(nullable= false),因为它创建了一个约束...),但是生成的更新语句将不包括标记的字段。
要了解更多信息,您必须熟悉JPA的实体生命周期状态和管理它们的方法,如下图所示。
以及我强烈建议阅读这article的详细解释,* 是所附图片的来源 *。

相关问题