配置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">
<!-- 扫描service部分的包 -->
<context:component-scan base-package="cn.itsource.pss.service" />
<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="cn.itsource.aisell.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:扫描的包 dao层 -->
<jpa:repositories base-package="cn.itsource.pss.repository" transaction-manager-ref="transactionManager"
entity-manager-factory-ref="entityManagerFactory" />
</beans>
准备一个父类domain(提取公共id,避免每次重复创id)
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
//不用保存到数据库
@MappedSuperclass
//抽取一个公共类,创建id字段,避免多次创建
public class BaseDomain {
@Id
@GeneratedValue
private Long id;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
}
子类继承(之后的管理者,菜单,员工各种属性直接写自己独有的字段+继承父类domain id属性)
@Entity
public class Employee extends BaseDomain {
private String username;
private String password;
private String email;
private Integer age;
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;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "Employee{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
", email='" + email + '\'' +
", age=" + age +
'}';
}
}
SpringDataJpa:
它是JPA规范的再次封装抽象,底层还是使用了Hibernate的JPA技术实现,引用JPQL的查询语句 ,是属于Spring的生成体系中的一部分。减少开发的工作量,大大提高了开发效率
JpaRepository的CRUD
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringDateJpa {
//导入repository继承的接口
@Autowired
EmployeeRepository employeeRepository;
//查询全部
@Test
public void testfandAll()throws Exception{
//调用已经封装的接口findAll(),查询出全部数据
for (Employee e:employeeRepository.findAll()) {
//打印员工的属性
System.out.println(e);
}
}
//查询一条
@Test
public void testfindOne()throws Exception{
Employee findOne = employeeRepository.findOne(1L);
System.out.println(findOne);
}
//删除数据
@Test
public void testDelete()throws Exception{
employeeRepository.delete(273L);
}
//添加
@Test
public void testSave()throws Exception{
//创建员工对象
//赋值
Employee employee = new Employee();
employee.setAge(99);
employee.setEmail("shaB@qq.com");
employee.setUsername("冯舔");
employee.setPassword("123456");
employeeRepository.save(employee);
}
//修改 save 和添加一样,但是修改的时候需要加id属性
@Test
public void testSaveUpdate()throws Exception{
Employee employee =new Employee();
employee.setId(274L);
employee.setAge(20);
employee.setUsername("huahua");
employee.setPassword("2333");
employee.setEmail("2333@163.com");
employeeRepository.save(employee);
}
批量删除
需要给予多个id,然后用list.add添加执行批量删除方法
//批量删除
@Test
public void testDeleteList()throws Exception{
//创建集合,把数据放到集合批量删除
List list=new ArrayList();
//创建employee对象
Employee employee =new Employee();
employee.setId(275L);
Employee employee1=new Employee();
employee1.setId(276L);
//放数据到集合
list.add(employee);
list.add(employee1);
//批量删除方法
employeeRepository.deleteInBatch(list);
}
//查询总个数
@Test
public void testCount()throws Exception{
//查询总个数方法
long count = employeeRepository.count();
//打印总个数
System.out.println(count);//139
}
分页:
//分页
@Test
public void testPage()throws Exception{
//分页,从第一页开始,每页十条数据
Pageable pageable=new PageRequest(1,10);
Page<Employee> page = employeeRepository.findAll(pageable);
//查询总条数
long totalElements = page.getTotalElements();
System.out.println("totalElements"+totalElements);//totalElements139
//查询总页数
int totalPages = page.getTotalPages();
System.out.println("totalPages"+totalPages);//totalPages14
//查询输入当前页的所有数据 (第二页 1,从0页开始)
List<Employee> content = page.getContent();
System.out.println(content);
//查询每页条数
int numberOfElements = page.getNumberOfElements();
System.out.println(numberOfElements);//10
}
排序:
//排序
@Test
public void testSort()throws Exception{
//创建排序对象 properties=“???” 根据某个条件排序 按照年龄升序排序
Sort sort =new Sort(Sort.Direction.ASC,"age");
List<Employee> employeeList = employeeRepository.findAll(sort);
//循环出所有结果集
for (Employee employee:employeeList) {
System.out.println(employee);
}
}
排序+分页:
//排序分页
@Test
public void testSortAndPage()throws Exception{
//按照年龄升序排序
Sort sort =new Sort(Sort.Direction.ASC,"age");
//分页 传入排序 当前页第二页 每页十条数据 升序排序 sort
Pageable pageable =new PageRequest(1,10,sort);
//查询所有分页的数据
Page<Employee> employees = employeeRepository.findAll(pageable);
//循环出分页的数据 employees.getContent()
for (Employee employee:employees.getContent()) {
System.out.println(employee);
}
}
规则查询:
//Employee是一个实体类 domain
//Long是主键id
public interface EmployeeRepository extends JpaRepository<Employee,Long> {
//按照规则来查询
public List<Employee> findByUsernameLike(String username);
public List<Employee> findByUsername(String username);
//大于20岁的
public List<Employee> findByAgeGreaterThan(Integer age);
//按规则查询
@Test
public void testName()throws Exception{
//模糊查询,username 带有admin的员工
List<Employee> byUsernameLike = employeeRepository.findByUsernameLike("%admin%");
for (Employee employee: byUsernameLike) {
System.out.println(employee);
}
}
@Test
public void testName1()throws Exception{
List<Employee> byUsername = employeeRepository.findByUsername("admin");
for (Employee employee:byUsername) {
System.out.println(employee);
}
}
@Test
public void testName2()throws Exception{
//查询大于20岁的
List<Employee> byAgeGreaterThan = employeeRepository.findByAgeGreaterThan(20);
for (Employee employee:byAgeGreaterThan) {
System.out.println(employee);
}
}
注解式:
### 只需要将@Query定义在Respository的方法之上即可
//注解查询
//查询id最大的
@Query("select o from Employee o where o.id =(select max(p.id) from Employee p)")
public Employee queryEmployee();
@Query("select o from Employee o where o.username like ?1 and o.age like ?2")
public List<Employee> queryEmployee1(String name ,Integer age);
//@Param(username) 必须和 :username 一致 建议来都写来一致
@Query("select o from Employee o where o.username like :username and o.email like :email")
public List<Employee> queryEmployee2(@Param("username") String name , @Param("email") String email);
//总条数
@Query(value = "select count(*) from employee ",nativeQuery = true)
public Long queryCount();
//注解式
//查询id最大的MAX
@Test
public void testName3()throws Exception{
Employee queryEmployee0 = employeeRepository.queryEmployee();
System.out.println(queryEmployee0);
}
//通过sql 给指定sql字段值查询
@Test
public void testName4()throws Exception{
//输入数据库已有的属性
List<Employee> queryEmployee1 = employeeRepository.queryEmployee1("冯舔", 99);
System.out.println(queryEmployee1);
//[Employee{username='冯舔', password='123456', email='shaB@qq.com', age=99}]
}
@Test
public void testName5()throws Exception{
//输入数据库已有的属性
List<Employee> queryEmployee2 = employeeRepository.queryEmployee2("冯狗", "shaX@qq.com");
System.out.println(queryEmployee2);
//[Employee{username='冯狗', password='123456', email='shaX@qq.com', age=99}]
}
//查询总条数
@Test
public void testName6()throws Exception{
Long queryCount = employeeRepository.queryCount();
System.out.println(queryCount);//总条数141
}
BaseQuery:公共的分页条件
package cn.itsource.pss.query;
/**
* 公共的条件与规范
*/
public abstract class BaseQuery {
//当前页(从1开始)
private int currentPage = 1;
//每页条数
private int pageSize = 10;
//排序方式 ASC/DESC
private String orderByType ="ASC";
//排序字段
private String orderByName;
public int getCurrentPage() {
return currentPage;
}
/**
* 专门准备的方法,因为前台用户传的是从第1页开始,而我们后台分页又是从0开的
* @return
*/
public int getJpaPage() {
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 getOrderByType() {
return orderByType;
}
public void setOrderByType(String orderByType) {
this.orderByType = orderByType;
}
public String getOrderByName() {
return orderByName;
}
public void setOrderByName(String orderByName) {
this.orderByName = orderByName;
}
EmployeeQuery:Employee独有的一些条件
public class EmployeeQuery extends BaseQuery {
private String username;//姓名
private String email;//邮件
private Integer age;//年龄
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;
}
//like(条件boolean值,字段,值)
Specification<Employee> spec = Specifications.<Employee>and()
.like(StringUtils.isNotBlank(baseQuery.getUsername()), "username","%"+baseQuery.getUsername()+"%")
.like(StringUtils.isNotBlank(baseQuery.getEmail()), "email","%"+baseQuery.getEmail()+"%")
.lt(baseQuery.getAge()!=null, "age",baseQuery.getAge())
.build();
//这里确定是否需要排序
Sort sort = null;
if(baseQuery.getOrderByName()!=null){
Sort.Direction desc = "DESC".equals(baseQuery.getOrderByType())?Sort.Direction.DESC:Sort.Direction.ASC;
sort = new Sort(desc,baseQuery.getOrderByName());
}
Pageable pageable = new PageRequest(baseQuery.getJpaPage(), baseQuery.getPageSize(),sort);
Page<Employee> page = employeeRepository.findAll(spec, pageable);
for (Employee emp : page) {
System.out.println(emp);
}
}
创建Specification的流程放到Query里
BaseQuery中添加抽象方法
public abstract class BaseQuery {
...
//拿到查询的条件对象(由子类实现)
public abstract Specification createSpecification();
//拿到排序的数据
public Sort createSort() {
Sort sort = null;
if (StringUtils.isNotBlank(orderByName)) {
Sort.Direction type= "ASC".equals(orderByType.toUpperCase())? Sort.Direction.ASC:Sort.Direction.DESC;
sort = new Sort(type,orderByName);
}
return sort;
}
...
}
EmployeeQuery中实现相应方法
(以后每一个Query要做高级查询都写在这个位置)
public class EmployeeQuery extends BaseQuery {
...
@Override
public Specification createSpecification() {
//根据条件把数据返回即可
return Specifications.<Employee>and()
.like(StringUtils.isNotBlank(username), "username","%"+username+"%")
.like(StringUtils.isNotBlank(email), "email","%"+email+"%")
.lt(age!=null, "age",age)
.build();
}
...
}