智销系统项目day1 - 基础配置和SpringDataJpa
2019-07-04 21:09
190 查看
版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_42439165/article/details/94646975
2. JpaSpecificationExecutor认识 3. spec插件 3.2 在Maven中引入相应的包 4. Query查询条件
文章目录
- 1. 创建项目的基础配置
- 1.1 引入项目中所需要的所有包(pom.xml)
- 1.2 配置applicationContext.xml文件
- 1.3 准备Domain
- 1.4 完成Repository的功能
- 1.5 测试集成是否成功
1. 创建项目的基础配置
1.1 引入项目中所需要的所有包(pom.xml)
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>cn.itsource</groupId> <artifactId>yxb</artifactId> <version>1.0-SNAPSHOT</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <org.springframework.version>4.2.5.RELEASE</org.springframework.version> <org.hibernate.version>4.3.8.Final</org.hibernate.version> <spring-data-jpa.version>1.9.0.RELEASE</spring-data-jpa.version> <com.fasterxml.jackson.version>2.5.0</com.fasterxml.jackson.version> <org.slf4j.version>1.6.1</org.slf4j.version> </properties> <dependencies> <!-- Spring的支持包 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${org.springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${org.springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>${org.springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>${org.springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${org.springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>${org.springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${org.springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${org.springframework.version}</version> <scope>test</scope> </dependency> <!-- 引入web前端的支持 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${org.springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${org.springframework.version}</version> </dependency> <!-- SpringMCV上传需要用到io包--> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-io</artifactId> <version>1.3.2</version> </dependency> <!-- 文件上传用到的包 --> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.2.2</version> </dependency> <!-- SpringMVC的json支持包 --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>${com.fasterxml.jackson.version}</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>${com.fasterxml.jackson.version}</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>${com.fasterxml.jackson.version}</version> </dependency> <!-- hibernate的支持包 --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>${org.hibernate.version}</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-entitymanager</artifactId> <version>${org.hibernate.version}</version> </dependency> <!-- SpringData的支持包 --> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-jpa</artifactId> <version>${spring-data-jpa.version}</version> </dependency> <!-- SpringData的擴展包 --> <dependency> <groupId>com.github.wenhao</groupId> <artifactId>jpa-spec</artifactId> <version>3.1.1</version> <!-- 把所有的依賴都去掉 --> <exclusions> <exclusion> <groupId>*</groupId> <artifactId>*</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>commons-dbcp</groupId> <artifactId>commons-dbcp</artifactId> <version>1.2.2</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.6</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.5</version> </dependency> <!-- 測試包 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <!-- 这个scope 只能作用在编译和测试时,同时没有传递性。表示在运行的时候不添加此jar文件 --> <scope>provided</scope> </dependency> <!-- 日志文件 --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${org.slf4j.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>${org.slf4j.version}</version> <scope>runtime</scope> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.14</version> </dependency> <!-- 代码生成器模版技术 --> <dependency> <groupId>org.apache.velocity</groupId> <artifactId>velocity</artifactId> <version>1.6</version> </dependency> <!-- shiro的支持包 --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-all</artifactId> <version>1.4.0</version> <type>pom</type> </dependency> <!-- shiro与Spring的集成包 --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.4.0</version> </dependency> <!-- poi支持的jar包 --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>3.11</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>3.11</version> </dependency> <!-- 图片压缩功能 --> <!-- 缩略图 --> <dependency> <groupId>net.coobird</groupId> <artifactId>thumbnailator</artifactId> <version>0.4.6</version> </dependency> <!-- 定时调度 --> <dependency> <groupId>quartz</groupId> <artifactId>quartz</artifactId> <version>1.5.2</version> </dependency> <!-- 邮件支持 --> <dependency> <groupId>javax.mail</groupId> <artifactId>mail</artifactId> <version>1.4.1</version> </dependency> </dependencies> <build> <finalName>yxb</finalName> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> <plugin> <groupId>org.mortbay.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <version>8.1.15.v20140411</version> <configuration> <stopPort>9966</stopPort> <stopKey>foo</stopKey> <webAppConfig> <contextPath>/</contextPath> </webAppConfig> </configuration> </plugin> </plugins> </build> </project>
1.2 配置applicationContext.xml文件
注意:修改相应的包扫描(每个系统都会有不一样的地方)
里面的路径需要注意不要配错,建表策略为false
<?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:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jpa="http://www.springframework.org/schema/data/jpa" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd"> <!-- 扫描service部分的包 --> <context:component-scan base-package="com.zpx.domain" /> <context:property-placeholder location="classpath:jdbc.properties" /> <!-- 配置连接池 --> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <!--连接数据4个属性 --> <property name="driverClassName" value="${jdbc.driverClassName}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> <!--maxActive: 最大连接数量 --> <property name="maxActive" value="150" /> <!--minIdle: 最小空闲连接 --> <property name="minIdle" value="5" /> <!--maxIdle: 最大空闲连接 --> <property name="maxIdle" value="20" /> <!--initialSize: 初始化连接 --> <property name="initialSize" value="30" /> <!-- 用来配置数据库断开后自动连接的 --> <!-- 连接被泄露时是否打印 --> <property name="logAbandoned" value="true" /> <!--removeAbandoned: 是否自动回收超时连接 --> <property name="removeAbandoned" value="true" /> <!--removeAbandonedTimeout: 超时时间(以秒数为单位) --> <property name="removeAbandonedTimeout" value="10" /> <!--maxWait: 超时等待时间以毫秒为单位 1000等于60秒 --> <property name="maxWait" value="1000" /> <!-- 在空闲连接回收器线程运行期间休眠的时间值,以毫秒为单位. --> <property name="timeBetweenEvictionRunsMillis" value="10000" /> <!-- 在每次空闲连接回收器线程(如果有)运行时检查的连接数量 --> <property name="numTestsPerEvictionRun" value="10" /> <!-- 1000 * 60 * 30 连接在池中保持空闲而不被空闲连接回收器线程 --> <property name="minEvictableIdleTimeMillis" value="10000" /> <property name="validationQuery" value="SELECT NOW() FROM DUAL" /> </bean> <!-- 集成hibernate的jpa功能 --> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="dataSource" ref="dataSource" /> <!--待扫描的实体类包,不再需要persistence.xml了 --> <property name="packagesToScan" value="com.zpx.domain" /> <!-- 3.配置JPA的实现 --> <!-- private JpaVendorAdapter jpaVendorAdapter; --> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> <!-- org.springframework.orm.jpa.vendor.AbstractJpaVendorAdapter --> <!-- private boolean showSql = false;是否显示sql语句 --> <property name="showSql" value="true" /> <!-- private boolean generateDdl = false;是否建表 --> <property name="generateDdl" value="false" /> <!-- private String databasePlatform;原来方言 --> <property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" /> </bean> </property> </bean> <!-- Jpa 事务配置 --> <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="entityManagerFactory" /> </bean> <!-- 注解声明式事务管理 --> <tx:annotation-driven /> <!-- Spring Data Jpa配置 ********************************************--> <!-- base-package:扫描的包 --> <jpa:repositories base-package="com.zpx.repository" transaction-manager-ref="transactionManager" entity-manager-factory-ref="entityManagerFactory" /> </beans>
1.3 准备Domain
父类:BaseDomain
package com.zpx.domain; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.MappedSuperclass; //MappedSuperclass:表示当前类是父类 @MappedSuperclass // 在JPA里面就表示是父类,不持久化到表 public class BaseDomain { @Id @GeneratedValue protected Long id; public Long getId() { return id; } public void setId(Long id) { this.id = id; } }
子类Employee
@Entity @Table(name="employee") public class Employee extends BaseDomain { private String username; private String password; private String email; private Integer age; //省略getter,setter与toString(注意:Alt+Insert可以自动生成) }
1.4 完成Repository的功能
package com.zpx.repository; import com.zpx.domain.Employee; import org.springframework.data.jpa.repository.JpaRepository; /** * 必需继续JpaRepository<1v,2v> * 1v:代表你要操作的是哪一个domain对象 * 2v:这个domain对象的主键的类型 */ public interface EmployeeRepository extends JpaRepository<Employee, Long> { }
1.5 测试集成是否成功
package com.zpx.repository; import com.zpx.domain.Employee; ... @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext.xml") public class EmployeeRepositoryTest { @Autowired private EmployeeRepository employeeRepository; @Test public void testFind() throws Exception{ List<Employee> emps = employeeRepository.findAll(); for (Employee emp :emps){ System.out.println(emp); } } }
2. JpaSpecificationExecutor认识
- JpaSpecificationExecutor(JPA规则执行者)是JPA2.0提供的Criteria API的使用封装,可以用于动态生成Query来满足我们业务中的各种复杂场景。
- Spring Data JPA为我们提供了JpaSpecificationExecutor接口,只要简单实现toPredicate方法就可以实现复杂的查询。
public interface JpaSpecificationExecutor<T> { T findOne(Specification<T> spec); List<T> findAll(Specification<T> spec); Page<T> findAll(Specification<T> spec, Pageable pageable); List<T> findAll(Specification<T> spec, Sort sort); long count(Specification<T> spec); }
我们要使用这个接口中的方法,首先让我们的接口也去继承这个接口:
public interface EmployeeRepository extends JpaRepository<Employee,Long>,JpaSpecificationExecutor<Employee> { }
2.1 单个条件的查询
@Test public void testJpaSpecificationExecutor()throws Exception{ /* 根据相应的规则(Specification),查询对应的数据 Predicate:where xxx=? and yyy=? root:根,可以获取到类中的属性(xxx,yyy...) CriteriaQuery:查询哪些字段,排序是什么(主要是把多个查询的条件连系起来) CriteriaBuilder:字段之间是什么关系,如何生成一个查询条件,每一个查询条件都是什么方式 主要判断关系(和这个字段是相等,大于,小于like等) */ List<Employee> list = employeeRepository.findAll(new Specification<Employee>() { @Override public Predicate toPredicate(Root<Employee> root, CriteriaQuery<?> cq, CriteriaBuilder cb) { //使用root拿到相应的username属性 Path usernamePath = root.get("username"); //为属性添加查询规则 Predicate predicate = cb.like(usernamePath, "%1%"); return predicate; } }); list.forEach(e-> System.out.println(e)); }
2.2 多个条件查询
@Test public void testJpaSpecificationExecutor02()throws Exception{ List<Employee> list = employeeRepository.findAll(new Specification<Employee>() { @Override public Predicate toPredicate(Root<Employee> root, CriteriaQuery<?> cq, CriteriaBuilder cb) { //使用root拿到相应的username属性 Path usernamePath = root.get("username"); //为属性添加查询规则 Predicate p1 = cb.like(usernamePath, "%1%"); Path emailPath = root.get("email"); Predicate p2 = cb.like(emailPath, "%2%"); //gt大于的意思 Path agePath = root.get("age"); Predicate p3 = cb.gt(agePath, 20); //多个条件连接起来 Predicate predicate = cb.and(p1, p2, p3); return predicate; } }); list.forEach(e-> System.out.println(e)); }
2.3 查询+分页+排序
@Test public void testJpaSpecificationExecutor03()throws Exception{ Pageable pageable = new PageRequest(0,10); Sort sort = new Sort(Sort.Direction.DESC,"age"); Page<Employee> page = employeeRepository.findAll(new Specification<Employee>() { @Override public Predicate toPredicate(Root<Employee> root, CriteriaQuery<?> cq, CriteriaBuilder cb) { //使用root拿到相应的username属性 Path usernamePath = root.get("username"); //为属性添加查询规则 Predicate predicate = cb.like(usernamePath, "%1%"); return predicate; } }, pageable); page.forEach(e-> System.out.println(e)); }
3. spec插件
这是一个对于咱们刚才的动态生成Query功能的一个封装版,如果我们使用这个插件,在完成查询与分页的时候功能会简单不少。
基于Spring Data Jpa的动态查询库 https://github.com/wenhao/jpa-spec
3.1 功能介绍
- 兼容Spring Data Jpa 和JPA2.1接口。
- Equal/NotEqual/Like/NotLike/In/NotIn支持可变参数, Equal/NotEqual 支持空(Null)值。
- 每个条件支持关联查询。
- 支持自定义条件查询。
- 条件构建器。
- 支持分页和排序。
3.2 在Maven中引入相应的包
pom.xml(咱们项目中已经引入):
<!-- jpa的SpecificationSpecification功能封装 --> <dependency> <groupId>com.github.wenhao</groupId> <artifactId>jpa-spec</artifactId> <version>3.1.1</version> <!-- 把所有依赖都过滤 --> <exclusions> <exclusion> <groupId>*</groupId> <artifactId>*</artifactId> </exclusion> </exclusions> </dependency>
3.3 功能测试
3.3.1 单个条件查询
@Test public void testJpaSpac01()throws Exception{ //导包注意导入wenhao的包 //获取到查询的规则 Specification<Employee> spec = Specifications.<Employee>and() .like("username","%1%") .build(); //根据规则完成查询 List<Employee> list = employeeRepository.findAll(spec); list.forEach(e-> System.out.println(e)); }
3.3.2 多个条件查询
@Test public void testJpaSpec02()throws Exception{ //获取到查询的规则 Specification<Employee> spec = Specifications.<Employee>and() .like("username", "%1%") .like("email","%2%") .gt("age",20) .build(); //根据规则完成查询 List<Employee> list = employeeRepository.findAll(spec); list.forEach(e-> System.out.println(e)); }
3.3.3 条件+排序分页功能
@Test public void testJpaSpac03()throws Exception{ //先获取分页和排序对象 Sort sort = new Sort(Sort.Direction.valueOf("DESC"),"age"); Pageable pageable = new PageRequest(0,10,sort); //导包注意导入wenhao的包 //获取到查询的规则 Specification<Employee> spec = Specifications.<Employee>and() .like("username","%1%") // .like("email","%2%") // .gt("age",20) .build(); //根据规则完成查询 Page<Employee> page = employeeRepository.findAll(spec, pageable); page.forEach(e-> System.out.println(e)); }
Jpa-spec的功能还是比较简单实用的。其它一些功能,我们在项目用到再说相应的讲解。大家也可以去参照网络上相就的中文文档:
https://github.com/wenhao/jpa-spec/blob/master/docs/3.1.0_cn.md
https://www.w3cschool.cn/jpaspec/
4. Query查询条件
咱们每一个项目是做过高级查询与分页的,大家应该都清楚,查询的数据是从前端由客户输入(或者选择)传到后台的。那么,我们需要注意的情况有哪些呢?
- 用户传的数据有0-n个(我们需要去判断)
- 咱们必需要准备一个对象接收用户传过来的数据(使用Query对象)
- 分页的条件对我们来说也是封装到Query对象中的
接下来,我们要准备我们的Query对象:
4.1 BaseQuery:公共的分页条件
public abstract class BaseQuery { //当前页 private int currentPage = 1; //每条条数 private int pageSize = 10; //排序字段名(如果前台没有传字段名,代表不需要做排序) private String orderName; //排序的规则 private String orderType = "ASC"; //写个抽象方法去规范子类获取Specification对象的名称必需叫:createSpec public abstract Specification createSpec(); //创建排序对象 public Sort createSort(){ if(StringUtils.isNotBlank(orderName)){ //toUpperCase() 方法用于把字符串转换为大写。 return new Sort(Sort.Direction.valueOf(orderType.toUpperCase()),orderName); } return null; } public int getCurrentPage() { return currentPage; } //第一页从0开始计算 public int getJpaCurrentPage() { return currentPage-1; } public void setCurrentPage(int currentPage) { this.currentPage = currentPage; } public int getPageSize() { return pageSize; } public void setPageSize(int pageSize) { this.pageSize = pageSize; } public String getOrderName() { return orderName; } public void setOrderName(String orderName) { this.orderName = orderName; } public String getOrderType() { return orderType; } public void setOrderType(String orderType) { this.orderType = orderType; } }
4.2 EmployeeQuery:Employee特有的一些条件
public class EmployeeQuery extends BaseQuery { private String username; private String email; private Integer age; //返回咱们的查询条件 where username = ? @Override public Specification createSpec(){ /** * like方法两个参数 * 1.查询的字段 * 2.这个字段条件对应的值 * like方法三个参数 * 1.boolean false,这个查询不执行 * 2.查询的字段 * 3.这个字段条件对应的值 */ //抽取spac Specification<Employee> spec = Specifications.<Employee>and() .like(StringUtils.isNotBlank(username),"username", "%"+username+"%") .like(StringUtils.isNotBlank(email),"email", "%"+email+"%") .gt(age!=null,"age", age) .build(); return spec; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } }
4.3 功能测试
//wendao抽取的查询并分页功能 @Test public void testJpaSpecPageQuery()throws Exception{ EmployeeQuery query = new EmployeeQuery(); query.setUsername("1"); query.setOrderName("age"); query.setOrderType("DESC"); //调用被抽取的查询方法,拿到对象 Specification spec = query.createSpec(); //调用被抽取的分页方法,拿到对象 Sort sort = query.createSort(); //用sort创建page对象,并封装 Pageable pageable = new PageRequest(query.getJpaCurrentPage(), query.getPageSize(), sort); //查询全部,传入对象 Page<Employee> page = employeeRepository.findAll(spec, pageable); page.forEach(e-> System.out.println(e)); }
相关文章推荐
- 易用宝项目记录day1-springdatajpa
- Spring Boot + Spring Data JPA项目配置多数据源
- Spring Data JPA环境配置
- SPRING DATA JPA 中几种缓存的配置
- 使用spring-data-jpa的JpaRepository来进行类的db操作(配置)
- spring-data-jpa+hibernate 各种缓存的配置演示
- Spring Data JPA 的配置文件 已经数据库的状态
- J2EE项目系列(三)--Spring Data JPA+Spring+SpringMVC+Maven快速开发(1)项目架构
- SpringBoot连接SQLite数据库(基于Spring-Data-Jpa和Gradle配置)
- Spring Data Jpa 详解 (配置篇)
- SpringMVC+JPA+SpringData配置
- springMVC、spring、jpa、springData整合配置
- Spring Data JPA @EnableJpaRepositories配置详解
- SpringMVC+Spring Data JPA+Shiro+EasyUI简单权限管理系统
- SpringMVC+Spring Data JPA+Shiro+EasyUI简单权限管理系统
- 【系统学习SpringBoot】SpringBoot初遇Spring-Data-JPA
- Spring Data Jpa 详解 (配置篇)
- SpringMVC+JPA+SpringData配置
- 再说一下 坑爹的spring data jpa + mongodb + shiro的配置问题
- Spring Data Jpa 单表多条件删除配置