JPA中双向一对多(双向多对一)关联关系
示例:
1.Department实体类
/**
* 单向一对多的配置,在一方Department中,使用List来存储多方Employee
* @author boge
*/
@Entity
public class Department {
private Integer deptId;
private String deptName;
private String deptManager;
private List<Employee> emps = new ArrayList();
/**
* 单向一对多的配置,在一方Department中,使用List来存储多方Employee
* 需要通过注解来配置
* 只使用OneToMany描述,不够清楚,可能会认为这个关系是多对多,会产生一个中间表
* 还需要通过一个注解,来表示外键列
*
* 设置级联操作:
* 默认是置空
* CascadeType.REMOVE(级联删除)
CascadeType.REFRESH(级联刷新)
CascadeType.MERGE(级联更新)
fetch:指定抓取策略,默认是LAZY,懒加载
如果修改为EAGER,则表示立刻加载,使用left join进行查询
(cascade=CascadeType.REMOVE,fetch=FetchType.EAGER)
mappedBy="dept":来表示,一方放弃维护关联关系,而是交给多方来维护,mappedBy指定一方在多方中的
成员属性名称
*/
@OneToMany(mappedBy="dept")
// @JoinColumn(name="deptId") 放弃关联关系的维护
public List<Employee> getEmps() {
return emps;
}
public void setEmps(List<Employee> emps) {
this.emps = emps;
}
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
public Integer getDeptId() {
return deptId;
}
public void setDeptId(Integer deptId) {
this.deptId = deptId;
}
public String getDeptName() {
return deptName;
}
public void setDeptName(String deptName) {
this.deptName = deptName;
}
public String getDeptManager() {
return deptManager;
}
public void setDeptManager(String deptManager) {
this.deptManager = deptManager;
}
@Override
public String toString() {
return "Department [deptId=" + deptId + ", deptName=" + deptName + ", deptManager=" + deptManager + "]";
}
public Department(Integer deptId, String deptName, String deptManager) {
super();
this.deptId = deptId;
this.deptName = deptName;
this.deptManager = deptManager;
}
public Department() {
super();
}
}
2.Employee实体类
/**
* 完成,单向一对多的配置 在一方中,进行配置 部门(一) 员工(多)
*
* @author boge
*
*/
@Table(name = "emp")
@Entity
public class Employee {
private Integer empId;
private String userName;
private Integer age;
private String address;
private String gender;
private Department dept;
@ManyToOne
@JoinColumn(name="deptId")//指定在多方表中的外键列名称
public Department getDept() {
return dept;
}
public void setDept(Department dept) {
this.dept = dept;
}
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
public Integer getEmpId() {
return empId;
}
public void setEmpId(Integer empId) {
this.empId = empId;
}
@Column(name = "user_name")
@Basic() // optional=false userName字段,不能为null
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
/**
* 添加@Transient表示,忽略该属性对应的字段,将来就不会针对该属性进行映射 表中也不会有该字段
* 但是要注意:千万不要导错包,是:javax.persistences
* @return
*/
// @Transient
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
@Override
public String toString() {
return "Employee [empId=" + empId + ", userName=" + userName + ", age=" + age + ", address=" + address
+ ", gender=" + gender + "]";
}
public Employee(Integer empId, String userName, Integer age, String address, String gender) {
super();
this.empId = empId;
this.userName = userName;
this.age = age;
this.address = address;
this.gender = gender;
}
public Employee() {
super();
}
}
3.测试类
/**
* 测试双向一对多,和多对一的测试
* 得出一个结论:
* 在演示,同时保存多方和一方数据的案例中,发现,由多方维护关联关系,只发送两条insert语句
* 由双方维护、一方维护,则发送两条insert、1条update
* 经过比较,我们应该优先采用多方来维护关联关系
* 解决方案:在配置一方的时候,配置一方,让一方放弃关联关系的维护!
* @author boge
*/
public class OneOrManyTest {
EntityManagerFactory emf;
EntityManager em;
EntityTransaction transaction;
// 演示一方维护关联关系的情况;
@Test
public void test2(){
Department dept1 = new Department(null, "研发部", "老虎");
Employee emp1 = new Employee(null, "小白", 18, "昆明", "男");
//维护关联关系,一方、多方,都可以维护关联关系
List<Employee> emps = dept1.getEmps();
emps.add(emp1);
em.persist(dept1);
em.persist(emp1);
}
// 演示多方维护关联关系的情况;
@Test
public void test3(){
Department dept1 = new Department(null, "研发部", "老虎");
Employee emp1 = new Employee(null, "小白", 18, "昆明", "男");
//多方emp维护关联关系
emp1.setDept(dept1);
em.persist(dept1);
em.persist(emp1);
}
// 演示一方放弃维护关联关系的情况;
/*
* 演示双方维护关联关系的情况;
* 演示,同时保存多方和一方的数据
* 得出一个结论:无论是一方、多方、双方同时维护关联关系,总之,都是可以成功的
*/
@Test
public void test1(){
Department dept1 = new Department(null, "研发部", "老虎");
Employee emp1 = new Employee(null, "小白", 18, "昆明", "男");
//维护关联关系,一方、多方,都可以维护关联关系
List<Employee> emps = dept1.getEmps();
emps.add(emp1);
//多方emp维护关联关系
emp1.setDept(dept1);
em.persist(dept1);
em.persist(emp1);
}
@Before
public void before() {
// 1、获取EntityMangerFactory
emf = Persistence.createEntityManagerFactory("jpa-02");
// 2、获取EntityManger
// 重点对象,所有增删改查操作,都是通过它的方法进行的
em = emf.createEntityManager();
transaction = em.getTransaction();
transaction.begin();
}
@After
public void after(){
transaction.commit();
em.close();
emf.close();
}
}
4.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
xmlns="http://java.sun.com/xml/ns/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">
<!-- RESOURCE_LOCAL:开启本地事务的支持 -->
<persistence-unit name="jpa-02" transaction-type="RESOURCE_LOCAL">
<!-- 添加底层实现的支持 ,如,配置HIbernate对于JPA的支持 -->
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<!-- 映射的实体类 -->
<class>
com.kmu.entity.Department
</class>
<class>
com.kmu.entity.Employee
</class>
<properties>
<!-- 配置数据库连接信息 -->
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/jpa" />
<property name="javax.persistence.jdbc.user" value="root" />
<property name="javax.persistence.jdbc.password" value="root" />
<!-- 配置Hibernate框架需要的部分数据 -->
<!-- hibernate.format_sql:格式化sql,将来,程序运行时,会将运行的一些 信息,打印在控制台,如执行的sql语句打印在控制台。
hibernate.show_sql:在日志中,显示执行的mysql语句 hibernate.hbm2ddl.auto:自动见表、更新表结构的操作。
update:通过该配置选项,可以自动根据实体类,生成mysql中的数据表。 none:则不会自动生成表,而是需要你手动亲自在mysql中创建一个与java类映射的表。 -->
<property name="hibernate.format_sql" value="true" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.hbm2ddl.auto" value="update" />
</properties>
</persistence-unit>
</persistence>