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);
}
}