第三部分
复杂查询-SpecTest
package org.example.test;
import org.example.dao.CustomerDao;
import org.example.entity.Customer;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
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 SpecTest {
@Autowired
private CustomerDao customerDao;
/**
* 根据条件查询单个对象
*/
@Test
public void testSpec(){
/**匿名内部类
* 自定义查询条件
* 1、实现Specification接口(提供泛型,查询的对象类型)
* 2、实现toPredicate方法(构造查询条件)
* 3、需要借助方法参数中的两个参数(
* root:获取需要查询的对象属性
* CriteriaBuilder:构建查询条件
* )
*
* 查询条件 1、查询方式 cb对象
* 2、比较的属性 root对象
*/
Specification<Customer> spec = new Specification<Customer>() {
@Override
public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
return null;
}
};
customerDao.findOne(spec);
}
@Test
public void testSpec1(){
Specification<Customer> spec = (root,query,cb)->{
//1.获取比较的属性
Path<Object> custName = root.get("custName");
//2.构造查询条件
Predicate predicate = cb.equal(custName, "海之蓝");//进行精准匹配
return predicate;};
Customer one = customerDao.findOne(spec);
System.out.println(one);
}
@Test
public void testSpec2(){
Customer customer = customerDao.findOne((root, query, cb) -> {
//1.获取比较的属性
Path<Object> custName = root.get("custName");
//2.构造查询条件
Predicate predicate = cb.equal(custName, "海之蓝");//进行精准匹配 (比较的属性,比较的值)
return predicate;
});
System.out.println(customer);
}
/**
* 多条件查询
*/
@Test
public void testSpec3(){
Customer customer= customerDao.findOne((root,query,cb)->{
Path<Object> custName = root.get("custName");
Path<Object> custIndustry = root.get("custIndustry");
//条件1
Predicate con1 = cb.equal(custName, "青岛啤酒");
//条件2
Predicate con2 = cb.equal(custIndustry, "啤酒行业");
//连接多条件
Predicate predicate = cb.and(con1, con2);
return predicate;
});
System.out.println(customer);
}
/**
* 根据客户名 模糊查询 返回客户列表
* like gt lt le ge 得到path对象,根据path指定比较的参数类型,再去进行比较
* 指定参数类型:path.as(类型的字节码对象)
*/
@Test
public void testSpec4(){
Specification<Customer> spec = (root, query, builder) -> {
Path<Object> custName = root.get("custName");
Expression<String> expression = custName.as(String.class);
Predicate predicate = builder.like(expression, "%蓝");
return predicate;
};
List<Customer> list = customerDao.findAll(spec);
for (Customer customer : list) {
System.out.println(customer);
}
//添加排序条件
//第一个参数 排序方式(升,降序)
//第二个参数 排序的属性名称
Sort sort = new Sort(Sort.Direction.DESC,"custLevel" );
List<Customer> list1 = customerDao.findAll(spec, sort);
for (Customer customer : list1) {
System.out.println(customer);
}
}
/**
* 分页查询
* findAll(Specification,Pageable)
*/
@Test
public void testSpec5(){
//不给它条件
Specification<Customer> spec = null;
PageRequest pageRequest = new PageRequest(2, 5);
Page<Customer> pages = customerDao.findAll(spec, pageRequest);
System.out.println(pages.getTotalElements());//总条数
System.out.println(pages.getTotalPages());//总页数
System.out.println(pages.getNumber());//当前页码
System.out.println(pages.getNumberOfElements());//当前页 的实际条数
System.out.println(pages.getSize());//每页多少条
List<Customer> list = pages.getContent();
for (Customer customer : list) {
System.out.println(customer);
}
}
}
Customer.java
package org.example.entity;
import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;
/**
* @Entity声明实体类
* @Table配置实体类和表的映射关系
*/
@Entity
@Table(name = "cst_customer")
public class Customer {
/*
@Id :声明主键的配置
@GeneratedValue:配置主键的生成策略
strategy
GenerationType.IDENTITY 自增 (数据库要支持主键自增 mysql)
GenerationType.SEQUENCE 序列 (数据库要支持序列 oracle)
GenerationType.TABLE jpa提供的一种机制,通过一张数据库表的形式帮助完成主键自增
GenerationType.auto 由程序自动的帮我们选择主键生成策略
@Column 配置属性和字段的映射关系
name 数据库中字段的名称
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "cust_id")
private Long custId;
@Column(name = "cust_name")
private String custName;
@Column(name = "cust_source")
private String custSource;
@Column(name = "cust_level")
private String custLevel;
@Column(name = "cust_industry")
private String custIndustry;
@Column(name = "cust_phone")
private String custPhone;
@Column(name = "cust_address")
private String custAddress;
/**1、声明关系 一个客户有多个联系人
* @OneToMany 配置一对多关系
* targetEntity :目标关系的类对象
* 2、配置外键
*@JoinColumn
* name :当前外键字段
* referencedColumnName 当前外键参照主表的主键字段名称
* 一的一方添加了外键配置,对客户而言,具备了维护外键的作用
*/
/* @OneToMany(targetEntity = LinkMan.class)
@JoinColumn(name = "lkm_cust_id",referencedColumnName = "cust_id")
//注释此代码的目的是放弃外键维护权
mappedBy:多的一方 配置关系的属性名称
cascade :配置级联 (也可以设置多的一方的映射关系的注解上)
CascadeType.all 所有的crud (推荐)
merge 更新
PERSIST 保存
remove 删除
fetch:配置关联对象的加载方式
FetchType.EAGER 立即加载
FetchType.LAZY 懒加载
*/
@OneToMany(mappedBy = "customer",cascade = CascadeType.ALL)
private Set<LinkMan> linkMans = new HashSet<>();
public Long getCustId() {
return custId;
}
public void setCustId(Long custId) {
this.custId = custId;
}
public String getCustName() {
return custName;
}
public void setCustName(String custName) {
this.custName = custName;
}
public String getCustSource() {
return custSource;
}
public void setCustSource(String custSource) {
this.custSource = custSource;
}
public String getCustLevel() {
return custLevel;
}
public void setCustLevel(String custLevel) {
this.custLevel = custLevel;
}
public String getCustIndustry() {
return custIndustry;
}
public void setCustIndustry(String custIndustry) {
this.custIndustry = custIndustry;
}
public String getCustPhone() {
return custPhone;
}
public void setCustPhone(String custPhone) {
this.custPhone = custPhone;
}
public String getCustAddress() {
return custAddress;
}
public void setCustAddress(String custAddress) {
this.custAddress = custAddress;
}
public Set<LinkMan> getLinkMans() {
return linkMans;
}
public void setLinkMans(Set<LinkMan> linkMans) {
this.linkMans = linkMans;
}
@Override
public String toString() {
return "Customer{" +
"custId=" + custId +
", custName='" + custName + '\'' +
", custSource='" + custSource + '\'' +
", custLevel='" + custLevel + '\'' +
", custIndustry='" + custIndustry + '\'' +
", custPhone='" + custPhone + '\'' +
", custAddress='" + custAddress + '\'' +
", linkMans=" + linkMans +
'}';
}
}
LinkMan.java
package org.example.entity;
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;//联系人备注
/**
* 一个联系人属于一个客户
* 配置多对一关系
* 多的一方也会维护外键
*/
@ManyToOne(targetEntity = Customer.class,fetch = FetchType.LAZY)
@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 + '\'' +
'}';
}
}
LinkManDao.java
package org.example.dao;
import org.example.entity.LinkMan;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
public interface LinkManDao extends JpaRepository<LinkMan,Long>, JpaSpecificationExecutor<LinkMan> {
}
OneToManyTest.java
package org.example.test;
import org.example.dao.CustomerDao;
import org.example.dao.LinkManDao;
import org.example.entity.Customer;
import org.example.entity.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;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class OneToManyTest {
@Autowired
private CustomerDao customerDao;
@Autowired
private LinkManDao linkManDao;
@Test
@Transactional
@Rollback(value = false)
public void test1(){
Customer customer = new Customer();
customer.setCustLevel("白酒行业");
customer.setCustName("小糊涂");
LinkMan linkMan = new LinkMan();
linkMan.setLkmName("小王");
linkMan.setLkmGender("女");
/**
* 配置了客户到联系人的关系
* 两条insert,一条update
*/
customer.getLinkMans().add(linkMan);
customerDao.save(customer);
linkManDao.save(linkMan);
}
@Test
@Transactional
@Rollback(value = false)
public void test2(){
Customer customer = new Customer();
customer.setCustLevel("白酒行业");
customer.setCustName("小糊涂");
LinkMan linkMan = new LinkMan();
linkMan.setLkmName("小王");
linkMan.setLkmGender("女");
/**
* 多对一 只有两条insert语句
*/
linkMan.setCustomer(customer);
customerDao.save(customer);
linkManDao.save(linkMan);
}
@Test
@Transactional
@Rollback(value = false)
public void test3(){
Customer customer = new Customer();
customer.setCustLevel("白酒行业");
customer.setCustName("小糊涂");
LinkMan linkMan = new LinkMan();
linkMan.setLkmName("小王");
linkMan.setLkmGender("女");
/**
* 一到多 多发送一条update
* 由于一的一方可以维护外键,会发送update语句
* 解决此问题:只需要在一的一方放弃维护权即可
*/
customer.getLinkMans().add(linkMan);
/**
* 多对一 只有两条insert语句
*/
linkMan.setCustomer(customer);
customerDao.save(customer);
linkManDao.save(linkMan);
}
/**
* 级联添加 保存一个客户的同时保存客户的所有联系人
* 需要在操作主体的实体类上,配置casacde属性
*/
@Test
@Transactional
@Rollback(value = false)
public void test4(){
Customer customer = new Customer();
customer.setCustLevel("白酒行业");
customer.setCustName("小糊涂");
LinkMan linkMan = new LinkMan();
linkMan.setLkmName("小王");
linkMan.setLkmGender("女");
LinkMan man2 = new LinkMan();
man2.setLkmName("小yang");
man2.setLkmGender("男");
linkMan.setCustomer(customer);
man2.setCustomer(customer);
customer.getLinkMans().add(linkMan);
customer.getLinkMans().add(man2);
customerDao.save(customer);
}
/**
* 级联删除 删除一个客户的同时删除客户的所有联系人
* 需要在操作主体的实体类上,配置casacde属性
*/
@Test
@Transactional
@Rollback(value = false)
public void testDelete(){
Customer customer = customerDao.findOne(1L);
customerDao.delete(customer);
}
}
User.java
package org.example.entity;
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 = "user_age")
private Integer userAge;
/**
* 用户到角色的多对多关系
* 1、声明表关系配置
* @ManyToMany(targetEntity = Role.class)
* 2、配置中间表(包含两个外键)
* @JoinTable 配置中间表的名称
*
*/
@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<Role> roleSet = new HashSet<>();
@Override
public String toString() {
return "User{" +
"userId=" + userId +
", userName='" + userName + '\'' +
", userAge=" + userAge +
", roleSet=" + roleSet +
'}';
}
public Set<Role> getRoleSet() {
return roleSet;
}
public void setRoleSet(Set<Role> roleSet) {
this.roleSet = roleSet;
}
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 getUserAge() {
return userAge;
}
public void setUserAge(Integer userAge) {
this.userAge = userAge;
}
}
Role.java
package org.example.entity;
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 = "roleSet")
private Set<User> userSet = new HashSet<>();
@Override
public String toString() {
return "Role{" +
"roleId=" + roleId +
", roleName='" + roleName + '\'' +
", userSet=" + userSet +
'}';
}
public Set<User> getUserSet() {
return userSet;
}
public void setUserSet(Set<User> userSet) {
this.userSet = userSet;
}
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;
}
}
UserDao.java
package org.example.dao;
import org.example.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
public interface UserDao extends JpaRepository<User,Long> , JpaSpecificationExecutor<User> {
}
RoleDao.java
package org.example.dao;
import org.example.entity.Role;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
public interface RoleDao extends JpaRepository<Role,Long>, JpaSpecificationExecutor<Role> {
}
ManyToManyTest.java
package org.example.test;
import org.example.dao.RoleDao;
import org.example.dao.UserDao;
import org.example.entity.Role;
import org.example.entity.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;
/**
* 保存一个用户和一个角色
* 多对多放弃维护中间表的权力:谁被选择,谁被放弃,role被选择,role被放弃
*/
@Test
@Transactional
@Rollback(false)
public void testAdd(){
User user = new User();
user.setUserName("小王");
Role role = new Role();
role.setRoleName("普通用户");
//配置 用户->角色 的关系,可以对中间表中的数据进行维护
user.getRoleSet().add(role);
//配置 角色->用户 的关系,可以对中间表中的数据进行维护
role.getUserSet().add(user);
userDao.save(user);
roleDao.save(role);
}
/**
* 级联 保存一个user的同时,保存user的关联角色
*/
@Test
@Transactional
@Rollback(false)
public void testCascade(){
User user = new User();
user.setUserName("小王");
Role role = new Role();
role.setRoleName("普通用户");
//配置 用户->角色 的关系,可以对中间表中的数据进行维护
user.getRoleSet().add(role);
//配置 角色->用户 的关系,可以对中间表中的数据进行维护
role.getUserSet().add(user);
userDao.save(user);
}
/**
* 级联 删除id=1的user的同时,删除user的关联角色
*/
@Test
@Transactional
@Rollback(false)
public void testRemove(){
User user = userDao.findOne(1L);
userDao.delete(user);
}
}
ObjectQueryTest.java
package org.example.test;
import org.example.dao.CustomerDao;
import org.example.dao.LinkManDao;
import org.example.entity.Customer;
import org.example.entity.LinkMan;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;
import java.util.Iterator;
import java.util.Set;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class ObjectQueryTest {
@Autowired
private CustomerDao customerDao;
@Autowired
private LinkManDao linkManDao;
/**
* 测试对象导航查询
* 查询一个对象的时候,查询出它的关联对象
*/
@Test
@Transactional //解决 could not initialize proxy - no Session
public void testQuery1(){
Customer one = customerDao.getOne(1L);//
// Customer one = customerDao.findOne(1L);
Set<LinkMan> linkMans = one.getLinkMans();
Iterator<LinkMan> iterator = linkMans.iterator();
while (iterator.hasNext()){
LinkMan next = iterator.next();
System.out.println(next);
}
}
/**
* 测试对象导航查询
* 查询一个对象的时候,查询出它的关联对象
*/
@Test
@Transactional //解决 could not initialize proxy - no Session
public void testQuery2(){
Customer one = customerDao.findOne(1L);
Set<LinkMan> linkMans = one.getLinkMans();
Iterator<LinkMan> iterator = linkMans.iterator();
while (iterator.hasNext()){
LinkMan next = iterator.next();
System.out.println(next);
}
/**
* 默认使用的是延迟加载的方式查询的
* 调用get方法并不会立即发送查询sql,而是在使用关联对象的时候查询
*
*怎样使用立即查询
* 修改配置,fetch 需要配置到多表映射关系的注解上
* @OneToMany(mappedBy = "customer",cascade = CascadeType.ALL,
* fetch = FetchType.EAGER )
* 一般不建议使用 立即查询
*/
}
/**
* 测试对象导航查询
* 查询联系人的时候查询客户
* 从多的一方查询一的一方
* 默认加载方式:立即加载
*/
@Test
@Transactional
public void testQuery3() {
LinkMan one = linkManDao.findOne(2L);
Customer customer = one.getCustomer();
System.out.println(customer);
}
}
总结
以上就是今天学习的内容,喜欢的朋友们可以点赞,收藏,关注哦!感谢