初始化oneToOne Relation的SQL表

时间:2014-03-04 23:25:29

标签: hibernate

使用Hibernate,我有一个CompanyAddress的{​​{1}}关系。

我正在使用Hibernate来填充表格(所以这是通过代码),我没有问题检索OneToOne并且它是Company

但是如果我清空表AddressCompany然后将一个条目(插入到sql中)添加到Address表中,其id = 1并在该地址中添加一个条目id为1的表,在尝试获取Company时,出现以下错误:

Person

SEVERE: Servlet.service() for servlet [appServlet] in context with path [/frmk] threw exception [Request processing failed; nested exception is org.hibernate.HibernateException: More than one row with the given identifier was found: 1, for class: com.snj.frmk.core.orga.model.Address] with root cause org.hibernate.HibernateException: More than one row with the given identifier was found: 1, for class: com.snj.frmk.core.orga.model.Address Address都继承自Company,它本身继承自另一个对象。 我在下面提供了一些不完整的示例代码。

Person

我还包含了SQL以将值插入@Entity @Inheritance(strategy=InheritanceType.TABLE_PER_CLASS) public abstract class SnjObject implements Serializable { private static final long serialVersionUID = 3051191273679675478L; @GeneratedValue(strategy = GenerationType.TABLE) @Id public Long id; } @Entity @Inheritance(strategy=InheritanceType.TABLE_PER_CLASS) public abstract class Person extends SnjObject { private static final long serialVersionUID = -1782694326465928216L; @OneToOne(mappedBy="person", cascade=CascadeType.ALL) private Address adr1; } @Entity @Table(name = "SNJ_COMPANY") public class Company extends Person{ private static final long serialVersionUID = -5591910647468433471L; } @Entity @Table(name = "SNJ_ADDRESS") public class Address { @Id @Column(name="ID") @GeneratedValue(generator = "gen") @GenericGenerator(name = "gen", strategy = "foreign", parameters = @Parameter(name = "property", value = "person")) private Long id; } Company表: Address

INSERT INTO snj_company (ID,CODE_REFERENCE,NAME,SIZE,OFFICE_PHONE,FAX,MOBILE_PHONE,EMAIL,creatorId) VALUES (1,'FR00101','TEST',0,'0948878398', '', '', '' ,1);

1 个答案:

答案 0 :(得分:0)

好的,如果要生成ID列,并且没有任何其他要求,则应在每个ID字段上使用数据库序列生成器。如果您在create-drop模式下使用休眠,那么您将没有问题,因为Hibernate将创建序列并在插入新记录时自动使用它来填充您的ID字段。我会举一个例子来说明这个:

@Entity
@Table(name = "SNJ_ADDRESS")
public class Address {
    @Id
    @Column(name="ID")        
    @GeneratedValue(generator = "contactSequence") //specifies what generator you want
    @SequenceGenerator(name = "contactSequence", sequenceName = "CONTACT_SEQ") 
    /*Specifies that you want to use a database Sequence as your generator and the 
    name of that sequence. If it doesn't exist, Hibernate will create it.*/
    private Long ID.

如果您要使用序列设置另一个ID字段,只需提供不同的sequenceName,Hibernate将为您创建一个新的序列。 你可以发布用于清除表格然后插入的代码吗?你还使用哪个版本的Hibernate?我将假设您正在使用基于注释的事务配置的Hibernate 4。

有些人没有意识到(如果你没有仔细阅读,那么文档中没有明确说明)是Hibernate在事务结束和会话之前不会对数据库进行任何更改已关闭。

上面描述的问题是因为在删除之后没有提交会话(最可能的情况),因此当您尝试保存另一个地址时,它会检测到主键冲突并拒绝保存。否则它将保存数据,当您尝试检索Person时,Hibernate会发现两行具有相同的ID并停止,因为它不知道您想要哪一行。

TL; DR不要直接操作或设置你的ID,让Hibernate从数据库序列中生成它们,这个问题就会消失。