JPA一对多映射案例
程序员文章站
2022-04-23 15:45:38
...
班级表和学员资料表就是一对多的关系。一个班级有多个学员,一个学员属于某个班级。
班级和学员映射后的表结构如下:
班级表结构:
学员资料表结构:
需要的jar包和数据库连接配置不再说了,双向一对一案例已经说了
班级类BasClass.java
package com.jason.bean;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
/**
* one端
*
* 碰到many为末端的加载就是延迟加载,若one为末端则为立即加载,除了one-to-one。
*
* @author jason
*
*/
@Entity
@Table(name = "bas_class")
public class BasClass implements Serializable {
private static final long serialVersionUID = -4398577825279584033L;
private String claId;
private String claName;
private Set<StuInfo> items = new HashSet<StuInfo>();
public BasClass() {}
public BasClass(String claName) {
this.claName = claName;
}
// String类型不能用uuid,需要人为指定
@Id
@Column(length = 12)
public String getClaId() {
return claId;
}
public void setClaId(String claId) {
this.claId = claId;
}
@Column(nullable = false)
public String getClaName() {
return claName;
}
public void setClaName(String claName) {
this.claName = claName;
}
// @OneToMany(cascade={CascadeType.PERSIST,CascadeType.MERGE,CascadeType.REMOVE})
// mappedBy="basClass": 指明BasClass类为双向关系维护端,负责外键的更新
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "basClass")
public Set<StuInfo> getItems() {
return items;
}
public void setItems(Set<StuInfo> items) {
this.items = items;
}
/**
* 添加学员资料
*
* @param student
*/
public void addStuInfo(StuInfo item) {
if (!this.items.contains(item)) {
this.items.add(item);
item.setBasClass(this);
}
}
/**
* 删除学员资料
*
* @param student
*/
public void removeStuInfo(StuInfo item) {
if (this.items.contains(item)) {
item.setBasClass(null);
this.items.remove(item);
}
}
}
学员类StuInfo.java
package com.jason.bean;
import java.io.Serializable;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
/**
* many端
*
* 在one-to-many双向关联中,多的一方为关系维护端,关系维护端负责外键记录的更新
* 关系被维护端是没有权力更新外键记录的
*
* @author jason
*
*/
@Entity
@Table(name = "stu_info")
public class StuInfo implements Serializable {
private static final long serialVersionUID = 1505762337775729449L;
private Integer stuId;
private String stuName;
private Integer age;
private BasClass basClass;
public StuInfo() {
super();
}
public StuInfo(String stuName, Integer age) {
super();
this.stuName = stuName;
this.age = age;
}
@Id
@GeneratedValue
public Integer getStuId() {
return stuId;
}
public void setStuId(Integer stuId) {
this.stuId = stuId;
}
@Column(length = 20, nullable = false)
public String getStuName() {
return stuName;
}
public void setStuName(String stuName) {
this.stuName = stuName;
}
@Column(nullable = false)
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
// optional=true:可选,表示此对象可以没有,可以为null;false表示必须存在
@ManyToOne(cascade = { CascadeType.REFRESH, CascadeType.MERGE }, optional = true)
@JoinColumn(name = "cla_stu_id")
public BasClass getBasClass() {
return basClass;
}
public void setBasClass(BasClass basClass) {
this.basClass = basClass;
}
}
BasClassTest测试类
package junit.test;
import java.io.Serializable;
import java.util.List;
import java.util.Set;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import com.jason.bean.BasClass;
import com.jason.bean.StuInfo;
@SuppressWarnings("unchecked")
public class BasClassTest {
private static EntityManagerFactory factory;
private static EntityManager em;
@BeforeClass
public static void setUpBeforeClass() throws Exception {
factory = Persistence.createEntityManagerFactory("jason");
em = factory.createEntityManager();
em.getTransaction().begin();
}
/**
* 添加班级BasClass时同时添加两个学员StuInfo,因为班级BasClass为双向关系维护者,起着主导作用
*/
@Test
public void save() {
BasClass bc = new BasClass();
bc.setClaName("A班");
//UUID.randomUUID().toString()
bc.setClaId("a1");
bc.addStuInfo(new StuInfo("jason1",23));
bc.addStuInfo(new StuInfo("jason2",28));
em.persist(bc);
}
/**
* 删除BasClass对象时,会自动删除StuInfo对象(即:父对象删除时子对象跟着删除)
*/
@Test
public void detele1(){
BasClass bc=em.getReference(BasClass.class, "A班");
em.remove(bc);
}
/**
* 删除子对象时,父对象没影响
*/
@Test
public void detele2(){
StuInfo item=em.getReference(StuInfo.class, (Serializable)3);
em.remove(item);
}
@Test
public void find1(){
List<BasClass> bas=em.createQuery("select o from bas_class o").getResultList();
for(BasClass bc : bas){
System.out.println("班级ID:--"+bc.getClaId()+"/t"+"班级名称:--"+bc.getClaName());
Set<StuInfo> stuinfos=bc.getItems();
for(StuInfo stu : stuinfos){
System.out.println("学员姓名:--"+stu.getStuName()+"年龄:--"+stu.getAge());
}
System.out.println("===============");
}
}
//运行结果为
@Test
public void find2(){
List<StuInfo> items=em.createQuery("select o from stu_info o").getResultList();
for(StuInfo item : items){
System.out.println("学员姓名:"+item.getStuName()+"年龄:"+item.getAge());
BasClass bas=item.getBasClass();
System.out.println("班级ID:"+bas.getClaId()+", "+"班级名称:"+bas.getClaName());
System.out.println("============");
}
}
/**
* 测试jpa环境是否搭建成功
*
*/
@Test
public void test() {
Persistence.createEntityManagerFactory("jason");
}
@AfterClass
public static void tearDownAfterClass() throws Exception {
em.getTransaction().commit();
em.close();
factory.close();
}
}
推荐阅读
-
MyBatis从入门到精通(十一):MyBatis高级结果映射之一对多映射
-
JPA中实现双向一对多的关联关系
-
JPA中实现单向一对多的关联关系
-
SpringDataJpa在一对多、多对多关系映射时出现*Error
-
Mybatis04—注解开发实现CRUD以及实现一对一、一对多及多对多复杂关系映射
-
Mybatis常用的注解开发CRUD&&复杂关系映射(一对一,一对多)&&mybatis 基于注解的二级缓存
-
Mybatis使用注解实现一对多复杂关系映射
-
MyBatis高级映射(一对一、一对多、多对多、延迟加载)
-
MyBatis-21MyBatis高级结果映射【一对多映射(2种方式)】
-
JPA中映射关系详细说明(一对多,多对一,一对一、多对多)、@JoinColumn、mappedBy说明