您好我正在编写使用jpa和Hibernate 3.2版本将数据插入两个表的简单代码。我的注意事项是将Employee详细信息保存在两个表中,即Employee包含employeeId,这是主键,手动分配指定值和员工地址使用@onetoOne annotions在Employee表中共享主键employeeId。我喜欢这样的类
@Entity
@Table(name = "employee", catalog = "test", uniqueConstraints = {})
public class Employee implements java.io.Serializable {
// Fields
private Integer employeeid;
private String name;
private Employeeaddress employeeaddress;
// Constructors
/** default constructor */
public Employee() {
}
/** minimal constructor */
public Employee(Integer employeeid) {
this.employeeid = employeeid;
}
/** full constructor */
public Employee(Integer employeeid, String name) {
this.employeeid = employeeid;
this.name = name;
}
// Property accessors
@Id
@Column(name = "EMPLOYEEID", unique = true, nullable = false, insertable = true, updatable = true)
public Integer getEmployeeid() {
return this.employeeid;
}
public void setEmployeeid(Integer employeeid) {
this.employeeid = employeeid;
}
@Column(name = "NAME", unique = false, nullable = true, insertable = true, updatable = true, length = 45)
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
@OneToOne(mappedBy="employee")
@PrimaryKeyJoinColumn
public Employeeaddress getEmployeeaddress() {
return employeeaddress;
}
public void setEmployeeaddress(Employeeaddress employeeaddress) {
this.employeeaddress = employeeaddress;
}
}
@Entity
@Table(name = "employeeaddress", catalog = "test", uniqueConstraints = {})
public class Employeeaddress implements java.io.Serializable {
// Fields
private Integer employeeid;
private String address;
private Employee employee;
// Constructors
/** default constructor */
public Employeeaddress() {
}
/** minimal constructor */
public Employeeaddress(Integer employeeid) {
this.employeeid = employeeid;
}
/** full constructor */
public Employeeaddress(Integer employeeid, String address) {
this.employeeid = employeeid;
this.address = address;
}
// Property accessors
@Id
@Column(name = "EMPLOYEEID", unique = true, nullable = false, insertable = true, updatable = true)
public Integer getEmployeeid() {
return this.employeeid;
}
public void setEmployeeid(Integer employeeid) {
this.employeeid = employeeid;
}
@Column(name = "ADDRESS", unique = false, nullable = true, insertable = true, updatable = true, length = 45)
public String getAddress() {
return this.address;
}
public void setAddress(String address) {
this.address = address;
}
@OneToOne(mappedBy="employeeaddress")
@PrimaryKeyJoinColumn
public Employee getEmployee() {
return employee;
}
public void setEmployee(Employee employee) {
this.employee = employee;
}
}
我的主要课程是
public class EmployeeDao {
public static void main(String[] args) {
try{
AnnotationConfiguration cfg = new AnnotationConfiguration();
cfg.addAnnotatedClass(employeeforms.Employee.class);
cfg.addAnnotatedClass(employeeforms.Employeeaddress.class);
SessionFactory sessionFactory = cfg.buildSessionFactory();
Session session =sessionFactory.openSession();
Employee e = new Employee();
e.setEmployeeid(100872);
e.setName("sandeep");
Employeeaddress ed = new Employeeaddress();
ed.setAddress("Hyderabad");
e.setEmployeeaddress(ed);
session.save(e);
}catch (Exception e) {
e.printStackTrace();
}
}
}
当我运行我的主课时,我得到以下异常
java.lang.NullPointerException
at org.hibernate.cfg.OneToOneSecondPass.doSecondPass(OneToOneSecondPass.java:135)
at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1130)
at org.hibernate.cfg.AnnotationConfiguration.secondPassCompile(AnnotationConfiguration.java:296)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1286)
at employeeDao.EmployeeDao.main(EmployeeDao.java:16)
我的桌子是
CREATE TABLE employee (
EMPLOYEEID int(10) unsigned NOT NULL ,
NAME varchar(45) default '',
PRIMARY KEY (EMPLOYEEID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE employeeaddress (
EMPLOYEEID int(10) unsigned NOT NULL default '0',
ADDRESS varchar(45) default '',
PRIMARY KEY (EMPLOYEEID)
) ENGINE=InnoDB
DEFAULT CHARSET=latin1;
答案 0 :(得分:1)
你有(至少)三个问题。
第一个问题:你指定
@OneToOne(mappedBy="employee")
@PrimaryKeyJoinColumn
和
@OneToOne(mappedBy="employeeaddress")
@PrimaryKeyJoinColumn
这两个注释是矛盾的;如果设置了mappedBy
,则意味着映射信息位于另一侧。只有一方应定义映射(@PrimaryKeyJoinColumn)
,另一方应设置mappedBy
属性。
第二个问题:你指定
Employeeaddress ed = new Employeeaddress();
ed.setAddress("Hyderabad");
e.setEmployeeaddress(ed);
应初始化协会的双方。因此代码应该这样做:
e.setEmployeeaddress(ed);
ed.setEmployee(e);
Hibernate使用mappedBy not 设置的一侧来知道是否存在关联。
第三个问题:
您保存员工,但不保存地址。并且员工之间没有级联设置。
答案 1 :(得分:0)
基于these hibernate 3.6 docs,您的映射应如下所示:
@Entity
@Table(name = "employee", catalog = "test", uniqueConstraints = {})
public class Employee implements java.io.Serializable {
private Integer employeeid;
private Employeeaddress employeeaddress;
// other fields and constructors
@Id
@Column(name = "EMPLOYEEID", unique = true, nullable = false, insertable = true, updatable = true)
public Integer getEmployeeid() {
return this.employeeid;
}
public void setEmployeeid(Integer employeeid) {
this.employeeid = employeeid;
}
@OneToOne(mappedBy="employee")
public Employeeaddress getEmployeeaddress() {
return employeeaddress;
}
public void setEmployeeaddress(Employeeaddress employeeaddress) {
this.employeeaddress = employeeaddress;
}
}
@Entity
@Table(name = "employeeaddress", catalog = "test", uniqueConstraints = {})
public class Employeeaddress implements java.io.Serializable {
private Integer employeeid;
private Employee employee;
@Id
@Column(name = "EMPLOYEEID", unique = true, nullable = false, insertable = true, updatable = true)
public Integer getEmployeeid() {
return this.employeeid;
}
// EDIT: private setter for employeeid, id is set by setEmployee() but hibernate needs a setter to initialize the instance on load
private void setEmployeeid(Integer id) {
this.employeeid = id;
}
@OneToOne
@MapsId
public Employee getEmployee() {
return employee;
}
public void setEmployee(Employee employee) {
this.employee = employee;
}
}
编辑:
@MapsId
注释是在JPA 2.0中引入的(我认为自3.5以来在hibernate中实现)。如果您使用的是未实现JPA 2.0规范的较旧的hibernate版本,则可以为这样的两个实体映射相同的id(类Employee
保持不变):
@Entity
@Table(name = "employeeaddress", catalog = "test", uniqueConstraints = {})
public class Employeeaddress implements java.io.Serializable {
private Integer employeeid;
private Employee employee;
@Id
@GeneratedValue(generator = "anyName")
@GenericGenerator(name = "anyName", strategy = "foreign", parameters = { @Parameter(name = "property", value = "employee") })
@Column(name = "EMPLOYEEID", unique = true, nullable = false, insertable = true, updatable = true)
public Integer getEmployeeid() {
return this.employeeid;
}
// EDIT: private setter for employeeid, id is set by setEmployee() but hibernate needs a setter to initialize the instance on load
private void setEmployeeid(Integer id) {
this.employeeid = id;
}
@OneToOne
@PrimaryKeyJoinColumn
public Employee getEmployee() {
return employee;
}
public void setEmployee(Employee employee) {
this.employee = employee;
}
}
在保存关联的瞬态/分离Employeeaddress
实例或将类Employee
中的注释更改为级联保存之前,您还必须先保存瞬态/分离的Employee
实例:
@OneToOne(mappedBy="employee", cascade = CascadeType.SAVE_UPDATE)
public Employeeaddress getEmployeeaddress() {
return employeeaddress;
}