JPA--一对多和多对多
一对多
需求分析:
有客户Customer和房子Houst两个实体类,每个客户可以有多个房子,一个房子属于一个客户
客户是一的一方,房子是多的一方。
jpa_customer是主表,jpa_houst是从表
代码实现
1.编写实体类
客户Customer类
package com.domain; import org.hibernate.annotations.Target; import javax.persistence.*; import java.io.Serializable; import java.util.HashSet; import java.util.Set; /** * 客户实体类 * 使用注解时JPA规范,所以导包都需要导入javax.persistence下的包 */ @Entity //表明当前类是一个实体类 @Table(name = "jpa_customer") //建立与数据库表之间的联系 public class Customer implements Serializable { @Id //表明当前字段是主键 @Column(name = "c_id") //对应数据库中的字段名 @GeneratedValue(strategy =GenerationType.IDENTITY ) //使用JAP中的主键生成策略 private Integer id; @Column(name = "c_name") private String name; @Column(name = "c_lovel") private String lovel; //一对多关系,少的一方,一个客户多所房子 // @OneToMany:注释一的一方;targetEntity:目标类;mappedBy:放弃控制,参数为对方属性类get方法的参数。 @OneToMany(targetEntity = House.class,mappedBy = "customer") private Set<House> houses=new HashSet<House>(0); public Set<House> getHouses() { return houses; } public void setHouses(Set<House> houses) { this.houses = houses; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getLovel() { return lovel; } public void setLovel(String lovel) { this.lovel = lovel; } public Customer(String name, String lovel) { this.name = name; this.lovel = lovel; } public Customer() { } public Customer(Integer id, String name) { this.id = id; this.name = name; } @Override public String toString() { return "Customer [id=" + id + ", name=" + name + ", lovel=" + lovel + "]"; } }
Houst类
package com.domain; import javax.persistence.*; import java.io.Serializable; @Entity @Table(name = "jpa_house") public class House implements Serializable { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name ="h_id") private Integer hId; @Column(name ="h_iddress") private String hIddress; @Column(name ="h_price") private Double hPrice; //一对多,多的一方 //@ManyToOne 多的一方; //JoinColumn加入外键列 referencedColumnName对应主表的列 @ManyToOne(targetEntity = Customer.class) @JoinColumn(name = "h_c_id",referencedColumnName = "c_id") private Customer customer; @Override public String toString() { return "House{" + "hId=" + hId + ", hIddress='" + hIddress + '\'' + ", hPrice=" + hPrice + ", customer=" + customer + '}'; } public Customer getCustomer() { return customer; } public void setCustomer(Customer customer) { this.customer = customer; } public Integer gethId() { return hId; } public void sethId(Integer hId) { this.hId = hId; } public String gethIddress() { return hIddress; } public void sethIddress(String hIddress) { this.hIddress = hIddress; } public Double gethPrice() { return hPrice; } public void sethPrice(Double hPrice) { this.hPrice = hPrice; } }
2.运行生成数据库表
3.测试
保存测试
//保存操作 //需求:实现锁房子属于同一客户 @Test public void Test01(){ //1.获取EntityManager EntityManager em= JPAUtils.createEntityManager(); //2.获取事务开启事务 EntityTransaction tx = em.getTransaction(); tx.begin(); //3.创建客户和房子类 Customer c1=new Customer(); c1.setName("袁绍"); House h1=new House(); House h2=new House(); h1.sethIddress("幽州"); h2.sethIddress("豫州"); //4.将房子添加给客户 c1.getHouses().add(h1); c1.getHouses().add(h2); //5.将客户添加给房子 h1.setCustomer(c1); h2.setCustomer(c1); //6.执行保存 em.persist(c1); em.persist(h1); em.persist(h2); //释放资源 tx.commit(); em.close(); }
更新测试
//更新操作 //需求:实现锁房子属于同一客户 @Test public void Test02(){ //1.获取EntityManager EntityManager em= JPAUtils.createEntityManager(); //2.获取事务开启事务 EntityTransaction tx = em.getTransaction(); tx.begin(); //获取一个客户 Customer customer = em.find(Customer.class, 5); //给客户一个房子 House h1=new House(); h1.sethIddress("北魏"); customer.getHouses().add(h1); //快照机制自动保存 //将房子属性设给客户 h1.setCustomer(customer); //执行操作 //em.merge(customer); em.persist(h1); //释放资源 tx.commit(); em.close(); }
级联删除测试
修改修改数据库表的数据库级联删除为空
//一对多关系,少的一方,一个客户多所房子
// @OneToMany:注释一的一方;targetEntity:目标类;mappedBy:放弃控制,参数为对方属性类get方法的参数。
//cascade = CascadeType.REMOVE,级联删除 CascadeType.PERSIST不级联删除
@OneToMany(targetEntity = House.class,mappedBy = "customer",cascade = CascadeType.PERSIST)
private Set<House> houses=new HashSet<House>(0);
//删除操作 @Test public void Test03(){ //1.获取EntityManager EntityManager em= JPAUtils.createEntityManager(); //2.获取事务开启事务 EntityTransaction tx = em.getTransaction(); tx.begin(); //获取一个客户 Customer customer = em.find(Customer.class, 4); em.remove(customer); //释放资源 tx.commit(); em.close(); }
查询测试
//查询操作 @Test public void Test04(){ //1.获取EntityManager EntityManager em= JPAUtils.createEntityManager(); //2.获取事务开启事务 EntityTransaction tx = em.getTransaction(); tx.begin(); //获取一个客户 Customer customer = em.find(Customer.class, 7); System.out.println(customer);
//获取客户关联的所有房子 Set<House> houses = customer.getHouses(); for (House house : houses) { System.out.println(house); } //释放资源 tx.commit(); em.close(); }
多对多
需求分析:
房子类House对应家具类Furniture
一个房子有多种家具,一个家具可以为多种房子所有
jpa_houst表和furniture表
代理示例:
1.创建实体类
House类
package com.domain; import org.hibernate.annotations.GenericGenerator; import javax.persistence.*; import java.io.Serializable; import java.util.HashSet; import java.util.Set; @Entity @Table(name = "jpa_house") public class House implements Serializable { @Id @GenericGenerator(name = "uuid",strategy = "uuid") @GeneratedValue(generator = "uuid",strategy = GenerationType.IDENTITY) @Column(name ="h_id") private Integer hId; @Column(name ="h_iddress") private String hIddress; @Column(name ="h_price") private Double hPrice; //一对多,多的一方 //@ManyToOne 多的一方; //JoinColumn加入外键列 referencedColumnName对应主表的列 @ManyToOne(targetEntity = Customer.class) @JoinColumn(name = "h_c_id",referencedColumnName = "c_id") private Customer customer; //多对多 @ManyToMany //加入一张表,name表明,joinColumns = {@JoinColumnpei配置本类在表的列,inverseJoinColumns = {@JoinColumn对方列配置,放弃床表的类 @JoinTable(name = "jpa_house_furniture",joinColumns = {@JoinColumn(name="h_id",referencedColumnName = "h_id")}, inverseJoinColumns = {@JoinColumn(name="f_id",referencedColumnName = "f_id")} ) private Set<Furniture> furnitures =new HashSet<Furniture>(0); @Override public String toString() { return "House{" + "hId=" + hId + ", hIddress='" + hIddress + '\'' + ", hPrice=" + hPrice + ", customer=" + customer + ", furnitures=" + furnitures + '}'; } public Set<Furniture> getFurnitures() { return furnitures; } public void setFurnitures(Set<Furniture> furnitures) { this.furnitures = furnitures; } public Customer getCustomer() { return customer; } public void setCustomer(Customer customer) { this.customer = customer; } public Integer gethId() { return hId; } public void sethId(Integer hId) { this.hId = hId; } public String gethIddress() { return hIddress; } public void sethIddress(String hIddress) { this.hIddress = hIddress; } public Double gethPrice() { return hPrice; } public void sethPrice(Double hPrice) { this.hPrice = hPrice; } }
Furniture类
package com.domain; import org.hibernate.annotations.GenericGenerator; import javax.persistence.*; import java.util.HashSet; import java.util.Set; @Entity @Table(name = "jpa_furnitrue") public class Furniture { @Id @Column(name = "f_id") //生成主键的生成器,name给生成器取名,strategy hibernata的生成策略 @GenericGenerator(name = "uuid",strategy = "uuid") @GeneratedValue(generator = "uuid") private Integer fId; @Column(name = "f_name") private String fName; @Column(name = "f_price") private Double fPrice; @ManyToMany(mappedBy = "furnitures") private Set<House> houses =new HashSet<House>(0); public Integer getfId() { return fId; } public void setfId(Integer fId) { this.fId = fId; } public String getfName() { return fName; } public void setfName(String fName) { this.fName = fName; } public Double getfPrice() { return fPrice; } public void setfPrice(Double fPrice) { this.fPrice = fPrice; } @Override public String toString() { return "Furniture{" + "fId=" + fId + ", fName='" + fName + '\'' + ", fPrice=" + fPrice + ", houses=" + houses + '}'; } public Set<House> getHouses() { return houses; } public void setHouses(Set<House> houses) { this.houses = houses; } }
2.测试
添加
//保存操作 //需求:实现锁多所房子里面有多种家具 @Test public void Test01(){ //1.获取EntityManager EntityManager em= JPAUtils.createEntityManager(); //2.获取事务开启事务 EntityTransaction tx = em.getTransaction(); tx.begin(); //3.创建房子和家具对象 House h1=new House("81房"); House h2=new House("82房"); Furniture f1=new Furniture("双人床"); Furniture f2=new Furniture("桌子"); Furniture f3=new Furniture("担任床"); //4.将家电给房子 h1.getFurnitures().add(f1); h1.getFurnitures().add(f2); h1.getFurnitures().add(f3); h2.getFurnitures().add(f1); h2.getFurnitures().add(f3); //5.将房子给家电 f1.getHouses().add(h1); f1.getHouses().add(h2); f2.getHouses().add(h1); f3.getHouses().add(h1); f3.getHouses().add(h2); //6.执行保存操作 //级联保存可以在属性上面配置 @ManyToMany(cascade = CascadeType.ALL) em.persist(h1); // em.persist(h2); // em.persist(f1); // em.persist(f2); // em.persist(f3); //释放资源 tx.commit(); em.close(); }
删除
//删除操作 ;级联删除一般不允许用 @Test public void Test02(){ //1.获取EntityManager EntityManager em= JPAUtils.createEntityManager(); //2.获取事务开启事务 EntityTransaction tx = em.getTransaction(); tx.begin(); Furniture furniture = em.find(Furniture.class, "402881e870b9a6af0170b9a6b26f0004"); em.remove(furniture); //释放资源 tx.commit(); em.close(); }
查询
//查询操作 @Test public void test03(){ EntityManager em= JPAUtils.createEntityManager(); EntityTransaction tx = em.getTransaction(); tx.begin(); //先查询一个对象 Customer c1=em.find(Customer.class,1); System.out.println(c1.getName()); //再查询对象的所有房子 Set<House> houses = c1.getHouses(); for (House house : houses) { System.out.println(house.gethIddress()); //再根据每个房子查询对应的家具 for (Furniture f : house.getFurnitures()) { System.out.println(f.getfName()); } } tx.commit(); em.close(); }
查询输出结果
Hibernate: select customer0_.c_id as c_id1_0_0_, customer0_.c_lovel as c_lovel2_0_0_, customer0_.c_name as c_name3_0_0_ from jpa_customer customer0_ where customer0_.c_id=?
曹操
Hibernate: select houses0_.h_c_id as h_c_id4_2_0_, houses0_.h_id as h_id1_2_0_, houses0_.h_id as h_id1_2_1_, houses0_.h_c_id as h_c_id4_2_1_, houses0_.h_iddress as h_iddres2_2_1_, houses0_.h_price as h_price3_2_1_ from jpa_house houses0_ where houses0_.h_c_id=?
蜀国
Hibernate: select furnitures0_.h_id as h_id1_3_0_, furnitures0_.f_id as f_id2_3_0_, furniture1_.f_id as f_id1_1_1_, furniture1_.f_name as f_name2_1_1_, furniture1_.f_price as f_price3_1_1_ from jpa_house_furniture furnitures0_ inner join jpa_furnitrue furniture1_ on furnitures0_.f_id=furniture1_.f_id where furnitures0_.h_id=?
担任床
双人床
北魏
Hibernate: select furnitures0_.h_id as h_id1_3_0_, furnitures0_.f_id as f_id2_3_0_, furniture1_.f_id as f_id1_1_1_, furniture1_.f_name as f_name2_1_1_, furniture1_.f_price as f_price3_1_1_ from jpa_house_furniture furnitures0_ inner join jpa_furnitrue furniture1_ on furnitures0_.f_id=furniture1_.f_id where furnitures0_.h_id=?
桌子
担任床
双人床