使用springData进行多表联查

如何使用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);
    }

}

对应的接口我就省略了,然后是测试类。

你可能感兴趣的:(springdata)