JPA---Specifications动态查询多表查询,表表关系




    

    
    
        
        
        
        
        
            
        

        
        
            
                
                
                
                
                
                
                
                
            
        

        
        
            
        

    

    
    
        
        
        
        
    

    
    

    
    
        
    

    
    
        
            
            
            
            
            
            
            
        
    

   

    

    
    

2.DAO层实体类

package com.itheima.domain;

import javax.persistence.*;

/**
 * 1.实体类和表的映射关系
 *      @Eitity
 *      @Table
 * 2.类中属性和表中字段的映射关系
 *      @Id
 *      @GeneratedValue
 *      @Column
 */
@Entity
@Table(name="cst_customer")
public class Customer {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="cust_id")
    private Long custId;
    @Column(name="cust_address")
    private String custAddress;
    @Column(name="cust_industry")
    private String custIndustry;
    @Column(name="cust_level")
    private String custLevel;
    @Column(name="cust_name")
    private String custName;
    @Column(name="cust_phone")
    private String custPhone;
    @Column(name="cust_source")
    private String custSource;

    public Long getCustId() {
        return custId;
    }

    public void setCustId(Long custId) {
        this.custId = custId;
    }

    public String getCustAddress() {
        return custAddress;
    }

    public void setCustAddress(String custAddress) {
        this.custAddress = custAddress;
    }

    public String getCustIndustry() {
        return custIndustry;
    }

    public void setCustIndustry(String custIndustry) {
        this.custIndustry = custIndustry;
    }

    public String getCustLevel() {
        return custLevel;
    }

    public void setCustLevel(String custLevel) {
        this.custLevel = custLevel;
    }

    public String getCustName() {
        return custName;
    }

    public void setCustName(String custName) {
        this.custName = custName;
    }

    public String getCustPhone() {
        return custPhone;
    }

    public void setCustPhone(String custPhone) {
        this.custPhone = custPhone;
    }

    public String getCustSource() {
        return custSource;
    }

    public void setCustSource(String custSource) {
        this.custSource = custSource;
    }

    @Override
    public String toString() {
        return "Customer{" +
                "custId=" + custId +
                ", custAddress='" + custAddress + '\'' +
                ", custIndustry='" + custIndustry + '\'' +
                ", custLevel='" + custLevel + '\'' +
                ", custName='" + custName + '\'' +
                ", custPhone='" + custPhone + '\'' +
                ", custSource='" + custSource + '\'' +
                '}';
    }
}

3.测试

package com.itheima.test;

import com.itheima.dao.CustomerDao;
import com.itheima.domain.Customer;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import javax.persistence.criteria.*;
import java.util.List;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class testSpec {
    //1.1使用Specifications完成条件查询
    @Autowired
    private CustomerDao customerDao;
    @Test
    public void testSpec01(){
        Specification spec=new Specification() {
            //匿名内部类 创建Specification实现类,重写Predicate方法
            public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) {
                //cb:构建查询,添加查询方式   like:模糊匹配
                //root:从实体Customer对象中按照custName属性进行查询
                Path custName = root.get("custName");
                Predicate predicate = cb.like(custName.as(String.class), "%陈%");
                //一定要将创造的条件返回 不然相当于没有条件 返回的是null
                return predicate;
            }
        };
        List customers = customerDao.findAll(spec);
        for (Customer customer : customers) {

            System.out.println(customer);
        }
    }

    /**
     * 根据   姓氏    和  所属行业查询
     */
    @Test
    public void testSpec02(){
        Specification spec1=new Specification() {
            //匿名内部类 创建Specification实现类,重写Predicate方法
            public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) {
                //cb:构建查询,添加查询方式   like:模糊匹配
                //root:从实体Customer对象中按照custName属性进行查询
                Path custName = root.get("custName");//姓名模糊
                Path custIndustry = root.get("custIndustry");
                Predicate predicate1 = cb.like(custName.as(String.class), "陈%");
                Predicate predicate2 = cb.like(custIndustry.as(String.class), "%歌手%");
                Predicate and = cb.and(predicate1, predicate2);
                //一定要将创造的条件返回 不然相当于没有条件 返回的是null
                return and;
            }
        };
        Sort sort=new Sort(Sort.DEFAULT_DIRECTION.DESC,"custId");//根据ID排序倒叙
        List customers = customerDao.findAll(spec1,sort);
        for (Customer customer : customers) {

            System.out.println(customer);
        }
    }


    /**
     * 分页查询
     */
      @Test
    public  void testSpec03(){
        Pageable pageable=new PageRequest(0,1);
        Page all = customerDao.findAll(pageable);
        for (Customer customer : all) {
            System.out.println(customer);
        }

        System.out.println(all.getTotalPages());
        System.out.println(all.getSize());

    }
  @Test
    public void testFind() {
        Specification spec = new Specification() {
            public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) {
                //Join代表链接查询,通过root对象获取
                //创建的过程中,第一个参数为关联对象的属性名称,第二个参数为连接查询的方式(left,inner,right)
                //JoinType.LEFT : 左外连接,JoinType.INNER:内连接,JoinType.RIGHT:右外连接
                Join join = root.join("customer", JoinType.INNER);

                return cb.like(join.get("custName").as(String.class), "你%");
            }
        };
        List list = linkManDao.findAll(spec);
        for (LinkMan linkMan : list) {
            System.out.println(linkMan);
        }
    }
}
 
  

