前:关联关系:
1、单双向:
单向:指A能获取B,B不能获取A。实体类表现为A内有B属性,B内无A属性。
双向:指双方均能获取对方。实体类表现为A内有B属性,B内也有A属性。
2、n对n
n找n,即一方查找多方,多方查找一方。
3、级联操作:
级联保存 :PERSIST
级联删除 : REMOVE(危险)
强级联 :ALL,保存删除均可。
孤儿删除 :orphanRemoval = true (从一方解除关系,让多方外键置为空)
一、单向多对一 (先存一方,后存多方)
见上一篇。
二、单向一对多
1、实体
//多方
//单向一对多
//@Entity
//@Table(name="jpa3_Product_01")
public class Product_1 {
@Id
@GeneratedValue
private Long id;
private String name;
// @Column(columnDefinition = "decimal(19,2) ")//长度19,保留两位小数
private BigDecimal price;
}
//一方
//单向一对多
//@Entity
//@Table(name = "jpa3_ProductDir_01")
public class ProductDir_1 {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
@OneToMany(fetch = FetchType.LAZY)//设置为懒加载
@JoinColumn(name = "dir_id")//外键名称
@OrderBy("price DESC")//按价格降序排列,对于查询出的数组,数据库数据顺序不变
private List<Product_1> products= new ArrayList();//不能
}
2、测试
public class _01Test {
@Test//单向一对多测试
public void testOneToMany() throws Exception{
//创建产品类别
ProductDir_1 dir = new ProductDir_1();
dir.setName("坚果");
//创建产品
Product_1 product1 = new Product_1();
product1.setName("夏威夷果");
product1.setPrice(new BigDecimal(21.111));
Product_1 product2 = new Product_1();
product2.setName("开心果");
product2.setPrice(new BigDecimal(6.66666));
Product_1 product3 = new Product_1();
product3.setName("花生");
product3.setPrice(new BigDecimal(7.7777));
//连接关系
dir.getProducts().add(product1);
dir.getProducts().add(product2);
dir.getProducts().add(product3);
//获取管理对象
EntityManager entityManager = JPAUtil.getEntityManager();
//开启事务
entityManager.getTransaction().begin();
//持久化,不论先保存一方还是多方,都会发送相同多条sql
entityManager.persist(dir);
entityManager.persist(product1);
entityManager.persist(product2);
entityManager.persist(product3);
//提交事务
entityManager.getTransaction().commit();
//关闭
entityManager.close();
}
@Test//单向一对多,一方查询测试
public void testSet() throws Exception{
//获取管理对象
EntityManager entityManager = JPAUtil.getEntityManager();
//查询
ProductDir_1 dir = entityManager.find(ProductDir_1.class, 1L);
System.out.println("Set的类为:"+dir.getProducts().getClass());//Set的继承接口PersistentSet
//判断该类有无产品打印
if (dir.getProducts().size()!=0){
System.out.println(dir.getName()+"类的产品有:");
for(Product_1 p1 :dir.getProducts()){
System.out.println(p1);
}
}else {
System.out.println("该类别没有产品");
}
//关闭
entityManager.close();
}
}
三、双向的多对一、一对多
1、实体
//多方
//双向多对一
//@Entity
@Table(name="jpa3_Product_02")
public class Product_2 {
@Id
@GeneratedValue
private Long id;//1
private String name;//2
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "dir_id")
private ProductDir_2 dir;
}
//一方
//双向多对一
//@Entity
@Table(name = "jpa3_ProductDir_02")
public class ProductDir_2 {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
//孤儿删除:只删除多方内的某一
@OneToMany(orphanRemoval = true,cascade = CascadeType.ALL ,mappedBy = "dir",fetch = FetchType.LAZY)
//@JoinColumn(name = "dir_id")
private Set<Product_2> products= new HashSet();
}
2、测试
public class _02Test {
@Test//1、双向多对一,保存测试
public void testManyToOne() throws Exception{
//创建产品
Product_2 p1 = new Product_2();
p1.setName("苹果");
Product_2 p2 = new Product_2();
p2.setName("桃子");
//创建分类
ProductDir_2 dir = new ProductDir_2();
dir.setName("水果类");
//多方创建关系
p1.setDir(dir);
p2.setDir(dir);
//一方创建关系
dir.getProducts().add(p1);
dir.getProducts().add(p2);
EntityManager entityManager = JPAUtil.getEntityManager();
//开启事务
entityManager.getTransaction().begin();
//先一方,再多方,3条sql
//先多方,再一方,5条sql
entityManager.persist(p1);
entityManager.persist(p2);
entityManager.persist(dir);
//提交事务
entityManager.getTransaction().commit();
//关闭
entityManager.close();
}
@Test//2、双向多对一查询测试
public void testFind() throws Exception{
EntityManager entityManager = JPAUtil.getEntityManager();
//查询一方,配置迫切加载模式
//ProductDir_2 dir = entityManager.find(ProductDir_2.class, 1L);
//System.out.println(dir);
//查询多方,懒加载
Product_2 product_2 = entityManager.find(Product_2.class, 2L);
System.out.println(product_2);
entityManager.close();
}
@Test//3、级联保存测试
public void testCascade() throws Exception{
//创建产品
Product_2 p1 = new Product_2();
p1.setName("白菜");
Product_2 p2 = new Product_2();
p2.setName("萝卜");
//创建分类
ProductDir_2 dir = new ProductDir_2();
dir.setName("蔬菜类");
//多方创建关系:多方维护主键,一方设置级联保存时,多方创建关系才能实现一方级联保存时的主键创建
p1.setDir(dir);
p2.setDir(dir);
//一方创建关系:多方维护主键,一方设置级联保存时,一方创建关系用于创建多方和一方表格
dir.getProducts().add(p1);
dir.getProducts().add(p2);
EntityManager entityManager = JPAUtil.getEntityManager();
//开启事务
entityManager.getTransaction().begin();
//多方维护主键,一方设置级联保存,双方均建立关系,3条sql
entityManager.persist(dir);
//提交事务
entityManager.getTransaction().commit();
//关闭
entityManager.close();
}
@Test//4、级联删除测试
public void testDelete() throws Exception{
EntityManager entityManager = JPAUtil.getEntityManager();
//查询一条一方
ProductDir_2 dir2 = entityManager.find(ProductDir_2.class, 2L);
//级联删除 cascade = CascadeType.ALL 或 REMOVE
//开启事务
entityManager.getTransaction().begin();
//删除
entityManager.remove(dir2);
//提交事务
entityManager.getTransaction().commit();
entityManager.close();
}
@Test//5、孤儿删除测试
public void testOrphanRemoval() throws Exception{
EntityManager entityManager = JPAUtil.getEntityManager();
//查询一条一方
ProductDir_2 dir1 = entityManager.find(ProductDir_2.class, 1L);//水果
//查询一条一方
Product_2 pro3 = entityManager.find(Product_2.class, 3L);//西瓜
//孤儿删除 orphanRemoval = true
//开启事务
entityManager.getTransaction().begin();
//删除
dir1.getProducts().remove(pro3);
//提交事务
entityManager.getTransaction().commit();
entityManager.close();
}
@Test//6、删除一条一方下面的所有多方,但不删除该条一方
public void testDeleteMany() throws Exception{
EntityManager entityManager = JPAUtil.getEntityManager();
//查询一条一方
ProductDir_2 dir1 = entityManager.find(ProductDir_2.class, 2L);//蔬菜
//开启事务
entityManager.getTransaction().begin();
//删除蔬菜类下面所有子类
dir1.getProducts().clear();
//提交事务
entityManager.getTransaction().commit();
entityManager.close();
}
}
四、单向多对多(中间表维护)
1、实体
//非维护方
//单向多对多
//@Entity
//@Table(name = "jpa3_teacher")
public class Teacher {
@Id
@GeneratedValue
private Long id;
private String name;
}
//维护方
//单向多对多
//@Entity
//@Table(name = "jpa3_student")
public class Student {
@Id
@GeneratedValue
private Long id;
private String name;
@ManyToMany
@JoinTable(name = "jpa3_student_teacher",joinColumns = @JoinColumn(name="stu_id"),inverseJoinColumns = @JoinColumn(name="teach_id"))
private Set<Teacher> t_set = new HashSet();
2、测试
public class _03Test {
@Test//1、保存测试
public void testManyToMany() throws Exception{
//创建老师
Teacher t1 =new Teacher();
t1.setName("王老师");
Teacher t2 =new Teacher();
t2.setName("李老师");
//创建学生
Student stu1= new Student();
stu1.setName("阿毛");
stu1.getT_set().add(t1);
stu1.getT_set().add(t2);
Student stu2= new Student();
stu2.setName("阿蛋");
stu2.getT_set().add(t1);
stu2.getT_set().add(t2);
Student stu3= new Student();
stu3.setName("阿狗");
stu3.getT_set().add(t1);
stu3.getT_set().add(t2);
//获取管理对象
EntityManager entityManager = JPAUtil.getEntityManager();
//开启事务
entityManager.getTransaction().begin();
//保存
entityManager.persist(stu1);
entityManager.persist(stu2);
entityManager.persist(stu3);
entityManager.persist(t1);
entityManager.persist(t2);
//提交事务
entityManager.getTransaction().commit();
//关闭对象
entityManager.close();
}
@Test//2、查询测试
public void testFind() throws Exception{
//获取管理对象
EntityManager entityManager = JPAUtil.getEntityManager();
//查询
Student student = entityManager.find(Student.class, 1L);
System.out.println("长度:"+student.getT_set().size());//默认使用延迟加载
}
}
五、双向多对多(中间表维护)
1、实体
//双向多对多
//@Entity
//@Table(name = "jpa3_MMstu")
public class StudentMM {
@Id
@GeneratedValue
private Long id;
private String name;
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "jpa3_MM_stu_tea",joinColumns = @JoinColumn(name="sid"),inverseJoinColumns = @JoinColumn(name="tid"))
private Set<TeacherMM> t_set = new HashSet();
}
//双向多对多
//@Entity
//@Table(name = "jpa3_MMtea")
public class TeacherMM {
@Id
@GeneratedValue
private Long id;
private String name;
//teacher多对多配置
@ManyToMany
@JoinTable(name = "jpa3_MM_stu_tea",joinColumns = @JoinColumn(name="tid"),inverseJoinColumns = @JoinColumn(name="sid"))
private Set<StudentMM> s_set = new HashSet();
}
2、测试
public class _04Test {
@Test//1、双向多对多保存
public void testSave() throws Exception{
//创建Student
StudentMM s1 = new StudentMM();
s1.setName("阿毛");
StudentMM s2 = new StudentMM();
s2.setName("阿猪");
StudentMM s3 = new StudentMM();
s3.setName("阿蛋");
//创建Teacher
TeacherMM t1 = new TeacherMM();
t1.setName("马老师");
t1.getS_set().add(s1);
t1.getS_set().add(s2);
t1.getS_set().add(s3);
TeacherMM t2 = new TeacherMM();
t2.setName("牛老师");
t2.getS_set().add(s1);
t2.getS_set().add(s2);
t2.getS_set().add(s3);
//建立关系:Student添加Teacher
s1.getT_set().add(t1);
s1.getT_set().add(t2);
s2.getT_set().add(t1);
s2.getT_set().add(t2);
s3.getT_set().add(t1);
s3.getT_set().add(t2);
//获取
EntityManager entityManager = JPAUtil.getEntityManager();
//开启
entityManager.getTransaction().begin();
//保存,顺序无影响
entityManager.persist(s1);
entityManager.persist(s2);
entityManager.persist(s3);
entityManager.persist(t1);
entityManager.persist(t2);
//提交
entityManager.getTransaction().commit();
//关闭
entityManager.close();
}
@Test//2、级联保存
public void testCasecade() throws Exception{
//创建Student
StudentMM s1 = new StudentMM();
s1.setName("小明");
StudentMM s2 = new StudentMM();
s2.setName("小毛");
StudentMM s3 = new StudentMM();
s3.setName("小花");
//创建Teacher
TeacherMM t1 = new TeacherMM();
t1.setName("姬老师");
TeacherMM t2 = new TeacherMM();
t2.setName("苟老师");
//建立关系:Student添加Teacher
s1.getT_set().add(t1);
s1.getT_set().add(t2);
s2.getT_set().add(t1);
s2.getT_set().add(t2);
s3.getT_set().add(t1);
s3.getT_set().add(t2);
//获取
EntityManager entityManager = JPAUtil.getEntityManager();
//开启
entityManager.getTransaction().begin();
//保存,顺序无影响
entityManager.persist(s1);
entityManager.persist(s2);
entityManager.persist(s3);
//提交
entityManager.getTransaction().commit();
//关闭
entityManager.close();
}
@Test//3、级联删除
public void testDelete() throws Exception{
//获取管理对象
EntityManager entityManager = JPAUtil.getEntityManager();
//查询
StudentMM studentMM = entityManager.find(StudentMM.class, 2L);
TeacherMM teacherMM = entityManager.find(TeacherMM.class, 2L);
//开启
entityManager.getTransaction().begin();
//(1)级联删除,删除一条student,所有的相关中间表,和另一多方相关中间表也会被删除
//不配置级联删除,删除一条student只删除关联的数据
//entityManager.remove(studentMM);
//(2)清空,是否级联均相同
//studentMM.getT_set().clear();
//(3)删除一个Student的一条Teacher
studentMM.getT_set().remove(teacherMM);
//(4)删除一个Student的一条Teacher,再添加一条
studentMM.getT_set().remove(teacherMM);
studentMM.getT_set().add(teacherMM);
//(5)双向级联,全部删除
//提交
entityManager.getTransaction().commit();
//关闭
entityManager.close();
}
}
六、一对一(了解)
1、实体
//@Entity
//@Table(name = "jpa3_qq")
public class QQ {
@Id
@GeneratedValue
private Long id;
private String name;
@OneToOne(mappedBy = "qq")
private QQZone qqZone;
}
//@Entity
//@Table(name = "jpa3_QQzone")
public class QQZone {
@Id
@GeneratedValue
private Long id;
private String name;
@OneToOne(optional = false,fetch = FetchType.LAZY)//外键不能为空,默认迫切加载
@JoinColumn(name = "qq_id",unique = true)//外键唯一
private QQ qq;
}
2、测试
public class _05Test {
@Test//1、保存测试
public void testName() throws Exception{
//创建QQ
QQ qq =new QQ();
qq.setName("呆子");
QQZone qqZone = new QQZone();
qqZone.setName("悟能");
qqZone.setQq(qq);
//获取
EntityManager entityManager = JPAUtil.getEntityManager();
//开启
entityManager.getTransaction().begin();
//保存
entityManager.persist(qq);
entityManager.persist(qqZone);
//提交
entityManager.getTransaction().commit();
//关闭
entityManager.close();
}
@Test//2、查询测试
public void testFind() throws Exception{
//获取
EntityManager entityManager = JPAUtil.getEntityManager();
//保存
QQZone qqZone = entityManager.find(QQZone.class, 1L);
System.out.println(qqZone);
//关闭
entityManager.close();
}
}