JPA实业关联(hibernate实现)

JPA实体关联(hibernate实现)

1.一对一(OneToOne)

一对一关系映射分为单向一对一和多向一对一。在配置关系时必须确立控制方和被控制方。单向和双向的区别为看主控方和被控方两边是否都配置了@OneToOne,如果都有为双向一对一,反之为单向。

 

双向一对一关联有两条规则:
@JoinColumn必须配置在关系维护方即主控方上面;
mappedBy属性配置在被维护方的@OneToOne中,并且只能指向主控方,名称定义为主控方中包含的被控方引用名称。

 

/**
 * person属于关系维护方
 *
 */
@Entity
@Table(name="t_one_person")
public class Person {

	@Id
	@GeneratedValue(strategy=GenerationType.AUTO)
	private Integer id;
	
	@Column(length=10,nullable=false)
	private String name;
	
	/*
	 * 双向关系一对一
	 * @JoinColumn在JPA中成为连接列,目的是在Person实体表中生成一个IDCard实体
	 * 的外键关系.外键列明可以用name指定,如果不指定,默认为目标实体对象名和_ID组合.
	 * 拥有@JoinColumn的是关系维护方.
	 */
	@OneToOne(cascade=CascadeType.ALL,optional=false)
	@JoinColumn(name="idCard_id")
	private IDCard idCard;
	//省略get/set方法...
}
	

 

 

 

/**
 * 为关系被维持方
 *
 */
@Entity
@Table(name="t_one_idcard")
public class IDCard {

	@Id
	@GeneratedValue(strategy=GenerationType.AUTO)
	private Integer id;
	
	@Column(length=18,nullable=false)
	private String cadno;
	
	/*
	 * 双向关联:一对一
	 * mappedBy:反转.出现该属性的是关系被维护方,所指向的则是关系维护方.
	 */
	@OneToOne(cascade={CascadeType.PERSIST,CascadeType.REFRESH,CascadeType.MERGE},mappedBy="idCard",optional=false,fetch=FetchType.EAGER)
	private Person person;
       //省略get/set方法...
}

 

 

Junit测试:

 

public class TestJPA {

	EntityManagerFactory emf = null;

	@Before
	public void before() {
		emf = Persistence.createEntityManagerFactory("myJPA");
	}

	@Test
	public void add() {
		Person person = new Person();
		IDCard idCard = new IDCard();
		person.setName("老李");
		idCard.setCadno("111111111111111111");
		idCard.setPerson(person);
		person.setIdCard(idCard);

		EntityManager em = emf.createEntityManager();
		em.getTransaction().begin();

		em.persist(person);
		em.getTransaction().commit();
		em.close();
	}

	/**
	 * 关闭EntityManagerFactory
	 */
	@After
	public void after() {
		if (null != emf) {
			emf.close();
		}
	}
}

 

 

2.一对多(OneToMany)

在JPA规范中:
1<--->m 多的一方位关系维护端,关系维护端负责外键记录的更新.关系被维护端是没有权利更新外键字段的.

 

/**
 *关系被维护方
 */
@Entity
@Table(name="t_order")
public class Order {

	@Id
	@Column(length=55)
	private String orderId;
	
	//总价钱
	@Column(nullable=false)
	private Float amount=0f;
	
	/*订单项.一对多
	 * CascadeType.MERGE :级联更新
	 * CascadeType.PERSIST:级联保存
	 * CascadeType.REFRESH: 级联刷新 refresh(),才会触发
	 * CascadeType.REMOVE:级联删除
	 * CascadeType.ALL:以上所有
	 * 
	 * FetchType.EAGER:立即加载 @OneToOne: 默认.
	 * FetchType.LAZY:懒加载. @OneToMany :默认.
	 * 
	 * mappedBy:关系反转.此处有orderItem关系维护端.
	 */
	@OneToMany(cascade={CascadeType.ALL},fetch=FetchType.LAZY,mappedBy="order")
	private Set<OrderItem> items=new HashSet<OrderItem>();
	//省略get/set方法...
}

 

