SpringDataJpa

一.什么是SpringDataJpa前端

 

一.什么是SpringDataJpa

  • 它是Spring的一个子框架
  • 集成Jpa,让我们操做数据库变得更加的简单

二.项目导包

  • 可以看懂这里导入了哪些包
  • 也能够理解这些包是作什么的
<?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>aisell</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <name>aisell Maven Webapp</name> <!-- FIXME change it to the project's website --> <url>http://www.example.com</url> <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> <!-- SpringDataJpa的支持包 --> <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> <!--lang3:工具包 java.lang.--> <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>aisell</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> 

三 集成SpringDataJpa

3.1 完成Spring与Jpa的集成

昨天已经详细讲解过(要求本身是能够把它写出来)java

3.1.1 准备db.propeties

jdbc.driverClassName=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql:///aisell jdbc.username=root jdbc.password=123456 

3.2.2 准备applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" 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" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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 "> <!--扫描service层的类--> <context:component-scan base-package="cn.itsource.aisell.service" /> <!-- db.properties -> dataSource(配置数据源[链接池dbcp]) -> EntityManagerFactory -> dao -> service -> 事务 -> controller(集成SpringMVC) -> easyui --> <!--1.读取db.properties, 注意:不要忘了加classpath--> <context:property-placeholder location="classpath:db.properties" /> <!--2.配置dbcp链接池--> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="${jdbc.driverClassName}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> </bean> <!-- JPA:ORM规范 -> 不少框架实现了这个规范(hibernate,openjpa,toplink,...) 3.配置EntityManagerFactory对象 3.1 基本配置都是写在Spring中(四大金刚,建表策略,方言,是否显示SQL) 3.2 Spring来建立这个对象(准备一个domain,若是运行的时候建立了表,就表明这个对象是成功的) alt+insert -> JPA -> LocalContainerEntityManagerFactoryBean ctrl+t/f4 : 有办法看结构 --> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="dataSource" ref="dataSource"/> <!--扫描JPA支持的注解--> <property name="packagesToScan" value="cn.itsource.aisell.domain" /> <!-- 告诉Spring咱们使用的是哪个框架来完成JPA规范 这里就须要咱们配置一个适配器 jpaVendorAdapter:JPA须要配置的适配器(咱们会选择hibernate) --> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> <!--方言--> <property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" /> <!-- 建表策略 --> <property name="generateDdl" value="false" /> <!--是否显示sql--> <property name="showSql" value="true" /> </bean> </property> </bean> <!--4.加上事务--> <!--4.1 准备事务管理器--> <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="entityManagerFactory"/> </bean> <!--4.2 开启(注解)事务支持--> <tx:annotation-driven transaction-manager="transactionManager" /> </beans> 

3.2 集成SpringDataJpa

3.2.1 准备domain(父类)

  1. BaseDomain

jpa中父类domain必须要加上:@MappedSuperclassmysql

