JPA中双向一对多(双向多对一)关联关系 【3】

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>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值