/**
 * 
 *关系维护方
 *在JPA规范中:
 *  1<--->m 多的一方位关系维护端,关系维护端负责外键记录的更新.关系被维护端是没有权利更新外键字段的.
 */


@Entity
@Table(name="t_orderItem")
public class OrderItem {

	@Id
	@GeneratedValue(strategy=GenerationType.AUTO)
	private Integer id;
	
	@Column(length=40,nullable=false)
	private String productName;
	
	//销售价
	@Column(nullable=false)
	private Float sellPrice=0f;
	
	/*
	 * 订单.多对一
	 * optional=true :可选,对应数据库可以为null.
	 * @JoinColumn: 维护外键
	 */
	
	@ManyToOne(cascade={CascadeType.MERGE,CascadeType.REFRESH},fetch=FetchType.EAGER,optional=false)
	@JoinColumn(name="order_id")
	private Order order;
	//省略get/set方法..
}

 

 

Junit测试:

 

public class TestJPA {

	EntityManagerFactory emf = null;

	@Before
	public void before() {
		emf = Persistence.createEntityManagerFactory("myJPA");
	}
	
	@Test
	public void add(){
		OrderItem orderItem = new OrderItem();
		orderItem.setProductName("电脑");
		orderItem.setSellPrice(5000f);
		
		
		OrderItem orderItem1 = new OrderItem();
		orderItem1.setProductName("手机");
		orderItem1.setSellPrice(3000f);
		
		
		Order order=new Order();
		//订单项关联订单
		orderItem.setOrder(order);
		orderItem1.setOrder(order);
		
		
		order.setAmount(25.0f);
		order.setOrderId(UUID.randomUUID().toString());
		
		//订单关联订单项
		order.getItems().add(orderItem);
		order.getItems().add(orderItem1);
		
		
		EntityManager em = emf.createEntityManager();
		em.getTransaction().begin();
		em.persist(order);
		em.getTransaction().commit();
		em.close();
	}
	
	/**
	 * 关闭EntityManagerFactory
	 */
	@After
	public void after() {
		if (null != emf) {
			emf.close();
		}
	}
}

 

 

3.多对多(ManyToMany)

使用之间表,分为两个一对多

@Entity
@Table(name="t_many_student")
public class Student {

	@Id
	@GeneratedValue(strategy=GenerationType.AUTO)
	private Integer id;
	
	@Column(name="name",length=10,nullable=false)
	private String name;
	
	/* @JoinTable:中间表
	 * inverseJoinColumns:指定被维护端的外键定义,这里指向的是Teacher
	 * joinColumns:指定关系维护端的外键定义,这里指向的是student
	 */
	@ManyToMany(cascade=CascadeType.REFRESH)
	@JoinTable(name="student_teacher",inverseJoinColumns=@JoinColumn(name="teacher_ids"),joinColumns=@JoinColumn(name="student_ids"))
	private Set<Teacher> teachers=new HashSet<Teacher>();
	
	/**
	 * </pre>
	 * 添加老师和学生的关系
	 * </pre>
	 */
	public void addTeacher(Teacher teacher){
		this.teachers.add(teacher);
	}
	
	/**
	 * </pre>
	 * 解除老师和学生的关系
	 * </pre>
	 */
	public void removeTeacher(Teacher teacher){
		if(this.teachers.contains(teacher)){
			this.teachers.remove(teacher);
		}
	}
	//省略get/set方法...
}
@Entity
@Table(name="t_many_teacher")
public class Teacher {

	@Id
	@GeneratedValue(strategy=GenerationType.AUTO)
	private Integer id;
	
	@Column(name="name",length=10,nullable=false)
	private String name;
	
