1.集成环境搭建
1.1 Maven项目导包
<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>
<!-- junit测试包 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!-- 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>
配置编译版本1.8
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
1.2 编辑配置文件
==applicationContext.xml==
<?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">
<!--开启注解扫描-->
<context:component-scan base-package="com.hanfengyi.pss.domain"/>
<!--配置连接池,加载资源文件-->
<context:property-placeholder location="classpath:db.properties"/>
<!--配置数据源-->
<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>
<!--配置EntityManagerFactory-->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<!--数据源-->
<property name="dataSource" ref="dataSource"/>
<!--开启扫描包-->
<property name="packagesToScan" value="com.hanfengyi.pss.domain"/>
<!--配置jpa的适配器,告诉spring使用哪一个适配器-->
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<!--配置建表策略,是否建表-->
<property name="generateDdl" value="false"/>
<!--配置方言信息-->
<property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect"/>
<!--配置是否显示sql-->
<property name="showSql" value="true"/>
</bean>
</property>
</bean>
<!--配置事务-->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<!--开启事务注解-->
<tx:annotation-driven/>
<!--配置spring-data-->
<jpa:repositories base-package="com.hanfengyi.pss.repository"
entity-manager-factory-ref="entityManagerFactory" transaction-manager-ref="transactionManager"/>
</beans>
==jdbc.properties==
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/pss
jdbc.username=root
jdbc.password=112334
2.创建domain层
@Entity
@Table(name = "employee")
public class Employee extends BaseDomain {
private String username;
private String password;
private String email;
private Integer age;
...(get/set/toString)
==抽取父类(BaseDao)==
@MappedSuperclass 标识其为父类,不会将该类当成实体类映射到数据库表,继承它的子类实体在映射时会自动扫描父类的映射属性添加到子类实体对应的数据库表中!
@MappedSuperclass
public class BaseDomain {
@Id
@GeneratedValue
private Long id;
3.创建repository层
SpringData提供了一整套对数据访问层(Dao)的解决方案,是对Jpa的再一次封装,提供了很多接口,可以使我们不写实现类,就能完成对数据层的访问和操作,提高了我们的开发效率。
JpaRepository是Repository体系下的一个子接口,具备分页和排序的功能。
自定义接口继承JpaRepository,必须配置泛型,第一个参数确定要操作的实体类,第二个参数表示主键类型。
public interface IEmployeeRepository extends JpaRepository<Employee,Long> {
}
4.测试
@Autowired
private IEmployeeRepository employeeRepository;
@Test
public void test(){
System.out.println(employeeRepository.getClass()); //class com.sun.proxy.$Proxy31
}
4.1 基本操作
CRUD操作
employeeRepository.delete(id)
employeeRepository.findAll()
employeeRepository.findOne(id)
employeeRepository.save()根据有无id确定是添加还是删除
4.2 查询
- 排序
//第一个参数为排序规则,是一个常量(DESC降序,ASC升序),第二个参数为需要排序的属性
Sort sort = new Sort(Sort.Direction.DESC,"age");
List<Employee> employees = employeeRepository.findAll(sort);
employees.forEach(e-> System.out.println(e));
- 分页
//创建分页规则,第一个参数为当前页码(从0开始),第二个参数为每页容量
Pageable pageable = new PageRequest(0,5);
Page<Employee> all = employeeRepository.findAll(pageable);
- 排序+分页
//创建分页对象时传入排序对象(先排序,再分页)
Sort sort = new Sort(Sort.Direction.DESC,"age");
Pageable pageable = new PageRequest(0,5,sort);
Page<Employee> all = employeeRepository.findAll(pageable);
all.forEach(e-> System.out.println(e));
4.3根据条件进行查询
在接口中添加方法(方法名根据条件拼接)
public interface IEmployeeRepository extends JpaRepository<Employee,Long>,JpaSpecificationExecutor<Employee> {
//根据用户名查询
Employee findByUsername(String username);
//根据用户名模糊查询
List<Employee> findByUsernameLike(String name);
//根据用户名和邮件查询
List<Employee> findByUsernameLikeAndEmailLike(String uname,String ename);
表达式 | 例子 | Jpql查询语句 |
---|---|---|
And | findByLastnameAndFirstname | … where x.lastname = ?1 and x.firstname = ?2 |
Or | findByLastnameOrFirstname | … where x.lastname = ?1 or x.firstname = ?2 |
Is,Equals | findByFirstname,findByFirstnameIs,findByFirstnameEqual | … where x.firstname = 1? |
Between | findByStartDateBetween | … where x.startDate between 1? and ?2 |
LessThan(lt) | findByAgeLessThan | … where x.age < ?1 |
LessThanEqual(le) | findByAgeLessThanEqual | … where x.age <= ?1 |
GreaterThan | findByAgeGreaterThan | … where x.age > ?1 |
GreaterThanEqual | findByAgeGreaterThanEqual | … where x.age >= ?1 |
After | findByStartDateAfter | … where x.startDate > ?1 |
Before | findByStartDateBefore | … where x.startDate < ?1 |
IsNull | findByAgeIsNull | … where x.age is null |
IsNotNull,NotNull | findByAge(Is)NotNull | … where x.age not null |
Like | findByFirstnameLike | … where x.firstname like ?1 |
NotLike | findByFirstnameNotLike | … where x.firstname not like ?1 |
StartingWith | findByFirstnameStartingWith | … where x.firstname like ?1 (parameter bound with appended %) |
EndingWith | findByFirstnameEndingWith | … where x.firstname like ?1 (parameter bound with prepended %) |
Containing | findByFirstnameContaining | … where x.firstname like ?1 (parameter bound wrapped in %) |
OrderBy | findByAgeOrderByLastnameDesc | … where x.age = ?1 order by x.lastname desc |
Not | findByLastnameNot | … where x.lastname <> ?1 |
In | findByAgeIn(Collection ages) | … where x.age in ?1 |
NotIn | findByAgeNotIn(Collection age) | … where x.age not in ?1 |
True | findByActiveTrue() | … where x.active = true |
False | findByActiveFalse() | … where x.active = false |
IgnoreCase | findByFirstnameIgnoreCase | … where UPPER(x.firstame) = UPPER(?1) |
4.4 使用@Query注解查询
//使用注解@Query查询,可以使用jpql语句
//查询所有
@Query("select e from Employee e")
List<Employee> findAll();
@Query("select e from Employee e where username like ?1 and email like ?2")
//模糊查询(如果参数名字和字段名不一样,可以使用@param注解指定参数名)
List<Employee> findLike(@Param("username") String uname,@Param("email") String ename);
4.5 使用原生SQL查询
//使用原生sql查询
//查询所有
@Query(nativeQuery = true,value = "SELECT * FROM employee")
List<Employee> findAllBySql();
//模糊查询
@Query(nativeQuery = true,value = "SELECT * FROM employee WHERE username=?1")
List<Employee> findLikeBySql(String username);
5. JpaSpecificationExecutor
jpa的规范执行者
JPA2.0提供的Criteria API的使用封装
动态生成Query满足复杂场景需求
使用方式:继承于它,必须和Repository体系下的接口一起使用
public interface IEmployeeRepository extends JpaRepository<Employee,Long>,JpaSpecificationExecutor<Employee> {
}
5.1 简单查询
@Test
public void test01(){
//根据用户名模糊查询
List<Employee> list = iEmployeeRepository.findAll(new Specification<Employee>() {
/**
Predicate : 使以…为依据; where 条件 and 条件 ....
* @param root : 根 代表了可以查询和操作的实体对象的根,
* 获取字段(username,password,email)
* @param criteriaQuery : 代表一个specific的顶层查询对象
* 查询哪些字段,排序是什么(主要是把多个查询的条件连系起来)
* @param criteriaBuilder 用来构建CriteriaQuery的构建器对象(相当于条件或者说条件组合)
* 主要判断关系(和这个字段是相等,大于,小于like等)
*/
@Override
public Predicate toPredicate(Root<Employee> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
//1.获取字段
Path username = root.get("username");
//2.判断关系,对用户名判断
Predicate predicate = criteriaBuilder.like(username, "%1%");//第一个参数为表达式,就是获取到的字段,第二个为条件参数
return predicate;//返回predicate,条件结果
}
});
list.forEach(e-> System.out.println(e));
}
5.2 多个条件查询
@Test
public void test02(){
//查询条件有多个的时候,根据用户名和邮箱模糊查询
List<Employee> list = iEmployeeRepository.findAll(new Specification<Employee>() {
@Override
public Predicate toPredicate(Root<Employee> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
//1.获取字段
Path username = root.get("username");
Path email = root.get("email");
Path age = root.get("age");
//2.判断关系,like表示模糊查询,gt表示大于
Predicate predicate1 = criteriaBuilder.like(username, "%1%");
Predicate predicate2 = criteriaBuilder.like(email, "%2%");
Predicate predicate3 = criteriaBuilder.gt(age, 20);
//3.连接多个条件
Predicate predicate = criteriaBuilder.and(predicate1, predicate2,predicate3);
return predicate;
}
});
list.forEach(e-> System.out.println(e));
}
5.3 查询加排序加分页
@Test
public void test04(){
//查询加排序加分页,在分页对象中添加排序条件,再把分页对象丢进查询的方法中。
//创建排序规则
Sort sort = new Sort(Sort.Direction.ASC,"age");//第一个参数为排序规则,第二个参数为需要排序的属性
//创建分页规则
Pageable pageable = new PageRequest(0,5,sort);//把sort传进去,根据排序规则来进行分页
//查询
Page<Employee> page = iEmployeeRepository.findAll(new Specification<Employee>() {
@Override
public Predicate toPredicate(Root<Employee> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
//1.获取字段路劲
Path username = root.get("username");
//2.判断关系
Predicate predicate = criteriaBuilder.like(username, "%1%");
//3.返回条件结果
return predicate;
}
}, pageable);
page.forEach(e-> System.out.println(e));
}
6. jpa-spec插件
jpa-spec 在Spring Data JPA之上做扩展,支持原生JPA2规范,==极大的简化动态查询语法==!
导包
<dependency>
<groupId>com.github.wenhao</groupId>
<artifactId>jpa-spec</artifactId>
<version>3.1.1</version>
<!-- 把所有依赖都过滤 -->
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
6.1 简单查询
@Test
public void test01(){
//模糊查询用户名
List<Employee> list = iEmployeeRepository.findAll(
Specifications.<Employee>and()
//第一个参数为属性名,第二个参数为条件参数
.like("username","%1%")
.build()
);
list.forEach(e-> System.out.println(e));
}
6.2 查询加分页加排序
@Test
public void test02(){
//查询+分页+排序
//1.创建排序规则
Sort sort = new Sort(Sort.Direction.DESC,"age");
//2.创建分页对象,并添加排序规则
Pageable pageable = new PageRequest(0,1,sort);
//3.查询
Page<Employee> page = iEmployeeRepository.findAll(
Specifications.<Employee>and()
.like("username", "%1%")
.like("email", "%2%")
.build()
, pageable);
page.forEach(e-> System.out.println(e));
}
7. Query抽取
在每一个项目中,都会使用到查询功能,只是查询的实体不一致,此时应该抽取一个父类,有创造查询规则的能力,子类通过继承并重写自己的规则,可以极大的简化代码,增强拓展!
父类
/**
* BaseQuery抽取的父类,存放共性。
*/
public abstract class BaseQuery {
private int currentPage = 3;//当前页
private int pageSize = 10;//每页的容量
private String orderName;//排序的属性名
private boolean orderType;//排序的规则(升序还是降序,用true或者false代替)
//制定规则的抽象方法,子类必须重写自己的规则
public abstract Specification createSpec();
//排序的方法
public Sort createSort(){
//如果属性名字不为null且不为""(前台有排序需求),进行排序,为true的时候是升序,false为降序
if(StringUtils.isNotBlank(orderName))
return new Sort(orderType==true?Sort.Direction.ASC:Sort.Direction.DESC,orderName);
return null;
}
...get/set
子类
public class EmployeeQuery extends BaseQuery {
private String username;
private String email;
private Integer age;
/**
* @isNotBlank 判断字符串不为null且不为"";
* 根据前台接收的参数来创建规则
* @return Specification
*/
@Override
public Specification createSpec(){
Specification<Employee> specification = Specifications.<Employee>and()
.like(StringUtils.isNotBlank(username),"username", "%"+username+"%")
.like(StringUtils.isNotBlank(email),"email", "%"+email+"%")
.build();
return specification;
}
测试
@Test
public void test(){
//模拟前台传过来的数据进行查询+分页+排序操作
EmployeeQuery employeeQuery = new EmployeeQuery();
employeeQuery.setUsername("1");
employeeQuery.setEmail("2");
//分页参数
employeeQuery.setCurrentPage(1);
employeeQuery.setPageSize(5);
employeeQuery.setOrderName("age");
Pageable page = new PageRequest(employeeQuery.getJpaPage(),
employeeQuery.getPageSize(),
employeeQuery.createSort());
System.out.println(employeeQuery.createSort());
//-------------------------------------------------//
Page p = iEmployeeRepository.findAll(employeeQuery.createSpec(),page);
p.forEach(e-> System.out.println(e));
}