SpringDataJpa (二)-动态查询&多表操作

  • 一.动态查询
    • 1.Specifications动态查询
      • 1.1 搭建测试环境
        • 1.1.1 导入坐标
        • 1.1.2 创建客户实体类
        • 1.1.3 springdatajpa 核心配置文件
        • 1.1.4 编写dao接口
        • 1.1.5 案列测试代码
          • 1.1.5.1 查询所有
          • 1.1.5.2 多条件查询
          • 1.1.5.3 模糊查询
          • 1.1.5.4 Sort排序
          • 1.1.5.5 pageable分页
    • 2.多表查询(一对多)
      • 2.1.配置环境
        • 2.1.1 新建一个工程,添加两个表的类并配置映射关系
        • 2.1.2 测试保存操作
      • 2.2 级联
        • 2.2.1 级联添加
        • 2.2.2 级联删除
    • 3.多对多
      • 3.1 配置环境
      • 3.2 测试保存代码
      • 3.3 多对多放弃维护权
      • 3.4 多对多级联操作
    • 4. 对象导航查询

一.动态查询

1.Specifications动态查询

继承的是JpaSpecificationExecutor接口
方法列表:
1.findone(Specification spec)
2.List findAll(Specification spec)
Pageable 查询全部分页
3.Page findAll(Specification spec,Pageable pageable)
Sort 排序
4…List findAll(Specification spec,Sort sort)
5.long count(Specification spec)

Specification(是一个接口):查询条件
需要自定义我们自己的Specification实现类
需要实现以下方法:
Predicate toPredicate (Root root,CriteriaQuery<?> query,CriteriaBuilder cb)
其中的参数:
1.root:查询的根对象(查询的任何属性都可以从跟根对象中获取)
2.CriteriaQuery:顶层查询对象,自定义查询方法(了解,一般不用)
3.CriteriaBuilder
查询的构造器,封装很多查询条件

1.1 搭建测试环境

1.1.1 导入坐标

    <properties><spring.version>4.2.4.RELEASE</spring.version><hibernate.version>5.0.7.Final</hibernate.version><slf4j.version>1.6.6</slf4j.version><log4j.version>1.2.12</log4j.version><c3p0.version>0.9.1.2</c3p0.version><mysql.version>5.1.6</mysql.version></properties><dependencies><!-- junit单元测试 --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.9</version><scope>test</scope></dependency><!-- spring beg --><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.6.8</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-aop</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context-support</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-orm</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-beans</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>${spring.version}</version></dependency><!-- spring end --><!-- hibernate beg --><dependency><groupId>org.hibernate</groupId><artifactId>hibernate-core</artifactId><version>${hibernate.version}</version></dependency><dependency><groupId>org.hibernate</groupId><artifactId>hibernate-entitymanager</artifactId><version>${hibernate.version}</version></dependency><dependency><groupId>org.hibernate</groupId><artifactId>hibernate-validator</artifactId><version>5.2.1.Final</version></dependency><!-- hibernate end --><!-- c3p0 beg --><dependency><groupId>c3p0</groupId><artifactId>c3p0</artifactId><version>${c3p0.version}</version></dependency><!-- c3p0 end --><!-- log end --><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>${log4j.version}</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>${slf4j.version}</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId><version>${slf4j.version}</version></dependency><!-- log end --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>${mysql.version}</version></dependency><dependency><groupId>org.springframework.data</groupId><artifactId>spring-data-jpa</artifactId><version>1.9.0.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>4.2.4.RELEASE</version></dependency><!-- el beg 使用spring data jpa 必须引入 --><dependency><groupId>javax.el</groupId><artifactId>javax.el-api</artifactId><version>2.2.4</version></dependency><dependency><groupId>org.glassfish.web</groupId><artifactId>javax.el</artifactId><version>2.2.4</version></dependency><dependency><groupId>javax.xml.bind</groupId><artifactId>jaxb-api</artifactId><version>2.3.0</version></dependency><dependency><groupId>com.sun.xml.bind</groupId><artifactId>jaxb-impl</artifactId><version>2.3.0</version></dependency><dependency><groupId>com.sun.xml.bind</groupId><artifactId>jaxb-core</artifactId><version>2.3.0</version></dependency><dependency><groupId>javax.activation</groupId><artifactId>activation</artifactId><version>1.1.1</version></dependency><!-- el end --></dependencies><build><pluginManagement><plugins><!--jdk编译插件--><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.8.0</version><configuration><source>1.8</source><target>1.8</target><encoding>utf-8</encoding></configuration></plugin><!--tomcat插件--><plugin><groupId>org.apache.tomcat.maven</groupId><!-- tomcat7的插件, 不同tomcat版本这个也不一样 --><artifactId>tomcat7-maven-plugin</artifactId><version>2.1</version><configuration><!-- 通过maven tomcat7:run运行项目时,访问项目的端口号 --><port>80</port><!-- 项目访问路径  本例:localhost:9090,  如果配置的aa, 则访问路径为localhost:9090/aa--><path>/travel</path></configuration></plugin></plugins></pluginManagement></build>