	@ManyToMany(cascade={CascadeType.REFRESH},fetch=FetchType.LAZY,mappedBy="teachers")
	private Set<Student> students=new HashSet<Student>();
        //省略get/set方法...

}

  Junit测试:

public class TestJPA {

	EntityManagerFactory emf = null;

	@Before
	public void before() {
		emf = Persistence.createEntityManagerFactory("myJPA");
	}
	
	/**
	 * </pre>
	 * 添加老师和学生
	 * </pre>
	 */
	
	@Test
	public void add(){
		Student student = new Student("学生");
		Teacher teacher=new Teacher("老师");
		EntityManager em = emf.createEntityManager();
		em.getTransaction().begin();
		em.persist(teacher);
		em.persist(student);
		em.getTransaction().commit();
		em.close();
	}
	
	/**
	 * </pre>
	 * 建立老师和学生的关系
	 * </pre>
	 */
	
	@Test
	public void buildTS(){
		EntityManager em = emf.createEntityManager();
		em.getTransaction().begin();
		Student student = em.find(Student.class, 1);
		student.addTeacher(em.getReference(Teacher.class, 1));
		em.persist(student);
		em.getTransaction().commit();
		em.close();
	}
	
	/**
	 * </pre>
	 * 解除老师和学生的关系
	 * </pre>
	 */
	
	@Test
	public void deleteTS(){
		EntityManager em = emf.createEntityManager();
		em.getTransaction().begin();
		Student student = em.find(Student.class, 1);
		student.removeTeacher(em.getReference(Teacher.class, 1));
		em.persist(student);
		em.getTransaction().commit();
		em.close();
	}
	
	/**
	 * </pre>
	 *删除老师
	 * </pre>
	 */
	
	@Test
	public void deleteTeacher(){
		EntityManager em = emf.createEntityManager();
		em.getTransaction().begin();
		Student student = em.find(Student.class, 1);
		Teacher teacher = em.getReference(Teacher.class, 1);
		//先解除老师和学生的关系
		student.removeTeacher(teacher);
		//然后在删除老师
		em.remove(teacher);
		em.getTransaction().commit();
		em.close();
	}
	
	/**
	 * </pre>
	 *删除学生
	 * </pre>
	 */
	
	@Test
	public void deleteStudent(){
		EntityManager em = emf.createEntityManager();
		em.getTransaction().begin();
		Student student = em.find(Student.class, 1);
		em.remove(student);//因为student是关系维护端,有权进行中间表进行修改,不需要解除关系.
		em.getTransaction().commit();
		em.close();
	}
	
	
	/**
	 * 关闭EntityManagerFactory
	 */
	@After
	public void after() {
		if (null != emf) {
			emf.close();
		}
	}
}

 

4.复合主键

/**
 * 复合主键必须要实现Serializable,无参构造,必须重写hashCode,equals.
 * @author HH
 *
 */
@Embeddable//用于实体里面的时候,告诉JPA实现产品只使用这个复合主键类的属性
public class AirLinePK implements Serializable{

	@Column(length=3)
	private String startCity;
	
	@Column(length=3)
	private String endCity;
	
        //省略get/set方法...
        //....
       //省略重写的hashCode和equals方法...
}

 

@Entity
public class AirLine {

	@EmbeddedId//专门用于复合主键类
	private AirLinePK id;
	
	@Column(length=20)
	private String name;

        //省略get/set方法..
}

 Junit测试:

public class TestJPA {

	EntityManagerFactory emf = null;

	@Before
	public void before() {
		emf = Persistence.createEntityManagerFactory("myJPA");
	}
	
	@Test
	public void add(){
		EntityManager em = emf.createEntityManager();
		em.getTransaction().begin();
		em.persist(new AirLine(new AirLinePK("PEK","SHA"),"北京飞上海"));
		em.getTransaction().commit();
		em.close();
	}

	/**
	 * 关闭EntityManagerFactory
	 */
	@After
	public void after() {
		if (null != emf) {
			emf.close();
		}
	}
}