Oracle遗留表没有很好的PK:如何hibernate?
我在Oracle数据库中有遗留表,我想通过Hibernate从Java应用程序访问。 问题是:表没有好的主键。 例如,表格看起来像这样:
create table employee ( first_name varchar(64) not null, last_name varchar(64) not null, hired_at date, department varchar(64) ); create unique index emp_uidx on employee (firstname, lastname, hired_at);
原始设计者决定使用hired_at
列作为状态字段,认为数据库永远不需要区分公司外部的John Smiths,但可以通过hired_at日期识别具有相同名称的员工。 显然,这会创建一个部分可空和可修改的主键。 由于数据库不允许将其作为主键,因此他使用了唯一索引。
现在,如果我尝试为此编写一个Hibernate映射,我可以想出这样的东西:
这适用于读取数据,但是当我创建仅在其hiredAt日期不同的新条目时,我会遇到org.hibernate.NonUniqueObjectExceptions。 或者,我可能会考虑Oracle的ROWIDfunction:
这对于读取数据也很好。 但显然,你不能坚持新的对象,因为Hibernate现在抛出一个org.hibernate.exception.SQLGrammarException:在尝试存储实体时无法获得下一个序列值。
显而易见的方法是通过代理键。 然而,这需要更改数据库模式,这将我们带回到“遗留”的东西。
我在俯瞰什么? 有没有办法让Hibernate与Oracle的ROWID合作,可能使用不同的生成器? 或者有没有办法让第一个想法发挥作用,也许有聪明的DAO可以驱逐和重新加载实体,并隐藏应用程序的复杂性? 或者我应该寻找Hibernate的替代方案,Ibatis可能吗?
您不希望将ROWID
用作主键,因为它不能保证在行的生命周期内保持稳定。
添加合成密钥是最好的选择。 使用触发器使用序列值填充列。
您对遗留方面有点模糊,因此很难确定其含义是什么。 添加列会破坏任何未明确列出目标列的insert语句。 它也可能会破坏任何SELECT *
查询(除非它们选择使用%ROWTYPE
关键字声明的变量。但是你不必更改任何其他应用程序,因此它使用新的主键而不是现有的列 – 除非你真的想要至。
我会添加一个带有后备序列的代理键。 它不会改变任何遗留语义,Hibernate会满足。
只是好奇 – 如果索引有姓名和雇佣日期,为什么你的复合键不包括雇用日期? 我原本希望在复合键中看到索引中的所有字段。
- Spring / Hibernate如何访问私有成员?
- 为什么在从jndi.properties注入后在JNDI中找不到数据源?
- 默认值不在hibernate状态下工作
- JPA SQL Server没有JDBC类型的Dialect映射:-9
- java.lang.ClassNotFoundException:javax.persistence.NamedStoredProcedureQuery – Hibernate错误
- 我可以让Hibernate通过工厂方法创建一个对象吗?
- 在hibernate / jpa最佳实践问题中将分离的或新的实体与现有实体合并
- oracle.jdbc.driver.T4CTTIrxd.readBitVector上的java.lang.ArrayIndexOutOfBoundsException(T4CTTIrxd.java:135)
- 抢先并优雅地检查org.hibernate.Session是否仍然连接(通过c3p0)