4.一对多(表)

在主表中加入从表的属性最好用set 集合(如果配置

mappedBy就表示设置了外键放弃维护

)

/**
     * 使用注解的形式配置多表关系
     *      1.声明关系
     *          @OneToMany : 配置一对多关系
     *              targetEntity :对方对象的字节码对象
     *      2.配置外键(中间表)
     *              @JoinColumn : 配置外键
     *                  name:外键字段名称
     *                  referencedColumnName:参照的主表的主键字段名称
     *
     *  * 在客户实体类上(一的一方)添加了外键了配置,所以对于客户而言,也具备了维护外键的作用
     *
     */

  // @OneToMany(targetEntity = LinkMan.class)
   // @JoinColumn(name = "lkm_cust_id",referencedColumnName = "cust_id")
    /**
     * 放弃外键维护权
     *      mappedBy:对方配置关系的属性名称\
     * cascade : 配置级联(可以配置到设置多表的映射关系的注解上)
     *      CascadeType.all         : 所有
     *                  MERGE       :更新
     *                  PERSIST     :保存
     *                  REMOVE      :删除
     *
     * fetch : 配置关联对象的加载方式
     *          EAGER   :立即加载
     *          LAZY    :延迟加载
     *

     */
   @OneToMany(mappedBy = "customer", cascade = CascadeType.ALL )
    private Set linkMans = new HashSet();

5.测试

package com.itheima.test;

import com.itheima.dao.CustomerDao;
import com.itheima.dao.LinkManDao;
import com.itheima.domain.Customer;
import com.itheima.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 java.util.Set;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class TestOne2Many {
    @Autowired
    private CustomerDao customerDao;

    @Autowired
    private LinkManDao linkManDao;

    /**
     * 保存一个客户和联系人
     */
    @Test
    @Transactional
    @Rollback(false)
    public void saveTest(){
        Customer c = new Customer();
        c.setCustName("詹姆斯1");
        c.setCustLevel("VIP客户");
        c.setCustSource("网络");
        c.setCustIndustry("商业办公");
        c.setCustAddress("昌平区北七家镇");
        c.setCustPhone("010-84389340");

        LinkMan l = new LinkMan();
        l.setLkmName("骑士1");
        l.setLkmGender("male");
        l.setLkmMobile("13811111111");
        l.setLkmPhone("010-34785348");
        l.setLkmEmail("[email protected]");
        l.setLkmPosition("老师");
        l.setLkmMemo("还行吧");

        c.getLinkMans().add(l);
       l.setCustomer(c);//储存外键
        customerDao.save(c);
        linkManDao.save(l);
    }
//一对多,默认:使用延迟加载(****)
    @Test
    @Transactional
    @Rollback(false)
    public  void findByZhuB(){
        Customer one = customerDao.findOne(9L);
        Set linkMans = one.getLinkMans();
        System.out.println(linkMans);
        System.out.println(one);
    }

   @Test
    public  void testDel(){

        //linkManDao.delete(4L);//从表删除,直接删除

       customerDao.delete(12L);//从主表删除 1.如果从表有数据 会默认将从表的外键设置为null从而删除(外键没有设为非空)
         //2.如果在主表设置了放弃外键维护,则不能直接删除,会报错
         //3.可以在主表的 从表属性上 注解里面设置级联cascade,从表的相关数据也会被删除
         //4.级联:操作一个对象的同时操作他的相关联的对象

    }


}