/** * 泛化:继承关系 * 在咱们JPA,若是要抽取一个父类,就必需加上 @MappedSuperclass * 很是明肯定的告诉JPA,这是一个用于映射的父类 */ @MappedSuperclass public class BaseDomain { @Id @GeneratedValue protected Long id; //getter,setter ... } 
  1. Employeee
@Entity @Table(name = "employee") public class Employee extends BaseDomain { private String username; private String password; private Integer age; private String email; //getter,setter ... } 

3.2.2 准备Repository接口

/** * 关于Employee对象的CRUD(分页排序) 就写完了 * 泛型一:对哪个实体作CRUD * 泛型二:主键的类型 */ public interface EmployeeRepository extends JpaRepository<Employee,Long> { ... } 

3.2.3 扫描repository

  • repository 就是我们过去的dao
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" ... xmlns:jpa="http://www.springframework.org/schema/data/jpa" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd ... http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd "> ... <!-- 让SpringDataJpa去扫描repository --> <jpa:repositories base-package="cn.itsource.aisell.repository" entity-manager-factory-ref="entityManagerFactory" transaction-manager-ref="transactionManager" /> </beans> 

四.完成的CRUD功能

4.1 基本的CRUD

  • 查询全部:employeeRepository.findAll()
  • 查询一条数据: employeeRepository.findOne(1L)
    • 思考题: findOne与getOne的区别?
  • 添加/修改: employeeRepository.save(employee)
    • 主要看数据库中是否有这个值
  • 删除 : employeeRepository.delete(274L)

4.2 分页和排序

4.2.1 排序

/** * 排序对象 * 第一个参数:排序的类型(升序仍是降序) * 第二个参数:排序的属性 */ Sort sort = new Sort(Sort.Direction.DESC,"age"); List<Employee> list = employeeRepository.findAll(sort); list.forEach(e-> System.out.println(e)); 

4.2.2 分页

注:这里的分页是从0开始的git

/** * page:第几页(0就是第1页) * size:每页条数 */ Pageable pageable = new PageRequest(0,10); //分页对象 Page<Employee> list = employeeRepository.findAll(pageable); list.forEach(e-> System.out.println(e)); 

4.2.3 分页+排序

Sort sort = new Sort(Sort.Direction.DESC,"age"); /** * page:第几页(0就是第1页) * size:每页条数 * sort:排序对象 */ Pageable pageable = new PageRequest(0,10,sort); //分页对象 Page<Employee> list = employeeRepository.findAll(pageable); list.forEach(e-> System.out.println(e)); 

4.3 名称规则(根据条件进行查询)

详细规则请查看文档github

/** * 根据规范(SpringDataJpa)写方法名,就能够进行查询 * @param username * @return * username =? */ //根据用户名查询一个员工 Employee findByUsername(String username); //用户名模糊查询 username like ? List<Employee> findByUsernameLike(String username); //用户名与邮件模糊查询 username like ? and email like ? List<Employee> findByUsernameLikeAndEmailLike(String username,String email); 

4.4 Query注解查询

//根据用户名获取用户 @Query("select o from Employee o where o.username =?1") Employee query01(String username); //用户名与邮件模糊查询 username like ? and email like ? @Query("select o from Employee o where o.username like ?1 and o.email like ?2") List<Employee> query02(String username,String email); // @Query("select o from Employee o where o.username like :username and o.email like :email") // List<Employee> query02(@Param("username") String username,@Param("email") String email); //直接写原生的SQL @Query(nativeQuery=true,value="select * from employee") List<Employee> query03(); 

五.JpaSpecificationExecutor

  • 是一个JPA的规范执行者
  • JPA2.0提供的Criteria API的使用封装
  • 须要我们的的repository继承JpaSpecificationExecutor接口
interface EmployeeRepository extends JpaRepository<Employee,Long>,JpaSpecificationExecutor<Employee> 

5.1 最简单的查询

@Test
public void testJpaSpecificationExecutor01() throws Exception{ /** * 这里的查询咱们须要本身去定义规则:Specification */ List<Employee> list = employeeRepository.findAll(new Specification<Employee>() { /** * 这个方法就是帮我们建立规则的方法,只要把这个方法搞定,我们就能够完成查询了 * @param root(根) : 表明了能够查询和操做的实体对象的根 * 能够帮助咱们获取到实体对应的字段 * @param query(查询) : 表明一个specific的顶层查询对象 * 包含查询的各个部分,好比select,from,where,group by ,order by 等 * 还能够支持and ,or的功能 * @param cb :用来构建CriteriaQuery的构建器对象(至关于条件或者说条件组合) * 主要判断关系(和这个字段是相等,大于,小于like等) * 支持 and,or的功能 * @return Predicate:代表; 阐明; 断言 * 你把它当成 where username like ? and email like ? and age > ? ... */ @Override public Predicate toPredicate(Root<Employee> root, CriteriaQuery<?> query, CriteriaBuilder cb) { //1.拿到Employee中的username字段 Path usernamePath = root.get("username"); //2.加上字段的判断关系 // 参数1:字段(表达式) 2.值 Predicate p1 = cb.like(usernamePath, "%1%"); return p1; } }); list.forEach(e-> System.out.println(e)); } 

5.2 多个条件查询

@Test
public void testJpaSpecificationExecutor02() throws Exception{ //Specification:查询规则 List<Employee> list = employeeRepository.findAll(new Specification<Employee>() { // root:拿到字段(表达式) cb:设置条件(>,<,=,like),and/or @Override public Predicate toPredicate(Root<Employee> root, CriteriaQuery<?> query, CriteriaBuilder cb) { //拿到username并设置条件 Path usernamePath = root.get("username"); Predicate p1 = cb.like(usernamePath, "%1%"); //拿到email并设置条件 Path emailPath = root.get("email"); Predicate p2 = cb.like(emailPath, "%2%"); //拿到age并设置条件 gt/lt:大于/小于 ge/le:大于等于/小等等于 Path agePath = root.get("age"); Predicate p3 = cb.gt(agePath, 18); //把条件结合起来 return cb.and(p1, p2, p3); } }); list.forEach(e-> System.out.println(e)); } 

5.3 查询+分页+排序

/** * 高级查询加分页 * @throws Exception */ @Test public void testJpaSpecificationExecutor03() throws Exception{ //建立一个分页对象 Pageable pageable = new PageRequest(1,10); //分页+高级查询 Page<Employee> page = employeeRepository.findAll(new Specification<Employee>() { @Override public Predicate toPredicate(Root<Employee> root, CriteriaQuery<?> query, CriteriaBuilder cb) { Path usernamePath = root.get("username"); return cb.like(usernamePath, "%1%"); } }, pageable); page.forEach(e->System.out.println(e)); } /** * 高级查询加分页+排序 * @throws Exception */ @Test public void testJpaSpecificationExecutor04() throws Exception{ Sort sort = new Sort(Sort.Direction.DESC,"age"); //建立一个分页对象 Pageable pageable = new PageRequest(0,10,sort); //分页+高级查询 Page<Employee> page = employeeRepository.findAll(new Specification<Employee>() { @Override public Predicate toPredicate(Root<Employee> root, CriteriaQuery<?> query, CriteriaBuilder cb) { Path usernamePath = root.get("username"); return cb.like(usernamePath, "%1%"); } }, pageable); page.forEach(e->System.out.println(e)); } 

六.jpa-spec

6.1 简单查询

注意:导的是:import com.github.wenhao.jpa.Specifications;web

//jpa-spec //完成我们的简单查询 username like ? @Test public void testJpaSpec01() throws Exception{ Specification<Employee> spec = Specifications.<Employee>and() .like("username", "%1%") .build(); List<Employee> list = employeeRepository.findAll(spec); list.forEach(e-> System.out.println(e)); } 

6.2 多条件查询

//jpa-spec //完成我们的简单查询 username like ? and email like ? and age>? @Test public void testJpaSpec02() throws Exception{ Specification<Employee> spec = Specifications.<Employee>and() .like("username", "%1%") .like("email","%2%") .gt("age",18) .build(); List<Employee> list = employeeRepository.findAll(spec); list.forEach(e-> System.out.println(e)); } 

6.3 多条件+分页

//jpa-spec //完成我们的简单查询 username like ? + 分页 + 排序 @Test public void testJpaSpec03() throws Exception{ //建立排序对象 Sort sort = new Sort(Sort.Direction.DESC,"age"); //建立分页对象 Pageable pageable = new PageRequest(0,10,sort); //规则对象(查询条件) Specification<Employee> spec = Specifications.<Employee>and() .like("username", "%1%") .build(); //功能执行 Page<Employee> page = employeeRepository.findAll(spec, pageable); page.forEach(e-> System.out.println(e)); } 

七.Query抽取

  • Query是我们的查询对象

7.1 BaseQuery

  • 有经验的人都会建立父类
    • 方便扩展
    • 公共的代码
    • 制定规范
  • 目前我们Query须要作的
    • 四个字段(currrentPage,pageSize,orderType,orderName)
    • 让每一个子类都有一个:createSpec()
    • 建立一个order对象
    • 解决了传过来的是当前页从1开始(SpringDataJpa是从0开始计算)
/** * 父类的做用: * 1.提供一些公共的属性的方法(少写代码) * 2.对子类造成相应的规范 * 3.为了之后代码的扩展性 */ public abstract class BaseQuery { //分页 -> 当前第几页 private int currentPage=1; //分页 -> 每页条数 private int pageSize=10; //排序 -> 排序的类型 true(DESC)/false(ASC) private boolean orderType; //排序 -> 排序的字段 -> 若是这个字段为null,就表明不排序 private String orderName; //建立排序对象 public Sort createSort(){ if(StringUtils.isNotBlank(orderName)){ //orderName有值才作排序 Sort sort = new Sort(orderType?Sort.Direction.DESC:Sort.Direction.ASC,orderName); return sort; } return null; } //要求只要继承了我,就必需有一个方法叫:createSpec() public abstract Specification createSpec(); public int getJpaPage() { return currentPage-1; } //getter,setter.... } 

7.2 EmployeeQuery

  • 设置当前对应的Domain的特有查询字段
  • 实现 createSpec()
/** * 员工查询 */ public class EmployeeQuery extends BaseQuery { //用户名 private String username; //邮件 private String email; //年龄 private Integer age; //查询的规则应该在查询对象中来建立 @Override public Specification createSpec(){ Specification<Employee> specification = Specifications.<Employee>and() .like(StringUtils.isNotBlank(username), "username", "%" + username + "%") .like(StringUtils.isNotBlank(email), "email", "%" + email + "%") .gt(age != null, "age", age) .build(); return specification; } //getter,setter... } 

7.3 测试spring

/** * 有Query的查询 * @throws Exception */ @Test public void testJpaSpec04() throws Exception{ //之后我们的查询数据是从前台传过来的,就会生成EmployeeQuery对象 EmployeeQuery query = new EmployeeQuery(); // query.setUsername("1"); // query.setEmail("2"); // query.setAge(18); query.setOrderName("age"); query.setOrderType(true); //建立排序对象 Sort sort = query.createSort(); //建立分页对象(分页对象从前台传过来) Pageable pageable = new PageRequest(query.getJpaPage(),query.getPageSize(),sort); //规则对象(查询条件) Specification<Employee> spec = query.createSpec(); //功能执行 Page<Employee> page = employeeRepository.findAll(spec, pageable); page.forEach(e-> System.out.println(e)); }
相关文章
相关标签/搜索