如何使用springData进行多表联查呢
多表联查一般就是多对一,一对多,和多对多。
首先来看下一对多和多对一。
下面有个用户表和一个联系人表,一个用户可以对应多个联系人,这样就是一对多;同时多个联系人对应一个用户,这样也就是多对一。
看下具体实现过程,首先需要搭建mave工程
然后就是导入pom.xml中对应的坐标
5.2.7.RELEASE
5.4.10.Final
1.6.6
1.2.12
0.9.1.2
5.1.6
junit
junit
4.12
test
org.aspectj
aspectjweaver
1.6.8
org.springframework
spring-aop
${spring.version}
org.springframework
spring-context
${spring.version}
org.springframework
spring-context-support
${spring.version}
org.springframework
spring-orm
${spring.version}
org.springframework
spring-beans
${spring.version}
org.springframework
spring-core
${spring.version}
org.hibernate
hibernate-core
${hibernate.version}
org.hibernate
hibernate-entitymanager
${hibernate.version}
org.hibernate
hibernate-validator
5.2.1.Final
c3p0
c3p0
${c3p0.version}
log4j
log4j
${log4j.version}
org.slf4j
slf4j-api
${slf4j.version}
org.slf4j
slf4j-log4j12
${slf4j.version}
mysql
mysql-connector-java
${mysql.version}
org.springframework.data
spring-data-jpa
1.9.0.RELEASE
org.springframework
spring-test
5.2.7.RELEASE
javax.el
javax.el-api
2.2.4
org.glassfish.web
javax.el
2.2.4
然后配置的是applicationContext.xml文件
update
配置好了以后,建立对应的数据库表
/*创建客户表*/
CREATE TABLE cst_customer (
cust_id bigint(32) NOT NULL AUTO_INCREMENT COMMENT '客户编号(主键)',
cust_name varchar(32) NOT NULL COMMENT '客户名称(公司名称)',
cust_source varchar(32) DEFAULT NULL COMMENT '客户信息来源',
cust_industry varchar(32) DEFAULT NULL COMMENT '客户所属行业',
cust_level varchar(32) DEFAULT NULL COMMENT '客户级别',
cust_address varchar(128) DEFAULT NULL COMMENT '客户联系地址',
cust_phone varchar(64) DEFAULT NULL COMMENT '客户联系电话',
PRIMARY KEY (`cust_id`)
) ENGINE=InnoDB AUTO_INCREMENT=94 DEFAULT CHARSET=utf8;
/*创建联系人表*/
CREATE TABLE cst_linkman (
lkm_id bigint(32) NOT NULL AUTO_INCREMENT COMMENT '联系人编号(主键)',
lkm_name varchar(16) DEFAULT NULL COMMENT '联系人姓名',
lkm_gender char(1) DEFAULT NULL COMMENT '联系人性别',
lkm_phone varchar(16) DEFAULT NULL COMMENT '联系人办公电话',
lkm_mobile varchar(16) DEFAULT NULL COMMENT '联系人手机',
lkm_email varchar(64) DEFAULT NULL COMMENT '联系人邮箱',
lkm_position varchar(16) DEFAULT NULL COMMENT '联系人职位',
lkm_memo varchar(512) DEFAULT NULL COMMENT '联系人备注',
lkm_cust_id bigint(32) NOT NULL COMMENT '客户id(外键)',
PRIMARY KEY (`lkm_id`),
KEY `FK_cst_linkman_lkm_cust_id` (`lkm_cust_id`),
CONSTRAINT `FK_cst_linkman_lkm_cust_id` FOREIGN KEY (`lkm_cust_id`) REFERENCES `cst_customer` (`cust_id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
以及对应的实体类
package com.w.domain;
import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;
@Entity
@Table(name="cst_customer")
public class Customer {
//主键
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="cust_id")
private Long cId;
//客户名称
@Column(name="cust_name")
private String cName;
//客户来源
@Column(name="cust_source")
private String cSource;
//所属行业
@Column(name="cust_industry")
private String cIndustry;
//等级
@Column(name="cust_level")
private String cLevel;
//地址
@Column(name="cust_address")
private String cAddr;
//电话
@Column(name="cust_phone")
private String cPhone;
/* @OneToMany(targetEntity = LinkMan.class)
//name应该是从表的外键,referencedColumnName应该为主表的id
@JoinColumn(name="lkm_cust_id",referencedColumnName = "cust_id")*/
/**
* 一对多可以通过放弃一的一方的外键维护,然后mappedBy写的是从表中对应的属性的名称
* cascade:级联操作,当操作主表的时候,可以将从表的数据也进行操作,例如test1
* all:所有
* merge:更新
* PERSIST:保存
* remove:删除
*/
@OneToMany(mappedBy = "customer",cascade = CascadeType.ALL)
private Set linkMans = new HashSet();
public Long getcId() {
return cId;
}
public void setcId(Long cId) {
this.cId = cId;
}
public String getcName() {
return cName;
}
public void setcName(String cName) {
this.cName = cName;
}
public String getcSource() {
return cSource;
}
public void setcSource(String cSource) {
this.cSource = cSource;
}
public String getcIndustry() {
return cIndustry;
}
public void setcIndustry(String cIndustry) {
this.cIndustry = cIndustry;
}
public String getcLevel() {
return cLevel;
}
public void setcLevel(String cLevel) {
this.cLevel = cLevel;
}
public String getcAddr() {
return cAddr;
}
public void setcAddr(String cAddr) {
this.cAddr = cAddr;
}
public String getcPhone() {
return cPhone;
}
public void setcPhone(String cPhone) {
this.cPhone = cPhone;
}
public Set getLinkMans() {
return linkMans;
}
public void setLinkMans(Set linkMans) {
this.linkMans = linkMans;
}
@Override
public String toString() {
return "Customer{" +
"cId=" + cId +
", cName='" + cName + '\'' +
", cSource='" + cSource + '\'' +
", cIndustry='" + cIndustry + '\'' +
", cLevel='" + cLevel + '\'' +
", cAddr='" + cAddr + '\'' +
", cPhone='" + cPhone + '\'' +
'}';
}
}
package com.w.domain;
import javax.persistence.*;
@Entity
@Table(name = "cst_linkman")
public class LinkMan {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "lkm_id")
private Long 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 lkmMemo;//联系人备注
/**
* 配置联系人到客户的多对一关系
* 使用注解的形式配置多对一关系
* 1.配置表关系
* @ManyToOne : 配置多对一关系
* targetEntity:对方的实体类字节码
* 2.配置外键(中间表)
*
* * 配置外键的过程,配置到了多的一方,就会在多的一方维护外键
*
*/
@ManyToOne(targetEntity = Customer.class)
@JoinColumn(name = "lkm_cust_id",referencedColumnName = "cust_id")
private Customer customer;
public Long getLkmId() {
return lkmId;
}
public void setLkmId(Long lkmId) {
this.lkmId = lkmId;
}
public String getLkmName() {
return lkmName;
}
public void setLkmName(String lkmName) {
this.lkmName = lkmName;
}
public String getLkmGender() {
return lkmGender;
}
public void setLkmGender(String lkmGender) {
this.lkmGender = lkmGender;
}
public String getLkmPhone() {
return lkmPhone;
}
public void setLkmPhone(String lkmPhone) {
this.lkmPhone = lkmPhone;
}
public String getLkmMobile() {
return lkmMobile;
}
public void setLkmMobile(String lkmMobile) {
this.lkmMobile = lkmMobile;
}
public String getLkmEmail() {
return lkmEmail;
}
public void setLkmEmail(String lkmEmail) {
this.lkmEmail = lkmEmail;
}
public String getLkmPosition() {
return lkmPosition;
}
public void setLkmPosition(String lkmPosition) {
this.lkmPosition = lkmPosition;
}
public String getLkmMemo() {
return lkmMemo;
}
public void setLkmMemo(String lkmMemo) {
this.lkmMemo = lkmMemo;
}
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
@Override
public String toString() {
return "LinkMan{" +
"lkmId=" + lkmId +
", lkmName='" + lkmName + '\'' +
", lkmGender='" + lkmGender + '\'' +
", lkmPhone='" + lkmPhone + '\'' +
", lkmMobile='" + lkmMobile + '\'' +
", lkmEmail='" + lkmEmail + '\'' +
", lkmPosition='" + lkmPosition + '\'' +
", lkmMemo='" + lkmMemo + '\'' +
'}';
}
}
还有就是创建对应的Dao接口,需要继承JpaRepository和 JpaSpecificationExecutor两个接口
然后就是编写测试类
package com.w;
import com.w.dao.CustomDao;
import com.w.dao.LinkManDao;
import com.w.domain.Customer;
import com.w.domain.LinkMan;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;
import javax.persistence.criteria.*;
import java.util.List;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class Test1{
@Autowired
private CustomDao customDao;
@Autowired
private LinkManDao linkManDao;
@Test
@Transactional
@Rollback(false)
public void test1() {
Customer customer = new Customer();
customer.setcName("中国移动3");
LinkMan linkMan = new LinkMan();
linkMan.setLkmName("张三3");
customer.getLinkMans().add(linkMan);
linkMan.setCustomer(customer);
customDao.save(customer);
//linkManDao.save(linkMan);
}
}
这里,如果选择级联操作,也就是添加用户以后直接保存联系人操作,一对多可以通过放弃一的一方的外键维护,然后mappedBy写的是从表中对应的属性的名称。
然后是多对多的映射
多对多的就是用户和角色,一个用户对应多个角色,一个角色对应多个用户,需要添加一个用户角色的关联表
DROP TABLE IF EXISTS `sys_role`;
CREATE TABLE `sys_role` (
`role_id` int(11) NOT NULL AUTO_INCREMENT,
`role_name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`role_id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=gbk;
DROP TABLE IF EXISTS `sys_user`;
CREATE TABLE `sys_user` (
`user_id` int(11) NOT NULL AUTO_INCREMENT,
`user_name` varchar(255) DEFAULT NULL,
`user_age` varchar(255) DEFAULT NULL,
PRIMARY KEY (`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=gbk;
DROP TABLE IF EXISTS `sys_user_role`;
CREATE TABLE `sys_user_role` (
`sys_user_id` int(11) NOT NULL DEFAULT '0',
`sys_role_id` int(11) DEFAULT NULL,
PRIMARY KEY (`sys_user_id`),
KEY `FK1ef5794xnbirtsnudta6p32on` (`sys_role_id`),
CONSTRAINT `FK1ef5794xnbirtsnudta6p32on` FOREIGN KEY (`sys_role_id`) REFERENCES `sys_role` (`role_id`),
CONSTRAINT `FKsbjvgfdwwy5rfbiag1bwh9x2b` FOREIGN KEY (`sys_user_id`) REFERENCES `sys_user` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=gbk;
以及对应的实体类
package com.w.domain;
import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;
@Entity
@Table(name = "sys_user")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "user_id")
private Long id;
@Column(name = "user_name")
private String userName;
@Column(name = "user_age")
private String userAge;
//targetEntity:关联的实体类,cascade:设置级联操作
@ManyToMany(targetEntity = Role.class,cascade = CascadeType.ALL)
/**
* 配置中间表多对多
*/
@JoinTable(
//中间表表名
name = "sys_user_role",
//joinColumns,当前对象在中间表中的外键
joinColumns = {@JoinColumn(name = "sys_user_id",referencedColumnName = "user_id")},
//inverseColumns,对方中间表中的外键
inverseJoinColumns = {@JoinColumn(name ="sys_role_id",referencedColumnName = "role_id")}
)
private Set roles = new HashSet();
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserAge() {
return userAge;
}
public void setUserAge(String userAge) {
this.userAge = userAge;
}
public Set getRoles() {
return roles;
}
public void setRoles(Set roles) {
this.roles = roles;
}
}
package com.w.domain;
import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;
@Entity
@Table(name="sys_role")
public class Role {
//主键
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="role_id")
private Long id;
//角色名称
@Column(name="role_name")
private String name;
/*@ManyToMany(targetEntity = User.class)
@JoinTable(name="sys_user_role",
joinColumns = {@JoinColumn(name = "sys_role_id",referencedColumnName = "role_id")},
inverseJoinColumns = {@JoinColumn(name = "sys_user_id",referencedColumnName = "user_id")}
)*/
//被动的一方放弃外键的维护
@ManyToMany(mappedBy = "roles")
private Set users = new HashSet();
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set getUsers() {
return users;
}
public void setUsers(Set users) {
this.users = users;
}
}
package com.w;
import com.w.dao.RoleDao;
import com.w.dao.UserDao;
import com.w.domain.Role;
import com.w.domain.User;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class TestMany2Many {
@Autowired
private UserDao userDao;
@Autowired
private RoleDao roleDao;
@Test
@Transactional
@Rollback(false)
public void test1() {
User user = new User();
String userName = "张三8";
user.setUserName(userName);
Role role = new Role();
role.setName("李四8");
user.getRoles().add(role);
role.getUsers().add(user);
userDao.save(user);
//roleDao.save(role);
}
}
对应的接口我就省略了,然后是测试类。