使用Hibernate,我有一个Company
和Address
的{{1}}关系。
我正在使用Hibernate来填充表格(所以这是通过代码),我没有问题检索OneToOne
并且它是Company
但是如果我清空表Address
和Company
然后将一个条目(插入到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);
答案 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从数据库序列中生成它们,这个问题就会消失。