6.多对多(有一个中间表需要注意)

6.1 两个实体类

package com.itheima.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 userId;
    @Column(name="user_name")
    private String userName;
    @Column(name="age")
    private Integer age;

    /**
     * 配置用户到角色的多对多关系
     *      配置多对多的映射关系
     *          1.声明表关系的配置
     *              @ManyToMany(targetEntity = Role.class)  //多对多
     *                  targetEntity:代表对方的实体类字节码
     *          2.配置中间表(包含两个外键)
     *                @JoinTable
     *                  name : 中间表的名称
     *                  joinColumns:配置当前对象在中间表的外键
     *                      @JoinColumn的数组
     *                          name:外键名
     *                          referencedColumnName:参照的主表的主键名
     *                  inverseJoinColumns:配置对方对象在中间表的外键
     */
    @ManyToMany(targetEntity = Role.class,cascade = CascadeType.ALL)
    @JoinTable(name = "sys_user_role",
            //joinColumns,当前对象在中间表中的外键
            joinColumns = {@JoinColumn(name = "sys_user_id",referencedColumnName = "user_id")},
            //inverseJoinColumns,对方对象在中间表的外键
            inverseJoinColumns = {@JoinColumn(name = "sys_role_id",referencedColumnName = "role_id")}
    )
    private Set roles = new HashSet();

    public Long getUserId() {
        return userId;
    }

    public void setUserId(Long userId) {
        this.userId = userId;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Set getRoles() {
        return roles;
    }

    public void setRoles(Set roles) {
        this.roles = roles;
    }
}
package com.itheima.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 roleId;
    @Column(name = "role_name")
    private String roleName;

    //配置多对多
    @ManyToMany(mappedBy = "roles")  //配置多表关系
    private Set users = new HashSet();

    public Long getRoleId() {
        return roleId;
    }

    public void setRoleId(Long roleId) {
        this.roleId = roleId;
    }

    public String getRoleName() {
        return roleName;
    }

    public void setRoleName(String roleName) {
        this.roleName = roleName;
    }

    public Set getUsers() {
        return users;
    }

    public void setUsers(Set users) {
        this.users = users;
    }
}

6.2测试

package com.itheima.test;

import com.itheima.dao.RoleDao;
import com.itheima.dao.UserDao;
import com.itheima.domain.Role;
import com.itheima.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 ManyToManyTest {

    @Autowired
    private UserDao userDao;
    @Autowired
    private RoleDao roleDao;

    /**
     * 保存一个用户,保存一个角色
     *
     *  多对多放弃维护权:被动的一方放弃
     */
    @Test
    @Transactional
    @Rollback(false)
    public void  testAdd() {
        User user = new User();
        user.setUserName("小李");

        Role role = new Role();
        role.setRoleName("java程序员");

        //配置用户到角色关系,可以对中间表中的数据进行维护     1-1
        user.getRoles().add(role);

        //配置角色到用户的关系,可以对中间表的数据进行维护     1-1
        role.getUsers().add(user);

        userDao.save(user);
        roleDao.save(role);
    }


    //测试级联添加(保存一个用户的同时保存用户的关联角色)
    @Test
    @Transactional
    @Rollback(false)
    public void  testCasCadeAdd() {
        User user = new User();
        user.setUserName("小李1");

        Role role = new Role();
        role.setRoleName("java程序员1");

        //配置用户到角色关系,可以对中间表中的数据进行维护     1-1
        user.getRoles().add(role);

        //配置角色到用户的关系,可以对中间表的数据进行维护     1-1
        role.getUsers().add(user);

        userDao.save(user);
    }

    /**
     * 案例:删除id为1的用户,同时删除他的关联对象
     */
    @Test
    @Transactional
    @Rollback(false)
    public void  testCasCadeRemove() {
        //查询1号用户
        User user = userDao.findOne(1l);
        //删除1号用户
        userDao.delete(user);

    }
}

 

你可能感兴趣的:(Java,SpringData,JPA,maven)