代码之家  ›  专栏  ›  技术社区  ›  wallenborn

没有好pk的Oracle遗留表:如何休眠?

  •  7
  • wallenborn  · 技术社区  · 16 年前

    我有一个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 Smith,但具有相同名称的员工可以通过其雇用日期进行识别。显然,这会创建一个部分可以为空且可修改的主键。因为数据库不允许将它作为主键,所以他改为使用唯一索引。

    现在,如果我尝试为此编写Hibernate映射,我可以想出如下方法:

    <hibernate-mapping>
      <class name="com.snakeoil.personnel" table="employee">
        <composite-id class="com.snakeoil.personnel.EmpId" name="id">
          <key-property name="firstName" column="first_name" type="string"/>
          <key-property name="lastName" column="last_name" type="string"/>
        </composite-id>
        <property name="hiredAt" column="hired_at" type="date"/>
        <property name="department" type="string">
      </class>
    </hibernate-mapping>
    

    这适用于读取数据,但当我创建新条目时,它们的hiredat日期不同,我会遇到org.hibernate.nonuniqueobjectexceptions。或者,我可以考虑Oracle的rowid功能:

    <id column="ROWID" name="id" type="string">
       <generator class="native"/>
    </id>
    

    这对于读取数据也很有用。但显然,您不能持久化新对象,因为Hibernate现在抛出了org.hibernate.exception.sqlGrammareException:在尝试存储实体时无法获取下一个序列值。

    很明显,可以通过代理键来解决这个问题。然而,这将需要更改数据库模式,这将使我们回到“遗留”的事情上。

    我忽略了什么?有没有一种方法可以让Hibernate与Oracle的rowid合作,也许是使用不同的生成器?或者,是否有一种方法可以让第一个想法发挥作用,也许是使用聪明的DAO,它可以大量地驱逐和重新加载实体,并隐藏应用程序的复杂性?或者我应该找个替代冬眠的方法吗,伊巴提斯?

    2 回复  |  直到 16 年前
        1
  •  7
  •   APC    16 年前

    你不想用 ROWID 作为主键,因为它不能保证在一行的生命周期中是稳定的。

    添加合成密钥是最好的选择。使用触发器用序列值填充列。

    你在遗产方面有点含糊不清,所以很难确定它的含义是什么。添加列将中断任何未显式列出目标列的INSERT语句。它也可能打破任何 SELECT * 查询(除非它们选择到使用 %ROWTYPE 关键字。但您不必更改任何其他应用程序,因此它使用新的主键而不是现有的列—除非您真的想这样做。

        2
  •  5
  •   duffymo    16 年前

    我将添加一个带有支持序列的代理键。它不会改变任何遗留的语义,Hibernate会得到满足。

    只是好奇——如果索引有名字、姓氏和雇用日期,为什么复合键不包括雇用日期?我还希望看到复合键中索引中的所有字段。