Spring Data JPA的多表操作
-
一对多关系
案例:客户和联系人(客户:公司;一个客户可以具有多个联系人,一个联系人只从属于一家公司)
步骤:
-
明确表关系
一对多
-
确定表关系(外键|中间表)
客户表是主表,联系人表是从表,在从表上添加外键,指向主表的主键
-
编写实体类,在实体类中描述表关系(包含关系)
客户实体类:在客户的实体类中包含联系人的集合
联系人实体类:在联系人实体类包含客户的对象
-
配置映射关系
使用jpa注解配置一对多映射关系
import javax.persistence.*; import java.util.HashSet; import java.util.Set; @Entity @Table(name = "customer") public class Customer { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id") private Integer id; @Column(name = "address") private String address; @Column(name = "industry") private String industry; @Column(name = "level") private String level; @Column(name = "name") private String name; @Column(name = "phone") private String phone; @Column(name = "source") private String source; //配置客户和联系人的关系,一对多关系(包含关系) /* * 使用注解配置多表关系 * 1.声明关系 * @OneToMany:一对多关系 * targetEntity:对方对象的字节码对象 * 2.配置外键|中间表 * @JoinColumn:配置外键 * name:外键名称 * referencedColumnName:参照的主表的主键名称 * 在客户的实体类上(一的一方)添加了外键的配置,所以对用户而言,具备了维护外键的作用 * */ @OneToMany(targetEntity = LinkMan.class) @JoinColumn(name = "fk",referencedColumnName = "id") private Set<LinkMan> linkMans = new HashSet<LinkMan>(); //setter and getter //toString }
import javax.persistence.*; @Entity @Table(name = "linkman") public class LinkMan { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "lkm_id") private Integer lkmid; @Column(name = "lkm_name") private String lkmname; @Column(name = "lkm_gender") private String lkmgender; @Column(name = "lkm_phone") private String lkmphone; @Column(name = "lkm_mobile") private String lkmmobile; @Column(name = "lkm_email") private String lkmemail; @Column(name = "lkm_position") private String lkmposition; @Column(name = "lkm_memo") private String lkmmeno; /* * 配置联系人到客户的多对一关系 * 使用注解的形式配置多对一关系 * 1.配置表关系 * @ManyToOne:配置多对一关系 * 2.配置外键|中间表 * name:外键名称 * referencedColumnName:参照的主表的主键名称 * * */ @ManyToOne(targetEntity = Customer.class) @JoinColumn(name = "fk",referencedColumnName = "id") private Customer customer; //setter and getter //toString }
测试代码
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:applicationContext.xml") public class OneToManyTest { @Resource private CustomerDao customerDao; @Resource private LinkManDao linkManDao; /* * 保存一个客户,保存一个联系人 * */ @Test @Transactional @Rollback(false) //不自动回滚 public void testAdd(){ //创建客户,创建联系人 Customer customer = new Customer(); customer.setName("百度"); LinkMan linkMan = new LinkMan(); linkMan.setLkmname("李彦宏"); //配置两个实体类的关系 customer.getLinkMans().add(linkMan);//也可以linkMan.setCustomer(customer); customerDao.save(customer); linkManDao.save(linkMan); } }
当两个实体类进行相互的配置关系时(即双方都配置),会出现多余的update语句,需要一的一方放弃外键维护权
// @OneToMany(targetEntity = LinkMan.class) // @JoinColumn(name = "fk",referencedColumnName = "id") //mappedBy 对方配置的属性的名称 @OneToMany(mappedBy = "customer") private Set<LinkMan> linkMans = new HashSet<LinkMan>();
级联操作:
1.需要区分操作主体
2.需要在操作主题的实体类上,添加级联属性(需要添加到多表映射关系的注解上)
3.cascade(配置级联)
级联添加
/* * 级联添加,保存一个客户的同时,保存客户的所有联系人 * 需要在操作主题的实体类上配置cascade属性 * */ @Test @Transactional @Rollback(false) //不自动回滚 public void testCasCade(){ //创建客户,创建联系人 Customer customer = new Customer(); customer.setName("百度1"); LinkMan linkMan = new LinkMan(); linkMan.setLkmname("李彦宏1"); //配置两个实体类的关系 customer.getLinkMans().add(linkMan); //也可以linkMan.setCustomer(customer); linkMan.setCustomer(customer); customerDao.save(customer); linkManDao.save(linkMan); }
客户实体类
@OneToMany(mappedBy = "customer",cascade = CascadeType.ALL) //级联所有操作 private Set<LinkMan> linkMans = new HashSet<LinkMan>();
级联删除
* * 级联删除,删除1号客户的同时,删除1号客户的所有联系人 * 需要在操作主题的实体类上配置cascade属性 * */ @Test @Transactional @Rollback(false) //不自动回滚 public void testCasCadeRemove(){ //查询1号客户 Customer customer = customerDao.findOne(1); //删除1号客户 customerDao.delete(customer); }
客户实体类
@OneToMany(mappedBy = "customer",cascade = CascadeType.ALL) //级联所有操作private Set<LinkMan> linkMans = new HashSet<LinkMan>();
注意:配置文件中注入jpa的配置信息
<!--注入jpa的配置信息--> <property name="jpaProperties"> <props> <prop key="hibernate.hbm2ddl.auto">update</prop> </props> </property>
-
-
多对多关系
案例:用户和角色以及级联的添加
@Entity @Table(name = "sys_user") public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "userid") private Integer userid; @Column(name = "username") private String username; @Column(name = "userage") private Integer userage; /* * 配置用户到角色的多对多关系 * 配置多对多关系 * 1.声明表关系配置 * @ManyToMany 多对多 * targetEntity:代表对方的实体类字节码 * 2.配置中间表(包含两个外键) * @JoinTable * name:中间表名 * * */ @ManyToMany(targetEntity = Role.class,cascade = CascadeType.ALL) @JoinTable(name = "sys_user_role", //joinColumns:当前对象在中间表的外键;referencedColumnName:外键来源于user实体类的主键userid joinColumns = {@JoinColumn(name = "fk_userid",referencedColumnName = "userid")}, //inverseJoinColumns中间对象在中间表的外键 inverseJoinColumns = {@JoinColumn(name = "fk_roleid",referencedColumnName = "roleid")}) private Set<Role> roles = new HashSet<Role>(); //setter and getter //toString }
@Entity @Table(name = "sys_role") public class Role { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "roleid") private Integer roleid; @Column(name = "rolename") private String rolename; /* * 配置角色到用户的多对多关系 * 放弃维护权:mappedBy对方配置映射关系的属性名称 * */ @ManyToMany(mappedBy = "roles") private Set<User> users = new HashSet<User>(); //setter and getter //toString }
接口
public interface UserDao extends JpaRepository<User,Integer>, JpaSpecificationExecutor<User> { }
public interface RoleDao extends JpaRepository<Role,Integer>, JpaSpecificationExecutor<Role> { }
测试类
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:applicationContext.xml") public class ManyToManyTest { @Resource UserDao userDao; @Resource RoleDao roleDao; /* * 多对多放弃维护权,被动的一方放弃 * */ @Test @Transactional @Rollback(false) public void manyToMany(){ User user = new User(); user.setUsername("老王"); Role role = new Role(); role.setRolename("程序员"); //配置用户到角色的关系,可以对中间表的数据进行维护 user.getRoles().add(role); //配置角色到用户的关系,可以对中间表的数据进行维护 role.getUsers().add(user); userDao.save(user); roleDao.save(role); } /* *测试级联的添加(保存用户的同时保存用户的关联角色) * */ @Test @Transactional @Rollback(false) public void casCade(){ User user = new User(); user.setUsername("老王1"); Role role = new Role(); role.setRolename("程序员1"); //配置用户到角色的关系,可以对中间表的数据进行维护 user.getRoles().add(role); //配置角色到用户的关系,可以对中间表的数据进行维护 role.getUsers().add(user); userDao.save(user); } }