1.1.2 创建客户实体类

@Entity
@Table(name="cst_customer")
public class Customer {@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_industry")private String custIndustry; //客户级别@Column(name = "cust_level")private String custLevel;  //客户所属行业@Column(name = "cust_address")private String custAddress; //客户地址@Column(name = "cust_phone")private String custPhone; //客户联系方式

1.1.3 springdatajpa 核心配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"xmlns:context="http://www.springframework.org/schema/context"xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:tx="http://www.springframework.org/schema/tx"xmlns:jpa="http://www.springframework.org/schema/data/jpa" xmlns:task="http://www.springframework.org/schema/task"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsdhttp://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsdhttp://www.springframework.org/schema/data/jpahttp://www.springframework.org/schema/data/jpa/spring-jpa.xsd"><bean id="dataSources" class="com.mchange.v2.c3p0.ComboPooledDataSource"><property name="driverClass" value="com.mysql.jdbc.Driver" /><property name="jdbcUrl" value="jdbc:mysql:///jpa" /><property name="user" value="root" /><property name="password" value="root" /></bean>
<!--1.创建entityManagerfactory对象交给spring容器管理--><bean id="entityManager" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"><property name="dataSource" ref="dataSources"></property>
<!--        2.配置的是扫描的包,实体类所在包--><property name="packagesToScan" value="cn.xkm.domain"></property>
<!--        3.jpa实现厂家--><property name="persistenceProvider"><bean class="org.hibernate.jpa.HibernatePersistenceProvider"></bean></property><!--JPA的供应商适配器--><property name="jpaVendorAdapter"><bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<!--            配置是否自动创建数据库表--><property name="generateDdl" value="false" />
<!--            指定数据库类型--><property name="database" value="MYSQL" />
<!--            数据库方言,支持的特有语法--><property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" /><property name="showSql" value="true" /></bean></property>
<!--        jpa的方言:高级的特性--><property name="jpaDialect"><bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"></bean></property></bean><!--    整合springdatajpa--><jpa:repositories base-package="cn.xkm.dao" transaction-manager-ref="transactionManager"entity-manager-factory-ref="entityManager"></jpa:repositories><bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"><property name="entityManagerFactory" ref="entityManager"></property></bean>
<!--    spring声明式事务,此处省略-->
<!--    注解包扫描--><context:component-scan base-package="cn.xkm"></context:component-scan>
</beans>

1.1.4 编写dao接口

public interface Customer extends JpaRepository<cn.xkm.domain.Customer,Long>, JpaSpecificationExecutor<cn.xkm.domain.Customer> {}

1.1.5 案列测试代码

1.1.5.1 查询所有
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class SpecTest {@Autowiredprivate CustomerDao customerDao;@Testpublic void testSpec(){//       匿名内部类
//       自定义查询条件Specification<Customer> spec = new Specification<Customer>(){@Overridepublic Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {//               1.获取比较的属性Path<Object> custName = root.get("custName");
//               2.构造查询Predicate xkm = criteriaBuilder.equal(custName, "xkm");return xkm;}};List<Customer> all = customerDao.findAll(spec);all.forEach(a-> System.out.println(a));}
}
1.1.5.2 多条件查询
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class SpecTest {@Autowiredprivate CustomerDao customerDao;@Testpublic void testSpec(){//       匿名内部类
//       自定义查询条件Specification<Customer> spec = new Specification<Customer>(){@Overridepublic Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {//               1.获取比较的属性Path<Object> custName = root.get("custName");Path<Object> custIndustry = root.get("custIndustry");
//               2.构造查询Predicate xkm = criteriaBuilder.equal(custName, "xkm");Predicate boss = criteriaBuilder.equal(custIndustry, "Boss");Predicate and = criteriaBuilder.and(xkm, boss);return and;}};Customer one = customerDao.findOne(spec);System.out.println(one);}
}
1.1.5.3 模糊查询
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class SpecTest {@Autowiredprivate CustomerDao customerDao;@Testpublic void testSpec(){//       匿名内部类
//       自定义查询条件Specification<Customer> spec = new Specification<Customer>(){@Overridepublic Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {//               1.获取比较的属性Path<Object> custName = root.get("custName");Predicate like = criteriaBuilder.like(custName.as(String.class), "x%");return like;}};List<Customer> all = customerDao.findAll(spec);all.forEach(a -> System.out.println(all));}
1.1.5.4 Sort排序
       Sort sort = new Sort(Sort.Direction.DESC,"custId");List<Customer> all = customerDao.findAll(spec,sort);for (Customer customer : all) {System.out.println(customer);}
1.1.5.5 pageable分页
       Pageable pageable = new PageRequest(0, 2);Page<Customer> all = customerDao.findAll(spec, pageable);for (Customer customer : all) {System.out.println(customer);}
//       获取结果列表System.out.println(all.getContent());
//       获取当前页总数System.out.println(all.getTotalPages());
//       获取总结果数System.out.println(all.getTotalElements());}

2.多表查询(一对多)

2.1.配置环境

2.1.1 新建一个工程,添加两个表的类并配置映射关系

//配置客户和联系人之间的关系
//    @OneToMany(targetEntity = LinkMan.class)
//    name:配置外键字段名称
//    referencedColumnNam:对应的主键字段名
//    @JoinColumn(name = "lkm_cusr_id",referencedColumnName = "cust_id")@OneToMany(mappedBy = "customer")//放弃外键维护权,mappedBy:对配置关系的属性名private Set<LinkMan> linkmans  = new HashSet<>();
    @ManyToOne(targetEntity = Customer.class,fetch = FetchType.LAZY)@JoinColumn(name = "lkm_cust_id",referencedColumnName = "cust_id")private Customer customer;

2.1.2 测试保存操作

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class SpecTest {@Autowiredprivate CustomerDao customerDao;@Autowiredprivate LinkManDao linkManDao;@Test@Transactional@Rollback(false)public void saveTest(){Customer customer = new Customer();customer.setCustName("向科铭");LinkMan linkMan = new LinkMan();linkMan.setLkmName("美国队长");
//       建立客户和联系人的关系
//       customer.getLinkmans().add(linkMan);linkMan.setCystomer(customer);customerDao.save(customer);linkManDao.save(linkMan);}
}

2.2 级联

概述:
1.级联添加:当我保存一个客户的同时保存联系人
2.级联删除:当我删除一个客户的同时删除联系人

级联操作:
1.需要区分操作主体
2.需要需要在操作主体的实体类上,添加级联属性(需要添加到多表映射关系的注解上)
3.cascade(配置级联)

2.2.1 级联添加

在多表中添加cascade = CascadeType.ALL属性,然后测试代码配置好关系保存客户即可

  @OneToMany(mappedBy = "customer" ,cascade = CascadeType.ALL)private Set<LinkMan> linkmans  = new HashSet<>();
    public void saveTest(){Customer customer = new Customer();customer.setCustName("向科铭");LinkMan linkMan = new LinkMan();linkMan.setLkmName("美国队长");
//       建立客户和联系人的关系linkMan.setCustomer(customer);customer.getLinkmans().add(linkMan);customerDao.save(customer);

2.2.2 级联删除

配置好以上关系后,查询出来删除

  public void saveTest(){Customer one = customerDao.findOne(1l);customerDao.delete(one);}

3.多对多

3.1 配置环境

两个表,分别配置好关系

//    中间表的名称@ManyToMany(targetEntity = User.class)@JoinTable(name = "sys_userandrole",
//            当前对象在中间表中的外键
//            name 设置中间表对应的字段名joinColumns ={@JoinColumn(name = "sys_roleid",referencedColumnName = "role_id")},
//            对方表在中间表的外键inverseJoinColumns = {@JoinColumn(name = "sys_userid",referencedColumnName = "user_id")})private Set<User> users = new HashSet<>();
         @ManyToMany(targetEntity = Role.class)@JoinTable(name = "sys_userandrole",
//            当前对象在中间表中的外键
//            name 设置中间表对应的字段名joinColumns ={@JoinColumn(name = "sys_userid",referencedColumnName = "user_id")},
//            对方表在中间表的外键inverseJoinColumns = {@JoinColumn(name = "sys_roleid",referencedColumnName = "role_id")})private Set<Role> roles = new HashSet<>();

3.2 测试保存代码

 @Test@Transactional@Rollback(false)public void saveTest(){User user = new User();Role role = new Role();user.setUserName("向科铭");role.setRoleName("老板");//添加关系user.getRoles().add(role);userDao.save(user);roleDao.save(role);}

3.3 多对多放弃维护权

原则:谁被动被选择谁放弃
删除中间表的配置,再配置自己再对方的映射set集合名称

//    对方映射关系set集合的名称@ManyToMany(mappedBy = "roles")private Set<User> users = new HashSet<>();

3.4 多对多级联操作

原则:确认主体,再主体的类上加上级联操作cascade = CascadeType.ALL

         @ManyToMany(targetEntity = Role.class,cascade = CascadeType.ALL)@JoinTable(name = "sys_userandrole",
//            当前对象在中间表中的外键
//            name 设置中间表对应的字段名joinColumns ={@JoinColumn(name = "sys_userid",referencedColumnName = "user_id")},
//            对方表在中间表的外键inverseJoinColumns = {@JoinColumn(name = "sys_roleid",referencedColumnName = "role_id")})private Set<Role> roles = new HashSet<>();

级联删除

   public void saveTest(){User one = userDao.findOne(1l);userDao.delete(one);}

4. 对象导航查询

概述:通过一个对象通过get方法将关联对象也查询出来,
(一对多,只需要查询出1的内容,可以getLinkmeans()得到对应的多内容,默认是延迟加载)
(多对一,只要查出多的内容再get一的方法即可,默认是立即加载)

  @Test@Transactional@Rollback(false)public void saveTest(){Customer one = customerDao.getOne(1l);Set<LinkMan> linkmans = one.getLinkmans();for (LinkMan linkman : linkmans) {System.out.println(linkman);}}

注:对象导航查询 一查多默认使用的是延迟加载的形式查询的
调用get方法不会立即发送查询,而是在使用关联对象的时候才会查询。

修改配置:添加以下配置开启立即加载(不推荐使用)
fetch = FetchType.EAGER
(FetchType.LAZY 延迟加载)

    @OneToMany(mappedBy = "customer" ,cascade = CascadeType.ALL,fetch = FetchType.EAGER)private Set<LinkMan> linkmans  = new HashSet<>();

SpringDataJpa (二)-动态查询多表操作相关推荐

  1. Django08:模型层(ORM)--测试脚本/必知的13条/神器的双下划线查询/多表操作

    单表操作 django 自带的sqlite3数据库对日期格式不是很敏感,处理的时候容易出错. 测试脚本 测试环境准备:去manage.py 中拷贝钱四行代码,然后自己手写两行. 脚本无论在引用下面,还 ...

  2. HBase性能优化方法总结(二):写表操作

    2. 写表操作 2.1 多HTable并发写 创建多个HTable客户端用于写操作,提高写数据的吞吐量,一个例子: static final Configuration conf = HBaseCon ...

  3. oracle 锁表查询和解表操作

    数据库操作语句的分类 DDL:数据库模式定义语言,关键字:create DML:数据操纵语言,关键字:Insert.delete.update DCL:数据库控制语言 ,关键字:grant.remov ...

  4. Django学习手册 - ORM 数据创建/表操作 汇总

    ORM 查询的数据类型: QuerySet与惰性机制(可以看作是一个列表) 所谓惰性机制:表名.objects.all()或者.filter()等都只是返回了一个QuerySet(查询结果集对象),它 ...

  5. Mybatis Plus 连表操作及分页

    collection 关键词多对多查询 一. 1.当子查询接收一个参数时: 不涉及具体的名称映射,名字可以任意 2.当子查询接受多个参数时: {自定义参数名称1=数据库字段名称1, 自定义参数名称2= ...

  6. 查询所有表、索引、视图信息的SQL语句-Mysql/oracle/sql server的不同实现方式

    注:所有查询默认在管理员用户下进行 ----------------------------------Mysql中------------------------------------------ ...

  7. 6.7 交互式动态查询窗体

    目录 1.创建交互式动态查询窗体 2.建立交互操作窗体 3.建立一个带条件的查询 4.添加一个显示结果的子窗体 5.设置组合框更新后事件 1.创建交互式动态查询窗体 参数查询是一种交互式动态查询,在输 ...

  8. pgsql查表名_PostgreSQL如何查询所有表名

    PostgreSQL如何查询所有表名 查询PostgreSQL所有表名有2种方式,一种是工具提供的\d命令,另一种就是使用SQL语句进行查询了,具体方法如下. 方法一:通过命令行查询 \d 数据库 - ...

  9. mysql循环查询一个表中的数据并进行修改_JavaScript学习笔记(二十四)-- MYSQL基础操作...

    MYSQL mysql 是一个数据库的名字 和 php 合作的比较好的数据库 之前我们说过一个问题,前端向后端索要数据,后端就是去数据库中查询数据,返回给前端 接下来就聊聊使用 php 操作数据库 M ...

最新文章

  1. ie 6 对注释标记的一个不稳定的错误
  2. 计算机室活动实施方案,微机室活动计划
  3. python画图代码turtle-Python使用Turtle图形函数画图 颜色填充!
  4. 亚洲杯:打平韩国即可小组第一 国足会继续带来惊喜吗?
  5. 牛客假日团队赛1 B
  6. 用python发送email
  7. Java连接Elasticsearch6.xxx 高级检索篇三
  8. SQLserver2012 修改数据库架构
  9. 0.96寸OLED 屏幕SSD1306驱动四脚原理图PDF
  10. Modelica运算符
  11. 麒麟V10系统-系统激活点击按钮无响应
  12. java web 小学期实训小节
  13. MySQL、JDBC、HTML、CSS、JavaScript、jQuery、tomcat、Http、Servlet、JSP、EL、JSTL、Maven、Cookie、Session(框架第一部分)
  14. 程序员如何营销自己?
  15. 计算机技术的发展包括几个阶段,目前电子计算机处于哪个阶段?计算机发展的四个阶段...
  16. Swift——自定义转场动画(一)
  17. 电信天翼云搭建Halo博客
  18. 计算机网络的发展历史
  19. CSDN如何搜索用户名/博客名
  20. Oracle本地管理的表空间

热门文章

  1. 一文彻底弄懂工厂模式(Factory)
  2. 使用国密算法签名PDF文件
  3. wechall靶场training系列通关记录
  4. 美国TSCA 法案管控产品中的几种PBT化学品
  5. Ensight后处理软件显示网格
  6. 基于Arduino的无接触式智能门锁(RFID和蓝牙开锁)
  7. 2019软科计算机中国排名,权威发布:2019软科中国最好学科排名
  8. 搞线上渠道推广实操这么些年了
  9. 考虑下面特殊的整数线性规划问题max求和 求和 为非负整数
  10. 线上支付、线下支付的功能对比