gpt4 book ai didi

java - 没有主键和可为空字段的 Hibernate 实体

转载 作者:行者123 更新时间:2023-12-01 18:34:46 24 4
gpt4 key购买 nike

我见过类似的案例,但并不是这种困难的精确组合,而且我见过的任何解决方案都不起作用。我正在将一些库从 Spring-data 1.X 和 Hibernate 4.X 升级到 Spring-data 2.X 和 Hibernate 5.X,我认为这与这两个框架之一有关......可能是 Hibernate,变得越来越多对版本之间的 ID 更加挑剔,因为在多个字段上使用 @Id 似乎是可行的。我想如果我需要的话,我可以将 Hibernate 4 与 Spring-data 2、QueryDSL 4 一起使用吗?

  1. 我有一个基于具有 2 个字段的表的 Hibernate @Entity。
  2. 第一个字段不是唯一的,因此它不可能是 PK。
  3. 另一个字段可为空,因此它不能是 PK。
  4. 我在生产中使用 Oracle。
  5. 我正在使用 sql.syntax_ora=true 测试 HSQLDB

解决方案#1:两个字段的复合键。
失败 #1:同时使用 @EmbeddedId/@Embedded 和 @IdClass 解决方案,当可空字段为 null 时,Hibernate 完全放弃该对象并返回一个简单的 null,而不是带有 null 字段的对象。

解决方案#2:选择伪列而不是 IE @Column(name = "ROWID")
失败 #2:Hibernate 无法识别这不是一个真正的列,并尝试在添加表别名时选择它,但由于找不到该字段而失败。

我还尝试添加括号“ROWID()”,但效果相同。

解决方案#3:使用@Formula尝试注入(inject)片段而不是假@Column
失败#3:我认为这不是一个允许的组合,只会导致错误,指出 identifier property [] can not contains Formula []

解决方案#4:使用自定义方言添加“ROWID”作为关键字,而不是依赖将其注册为函数
失败#4:与解决方案#2 没有显着差异

我并没有真正搞乱用于此表上的 .findAll() 的 JpaRepository,但在大多数情况下,我不太确定它应该是什么。如果 ID 设置为 @IdClass,像 #1 这样的东西会更好吗?

我在这里完全不知所措。它实际上是一个我无法真正搞乱的遗留数据库。我需要重写生成的 SQL 来选择对象、具有部分可为空的复合 id 的函数、具有非唯一 ID 的函数,否则使用非持久字段作为 id...rowid/rownum/某种哈希。 ..还有其他一些我没有看到的选项吗?这个@Entity将在哪里使用其明显无法识别的字段组合?

在用作 ID 的一部分时,是否有某种方法可以将第二列中的 null 值视为另一个值以防止失败 #1,但仍然允许它在对象本身中为 null?

        @Bean
public EntityManagerFactory entityManagerFactory() {
final LocalContainerEntityManagerFactoryBean bean = new LocalContainerEntityManagerFactoryBean();
//bean.setJpaDialect(new HibernateJpaDialect());
bean.setDataSource(dataSource());
bean.setJpaVendorAdapter(jpaVendorAdapter());
bean.setPackagesToScan("com.company.core.domain");

final Properties jpaProperties = new Properties();
//jpaProperties.setProperty("javax.persistence.schema-generation.database.action", "create");
jpaProperties.setProperty("hibernate.show_sql", "true");
jpaProperties.setProperty("hibernate.dialect", "org.hibernate.dialect.Oracle12cDialect");

bean.setJpaProperties(jpaProperties);
bean.afterPropertiesSet();

return bean.getObject();
}
@Bean
public DataSource dataSource() {
final String uuid = UUID.randomUUID().toString();
return new EmbeddedDatabaseBuilder().addScript("schema.sql").setName(uuid + ";sql.syntax_ora=true;hsqldb.sqllog=3").build();
}

最佳答案

我在这里所做的最好的事情就是调整我的 @Entity 以包含 ROWID 伪列。不幸的是,虽然 HSQLDB 支持某种 ROWNUM,但它仅在不以 tableAlias 为前缀时才有效,而 Hibernate 始终会这样做。而且它根本不支持ROWID。但是在 Oracle 中工作的 ROWID 在 HSQLDB 中不起作用,所以技巧是手动设置我的嵌入式 HSQLDB,将 ROWID 列设置为自动增量,并附上大量注释,说明这将在 Oracle 上工作(TM),而无需修改模型.

是的,正确的答案是在Oracle中的表中添加一个真正的PK。或者,使用嵌入式 Oracle(通过测试容器进行 IE dockerized 实例)也可以正常工作,但许可不是特别适合......或者我是这么被告知的。但是,尽管在测试中故意使用与运行时不同的模式是很老套的,但它确实有效,并且在多个地方都有详细记录,因此没有人会对任何事情感到惊讶。

或者...你知道...只是不要升级 Hibernate。这个实体多年来一直潜伏在 Hibernate 旧版本中的一个错误中,其中 Mapper 接受多个 @Id 字段作为复合键,但 Loader 无法将 null 字段识别为键的一部分,因此它允许对象重新水合。/p>

关于java - 没有主键和可为空字段的 Hibernate 实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60083393/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com