官网上给的例子是用的ApacheDerby进行的数据库操作,在这里咱们用mysql。
而且官网上的例子,onetomany,manytoone混着用,感觉如果纯看的话,得花费很多时间
去理解,所以这里咱们就一个一个单独讲解。
上篇文章简单介绍了:@Entity和@id以及@Column这些注解的使用。
这篇文章,我们就来讲解EclipseLink的映射关系之一-----oneToOne
其实一对一的关系,在数据库中的表示有很多种:
1、两个实体可以合成一个数据库;
2、可以是两个数据库表但是有外键关联。
3、也可以是两个数据库表,一个外键关系表。
下面咱们就来一一说明这三种情况怎么表示。
第一种,两个实体,但是对应一个数据库表
这种情况下用到了注解:@Embedded
在一个实体中,被标注上@Embedded的属性的实体,在形成数据库表的时候
是可以嵌入到这个实体表中的。
比如员工和家庭住址,是一对一的情况,我们把家庭住址实体放入到员工实体里面去,
就可以生成一个数据表。
员工实体如下:
package model;
import javax.persistence.Column; import javax.persistence.Embedded; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table;
@Entity @Table(name="Employee") public class Employee {
@Id @Column(name="id") private int id; @Column(name="name") private String name; @Column(name="salary") private long salary;
@Embedded privateFamilyAddressfamilyAddress;
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public long getSalary() { return salary; }
public void setSalary(long salary) { this.salary = salary; }
public Address getFamilyAddress() { returnfamilyAddress; }
public void setFamilyAddress(FamilyAddressfamilyAddress) { this.familyAddress=familyAddress; }
} |
地址实体如下:
package model;
import javax.persistence.Column; import javax.persistence.Embeddable;
@Embeddable public classFamilyAddress {
@Column(name="street") private String street; @Column(name="city") private String city; @Column(name="state") private String state; @Column(name="zip_code") private String zip;
public String getStreet() { return street; } public void setStreet(String street) { this.street = street; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } public String getState() { return state; } public void setState(String state) { this.state = state; } public String getZip() { return zip; } public void setZip(String zip) { this.zip = zip; }
} |
然后不要忘了修改xml文件中的运行类,不然会报错:“is not a known entity type”
如下:
<?xml version="1.0" encoding="UTF-8"?> <persistence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd" version="2.0" xmlns="http://java.sun.com/xml/ns/persistence"> <persistence-unit name="EmployeeService" transaction-type="RESOURCE_LOCAL"> <!-- <class>model.PersonInformation</class> --> <!-- <class>model.Person</class> --> <class>model.Employee</class> <properties> <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" /> <property name="javax.persistence.jdbc.url" value="jdbc:mysql://192.168.81.129:3306/simpleDb" /> <property name="javax.persistence.jdbc.user" value="root" /> <property name="javax.persistence.jdbc.password" value="root" />
<!-- EclipseLink should create the database schema automatically --> <property name="eclipselink.ddl-generation" value="create-tables" /> <property name="eclipselink.ddl-generation.output-mode" value="database" /> </properties> </persistence-unit> </persistence> |
测试方法如下:
package main;
import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence;
import model.FamilyAddress; import model.Employee;
public class EmployeeTest { private static final String PERSISTENCE_UNIT_NAME = "EmployeeService"; private static EntityManagerFactory factory;
public static void main(String[] args) { factory = Persistence.createEntityManagerFactory( PERSISTENCE_UNIT_NAME); EntityManager em = factory.createEntityManager(); //保证事务 em.getTransaction().begin(); Employee employee =new Employee(); employee.setName("David"); employee.setSalary(26000);
Address address =new Address(); address.setCity("beijing"); address.setState("stand_by"); address.setStreet("hutong"); address.setZip("1523647"); employee.setFamilyAddress(familyAddress); em.persist(employee); em.getTransaction().commit(); em.close(); } } |
运行后的结果如下:
第二种:形成有外键关系的两个数据表
员工表实体
package model;
import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.OneToOne; import javax.persistence.Table;
@Entity @Table(name="Employee2") public class Employee2 {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name="id") private int id; @Column(name="name") private String name; @Column(name="salary") private long salary; @OneToOne(cascade=CascadeType.ALL)//cascade表示他们的级联关系 .保证测试类中的em.persist方法保存的是两个对象实体,而不是知识员工实体 //不用显式的保存地址实体 @JoinColumn(name="address_id")// @JoinColumn里面指定了Employee表里引 用到Address时关联的名字是什么 private FamilyAddress2 familyAddress2; public int getId() { return id; }
public void setId(int id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public long getSalary() { return salary; }
public void setSalary(long salary) { this.salary = salary; }
public Address2 getAddress2() { return address2; }
public void setAddress2(Address2 address2) { this.address2 = address2; } public Employee2() {}
public Employee2(int id) { this.id = id; }
} |
地址表实体
package model;
import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table;
@Entity @Table(name="FamilyAddress2") public class FamilyAddress2 {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name="id") private int id;
@Column(name="street") private String street; @Column(name="city") private String city; @Column(name="state") private String state; @Column(name="zip_code") private String zip;
public int getId() { return id; } public void setId(int id) { this.id = id; } public String getStreet() { return street; } public void setStreet(String street) { this.street = street; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } public String getState() { return state; } public void setState(String state) { this.state = state; } public String getZip() { return zip; } public void setZip(String zip) { this.zip = zip; }
} |
同样不要忘了改xml,因为这次要创建两个表,所以得添加两个表的model到xml中。
xml的<class>的内容:需要创建的数据表的表对应的实体名
<?xml version="1.0" encoding="UTF-8"?> <persistence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd" version="2.0" xmlns="http://java.sun.com/xml/ns/persistence"> <persistence-unit name="EmployeeService" transaction-type="RESOURCE_LOCAL"> <!-- <class>model.PersonInformation</class> --> <!-- <class>model.Person</class> --> <class>model.Employee2</class> <class>model.FamilyAddress2</class> <properties> <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" /> <property name="javax.persistence.jdbc.url" value="jdbc:mysql://192.168.81.129:3306/simpleDb" /> <property name="javax.persistence.jdbc.user" value="root" /> <property name="javax.persistence.jdbc.password" value="root" />
<!-- EclipseLink should create the database schema automatically --> <property name="eclipselink.ddl-generation" value="create-tables" /> <property name="eclipselink.ddl-generation.output-mode" value="database" /> </properties> </persistence-unit> </persistence> |
测试类,如下:
因为员工类中已经设置了@OneToOne(cascade=CascadeType.ALL)
所以,保存的时候不用写em.persist(familyAddress2 ),
只用写保存员工实体就可以了。
package main;
import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence;
import model.FamilyAddress2 ; import model.Employee2;
public class EmployeeTest { private static final String PERSISTENCE_UNIT_NAME = "EmployeeService"; private static EntityManagerFactory factory;
public static void main(String[] args) { factory = Persistence.createEntityManagerFactory( PERSISTENCE_UNIT_NAME); EntityManager em = factory.createEntityManager(); //保证事务 em.getTransaction().begin(); Employee2 employee2 =new Employee2(); employee2.setName("David"); employee2.setSalary(26000);
FamilyAddress2 address2 =new FamilyAddress2(); address2.setCity("beijing"); address2.setState("stand_by"); address2.setStreet("hutong"); address2.setZip("1523647"); employee2.setFamilyAddress2(address2);
em.persist(employee2); em.getTransaction().commit(); em.close(); } } |
运行后的结果如下:
可以看出两个表的外键连接上了。
第三种,两个实体表生成两个数据表,外键独立一个表
此方法很简单,就把上面例子中的employee实体中的FamilyAddress属性上加上注解
@JoinTable和@OneToOne(cascade=CascadeType.ALL) 就可以了。
具体的employee实体如下:
package model;
import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinTable; import javax.persistence.OneToOne; import javax.persistence.Table;
@Entity @Table(name="Employee2") public class Employee2 {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name="id") private int id; @Column(name="name") private String name; @Column(name="salary") private long salary;
/*@OneToOne(cascade=CascadeType.ALL) //cascade表示他们的级联关系 . 保证测试类中的em.persist方法保存的是两个对象实体,而不是知识员工实体 //不用显式的保存地址实体 @JoinColumn(name="address_id") // @JoinColumn里面指定了Employee表里引用到Address时关联的名字是什么*/ @OneToOne(cascade=CascadeType.ALL) @JoinTable(name="employee_address",joinColumns=@JoinColumn(name="address_id"), inverseJoinColumns=@JoinColumn(name="employee_id")) //外键关系表,表名为employee_address,字段分别为address_id和employee_id //如果不写joinColumns和inverseJoinColumns,默认生成的字段名是 //两个单独数据表的"表名_id" private FamilyAddress2 familyAddress2;
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public long getSalary() { return salary; }
public void setSalary(long salary) { this.salary = salary; }
public FamilyAddress2 getFamilyAddress2() { return familyAddress2; }
public void setFamilyAddress2(FamilyAddress2 familyAddress2) { this.familyAddress2 = familyAddress2; }
public Employee2() {}
public Employee2(int id) { this.id = id; }
} |
小总:
至此,讲到了几种注解:@Embedded和@OneToOne和@JoinColumn和@JoinTable。