SpringData学习笔记

Spring Data是Spring下的子项目,大大简化了Dao层的开发量,最近终于把这个撸完,简单做一下记录,防止这该死的脑袋又忘记。

一、关于传统数据库的操作–JDBC的梳理

1.首先创建获取和销毁Connection对象的工具类

JDBCUtile工具类

package com.hhu.util;

import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

/**
 * jdbc的工具类,用于Connection的获取和资源的销毁
 */
public class JDBCUtil {


    /**
     * 将方法定义成静态方法,这样可以直接使用“类名+方法名”的方式方便调用
     * @return 获取的驱动
     * @throws Exception
     */
    public static Connection getConnection() throws Exception {
        //读取jdbc的配置文件
        InputStream is = JDBCUtil.class.getClassLoader().getResourceAsStream("jdbc.properties");
        Properties properties = new Properties();
        //将输入流载入properties
        properties.load(is);

        String userName = properties.getProperty("jdbc.userName");
        String password = properties.getProperty("jdbc.password");
        String url = properties.getProperty("jdbc.url");
        String driverClass = properties.getProperty("jdbc.driverClass");

        //加载驱动
        Class.forName(driverClass);

        Connection conn = DriverManager.getConnection(url, userName, password);

        return conn;
    }

    /**
     * 关闭连接资源
     * @param rs 结果集
     * @param st 编译对象
     * @param conn 连接对象
     */
    public static void closeResource(ResultSet rs, Statement st, Connection conn) {
        if(rs!=null) {
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        if(st!=null) {
            try {
                st.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        if(conn!=null) {
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

}

2.操作数据库

package com.hhu.jdbc;

import com.hhu.dao.Student;
import com.hhu.util.JDBCUtil;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

/**
 * 利用jdbc对数据库进行增删改查
 */
public class StudentDao {

    /**
     * 增操作
     */
    public void insertStudent(Student s) {
        Connection conn = null;
        PreparedStatement pst = null;
        ResultSet rs = null;
        String sql = "insert into student(name, age) values(?,?)";
        try {
            conn = JDBCUtil.getConnection();
            //预编译sql语句
            pst = conn.prepareStatement(sql);
            //给占位符设参
            pst.setString(1, s.getName());
            pst.setInt(2, s.getAge());
            //执行SQL
            pst.execute();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtil.closeResource(rs, pst, conn);
        }
    }

    /**
     * 删操作
     */
    public void deleteById(int id) {
        Connection conn = null;
        PreparedStatement pst = null;
        ResultSet rs = null;
        String sql = "delete from student where id=?";
        try {
            conn = JDBCUtil.getConnection();
            //预编译sql语句
            pst = conn.prepareStatement(sql);
            //给占位符设参
            pst.setInt(1, id);
            //执行SQL
            pst.execute();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtil.closeResource(rs, pst, conn);
        }
    }

    /**
     * 该操作
     */
    public void updateById(String name, int age, int id) {
        Connection conn = null;
        PreparedStatement pst = null;
        ResultSet rs = null;
        String sql = "update student set name=?,age=? where id=?";
        try {
            conn = JDBCUtil.getConnection();
            //预编译sql语句
            pst = conn.prepareStatement(sql);
            //给占位符设参
            pst.setString(1, name);
            pst.setInt(2, age);
            pst.setInt(3, id);
            //执行SQL
            pst.executeUpdate();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtil.closeResource(rs, pst, conn);
        }
    }

    /**
     * 查操作
     */
    public List<Student> findAll() {
        Connection conn = null;
        PreparedStatement pst = null;
        ResultSet rs = null;
        String sql = "select id,name,age from student";
        List<Student> list = new ArrayList<Student>();
        try {
            conn = JDBCUtil.getConnection();
            System.out.println(conn);
            //预编译sql语句
            pst = conn.prepareStatement(sql);
            //执行SQL
            rs = pst.executeQuery(sql);
            System.out.println(rs);
            while(rs.next()) {
                Student s = new Student(rs.getString("name"),rs.getInt("age"));
                list.add(s);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtil.closeResource(rs, pst, conn);
        }
        return list;
    }

}

二、SpringData对数据库的操作

利用SpringData操作是不需要手动建表,这一点和Hibernate相似,这一点注意实体类中的注解

1.依赖的引入

    <!--引入Spring-data-jpa的两个依赖:spring-data-jpa和hibernate-entityManager,一定注意两者的版本,
    否则会出现entitymanager无法打开的异常-->
    <dependency>
      <groupId>org.springframework.data</groupId>
      <artifactId>spring-data-jpa</artifactId>
      <version>1.8.0.RELEASE</version>
    </dependency>

    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-entitymanager</artifactId>
      <version>4.3.6.Final</version>
    </dependency>

2.配置Spring

<?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/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">

    <!--配置数据源-->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="username" value="root"></property>
        <property name="password" value="root"></property>
        <property name="url" value="jdbc:mysql://localhost:3306/spring_date"></property>
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
    </bean>

    <!--配置HibernateEntityManagerFactory-->
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSource"></property>
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"></bean>
        </property>
        <property name="packagesToScan" value="com.hhu"></property>
        <!--jpa的配置-->
        <property name="jpaProperties">
            <props>
                <prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.ImprovedNamingStrategy</prop>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.format_sql">true</prop>
                <prop key="hibernate.hbm2ddl.auto">update</prop>
            </props>
        </property>
    </bean>


    <!--配置事务管理器-->
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"></property>
    </bean>

    <!--配置支持注解的事务-->
    <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>

    <!-- 配置spring data能够扫描出来的包 -->
    <jpa:repositories base-package="com.hhu" entity-manager-factory-ref="entityManagerFactory"></jpa:repositories>
    <!--可以直接用context的全局扫描了,如果配置context就不需要配置上述的jpa的扫描-->
    <context:component-scan base-package="com.hhu"></context:component-scan>
</beans>

3.创建实体类

package com.hhu.dao;

import javax.persistence.*;

/**
 * 雇员,这个实体类用于测试jpa对于table的创建
 * jpa中所有的基本数据类型建议使用封装类型
 */
@Entity//这个注解表明他是一个实体类,根据xml中的配置会自动创建这个实体类的映射表
//@Table(name = "")//给table命名,默认就是实体名的小写
public class Employee {

    @Id//这个注解表明这个属性值是id
    @GeneratedValue//这个注解表明他是策略是id自增
    private Integer id;

    @Column(length = 20)//该注解是指定创建表字段时候的长度(默认为255)
    private String name;

    private Integer age;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Employee(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public Employee() {
    }

    @Override
    public String toString() {
        return "Employee{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

}

4.数据库操作类–Repository

Repository是jpa包下的核心类,也是数据库操作类, Repository是空接口不提供任何方法,是个标记接口,和Serializable和Cloneable一样,但是不一样的是,继承这个接口会自动被Spring管理!!不需要手动加注解。Repository体系中主要包括以下四类子接口:1.内置CrudRepository接口(即内部帮我们写好了save,update,delete方法),2.PagingAndSortingRepository(分页和排序) ,3.JpaRepository接口,4.JpaSpecificationExecutor接口。可以根据自己的需求选择其中的一个或者多个接口。

在贴代码之前,简单说一下Jpa的命名规则:千万不能乱写,jpa有自己的规则。
* jap的基本命名规则:
* 1.And/Or
* 即按多个条件进行查询,比如这里按照姓名和年龄去查询,那么方法名必须写成findByNameAndAge()
* Or同理
*
* 2.Between/LessThan/GreaterThan
* 查询分范围内的数据,必须带上范围字段,比如查询一定范围内的年龄,方法名必须为findByAgeBetween()
*LessThan(小于)和GreaterThan(大于)同上
*
* 3.Like/NotLike
* 即模糊匹配,必须带上匹配的字段,比如按名字模糊匹配(?ak),那么方法名为findByNameLike()
* NotLike同理
* 等等。。。
*
* 4.StartingWith/EndingWith/Containing(较为常用)
* 这三个是上诉第三点的具体版本,写法一样,它们模糊查询匹配如下:
* 比如查询行年
*
* 5.OrderBy
* 必须指明按哪个字段的何种方式排序,必须按年龄降序排列
* 比如先按姓名查找然后按年龄降序
* findByNameOrderByAgeDesc

1.Repositoy接口
一般情况下,就是以往的Dao层,这里正常定义成接口然后让它实现Repository接口,就可以进行一些简单的数据库的操作,如下:

package com.hhu.repository;

import com.hhu.dao.Employee;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.RepositoryDefinition;
import org.springframework.data.repository.query.Param;

import java.util.List;

@RepositoryDefinition(domainClass = Employee.class,idClass = Integer.class)
public interface EmployeeRepository {
    /*注意,这里是声明成接口的方式,一般情况下,Repository是jpa包下的核心类,会带有
    两个泛型,像这样的形式Repository<T , ID>,其中T表明此Repository需要操作的对象,
    这个实例里面是对Employee的操作,而Employee实体类的主键为id是Integer类型,所以这
    里应该写成Repository<Employee, Integer>,前面定义id为Integer不定义成int,也只考
    虑到泛型这一点,这里一定要带上泛型,否则会报错,默认将id当成varchar类型但他是Integer!!

    Repository是空接口不提供任何方法,是个标记接口,和Serializable和Cloneable一样,但是不
    一样的是,继承这个接口会自动被Spring管理!!

    只要继承这个接口(送一个面试题,接口之间的继承使用的是extends关键字而不是implements
    关键字),那么那都不需要写实现类,当然除了继承这个接口,还可以不用继承的方式可以使用
    RepositoryDefintion这个注解的方式来代替,如下的方式:
    @RepositoryDefinition(domainClass = Employee.class,idClass = Integer.class)
     */


    /**
     * 自动查询的关键,千万不能乱写,jpa有自己的规则,这里如果写成test()那么是无法自动匹配查询的!!
     *
     * Repository的主要结构体系:
     * 1.内置CrudRepository接口(即内部帮我们写好了save,update,delete方法)
     * 具体的方法如下:
     * save(entity) findOne(id) finaAll() delete(entity) deleteAll()
     * save(entities) exists(id) delete(id) delete(entities)
     *
     *
     * 2.PagingAndSortingRepository(分页和排序)
     * 这个接口包含了分页和排序的功能,
     * 2.1带排序功能的查询
     * findAll(Sort sort)
     *
     * 2.2带排序的分页查询
     * findAll(Pageable pageable)
     *
     * 3.JpaRepository接口
     * 这个接口中主要有如下的一些方法:
     * findAll() findAll(Sort sort) save(entities) flush()  deleteInBatch(entities)
     *
     *
     * 4.JpaSpecificationExecutor接口
     * 这个接口封装了JPA Criteria的查询条件
     *
     *
     * jap的基本命名规则:
     * 1.And/Or
     * 即按多个条件进行查询,比如这里按照姓名和年龄去查询,那么方法名必须写成findByNameAndAge()
     * Or同理
     *
     * 2.Between/LessThan/GreaterThan
     * 查询分范围内的数据,必须带上范围字段,比如查询一定范围内的年龄,方法名必须为findByAgeBetween()
     *LessThan(小于)和GreaterThan(大于)同上
     *
     * 3.Like/NotLike
     * 即模糊匹配,必须带上匹配的字段,比如按名字模糊匹配(?ak),那么方法名为findByNameLike()
     * NotLike同理
     * 等等。。。
     *
     * 4.StartingWith/EndingWith/Containing(较为常用)
     *  这三个是上诉第三点的具体版本,写法一样,它们模糊查询匹配如下:
     *  比如查询行年
     *
     * 5.OrderBy
     * 必须指明按哪个字段的何种方式排序,必须按年龄降序排列
     * 比如先按姓名查找然后按年龄降序
     * findByNameOrderByAgeDesc
     *
     *
     * 当然按照上述的规则定义方法名可能名字会非常长,另外一个是对于复杂的查询难以实现,
     * 这个时候可以利用@Query这个注解进行自定义书写SQL,而且使用这个注解的时候就可以
     * 丢弃上述的一套命名规则了,因为SQL语句此时是自己写的
     *
     *
     *
     * @param name
     * @return
     */
    public Employee findByName(String name);


    /**
     * 查询name模糊匹配并且age小于限定值
     */
    public List<Employee> findByNameStartingWithAndAgeLessThan(String name,Integer age);

    public List<Employee> findByNameEndingWithAndAgeGreaterThan(String name, Integer age);

    public List<Employee> findByNameContaining(String name);

    public List<Employee> findByNameLike(String name);

    /**
     * 查询名字在某一范围内(关键字In)或者年龄小于某一限定值,
     * 所以名字的方查询范围传入List集合
     */
    public List<Employee> findByNameInOrAgeLessThan(List<String> names, Integer age);

    /**
     * 获取id最大员工的信息
     *
     * @return
     */
    //注意:这里的不是写表名而是写类名
    @Query("select e from Employee e where id=(select max(id) from Employee e2)")//这个注解中直接写SQL语句即可
    public Employee getMaxId();

    //方式1:利用注解传入参数查询满足条件的记录,占位符的方式,即索引参数
    @Query("select e from Employee e where e.name=?1 and e.age=?2")
    public List<Employee> getTestRecords(String name,Integer age);


    //方式2:按照命名参数的方式来写SQL,只是将占位符换做了“:参数名”的方式,在形参上加上@Param的注解即可
    @Query("select e from Employee e where e.name=:name and e.age=:age")
    public List<Employee> getTestRecords2(@Param("name") String name, @Param("age")Integer id);

    //方式1:Like关键字,有点类似于containing了,用占位符,即索引参数
    @Query("select e from Employee e where e.name like %?1%")
    public List<Employee> queryLike1(String name);

    //方式2:Like关键字同样可以使用命名参数的方式
    @Query("select e from Employee e where e.name like %:name%")
    public List<Employee> queryLike2(@Param("name") String name);

    //打开原生的方式进行查询,一定要把nativeQuery设置为true,此时就可以用表名去查询
    @Query(nativeQuery = true, value = "select count(id) from employee")
    public long getCount();

    //写操作必须加Transactional和Modifying注解,只是事务注解一般是放在Service层的
    //@Transactional
    @Modifying//允许修改的意思
    @Query("update Employee e set e.age=:age where e.id=:id")
    public void update(@Param("age") Integer age, @Param("id") Integer id);
}

2.CrudRepository接口

package com.hhu.repository;

import com.hhu.dao.Employee;
import org.springframework.data.repository.CrudRepository;

/**
 * 继承CrudRepository接口,该接口又继承了顶级接口Repository
 */
public interface EmployeeCrudRepository extends CrudRepository<Employee, Integer>{
}

3.PagingAndSortingRepository接口

package com.hhu.repository;

import com.hhu.dao.Employee;
import org.springframework.data.repository.PagingAndSortingRepository;

/**
 * 继承分页查询的接口PagingAndSortingRepository
 */
public interface EmployeePagingAndSortingRepository extends PagingAndSortingRepository<Employee, Integer>{

}

4.JpaRepository接口

package com.hhu.repository;

import com.hhu.dao.Employee;
import org.springframework.data.jpa.repository.JpaRepository;

/**
 * 测试JpsRepository接口
 */
public interface EmployeeJpaRepository extends JpaRepository<Employee, Integer>{

}

5.JpaSpecificationExecutor接口

package com.hhu.repository;

import com.hhu.dao.Employee;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;

public interface EmployeeJpaSpecificationExecutor extends JpaRepository<Employee, Integer>, JpaSpecificationExecutor<Employee> {
}

最后是测试代码,注意后面几种接口的调用方法

package com.hhu.repository;

import com.hhu.dao.Employee;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;

import javax.persistence.criteria.*;
import java.util.ArrayList;
import java.util.List;

/**
 * 测试Repository
 */
public class EmployeeRepositoryTest {

    //定义上下文
    private ApplicationContext ctx = null;

    private EmployeeRepository employeeRepository = null;

    //分页接口
    private EmployeePagingAndSortingRepository employeePagingAndSortingRepository = null;

    //jpa接口
    private EmployeeJpaRepository employeeJpaRepository = null;

    //jpaSpecificationExecutor接口
    private EmployeeJpaSpecificationExecutor employeeJpaSpecificationExecutor = null;

    @Before
    public void doBefore() {
        System.out.println("set up...");
        ctx = new ClassPathXmlApplicationContext("beans.xml");
        employeeRepository = (EmployeeRepository) ctx.getBean(EmployeeRepository.class);
        employeePagingAndSortingRepository = (EmployeePagingAndSortingRepository)ctx.getBean("employeePagingAndSortingRepository");
        employeeJpaRepository = (EmployeeJpaRepository)ctx.getBean("employeeJpaRepository");
        employeeJpaSpecificationExecutor = (EmployeeJpaSpecificationExecutor)ctx.getBean("employeeJpaSpecificationExecutor");
    }

    @Test
    public void findByNameStartWithAndAgeLessThanTest() {
        List<Employee> list = employeeRepository.findByNameStartingWithAndAgeLessThan("test",24);
        System.out.println(list);
    }

    @Test
    public void findByNameEndingWithAndAgeGreaterLanTest() {
        List<Employee> list = employeeRepository.findByNameEndingWithAndAgeGreaterThan("5",23);
        System.out.println(list);
    }

    @Test
    public void employeeRepositoryTest() {
        String name = "jack";
        Employee employee = employeeRepository.findByName(name);
        System.out.println(employee);
    }

    @Test
    public void findByNameContainingTest() {
        List<Employee> list = employeeRepository.findByNameContaining("5");
        System.out.println(list);
    }

    @Test
    public void findByNameLike() {
        List<Employee> list = employeeRepository.findByNameLike("5");
        System.out.println(list);
    }

    @Test
    public void findByNameInOrAgeLessThan() {
        List<String> names = new ArrayList<String>();
        names.add("jack");
        names.add("air");
        names.add("test");
        names.add("test1");
        List<Employee> list = employeeRepository.findByNameInOrAgeLessThan(names,23);
        System.out.println(list);
    }

    @Test
    public void getMaxIdTest() {
        Employee e = employeeRepository.getMaxId();
        System.out.println(e);
    }

    @Test
    public void getTestRecodsTest() {
        List<Employee> e = employeeRepository.getTestRecords("test5",27);
        System.out.println("select e:" + e);
    }

    @Test
    public void getTestRecords2Test() {
        List<Employee> list = employeeRepository.getTestRecords2("jack",25);
        System.out.println(list);
    }

    @Test
    public void queryLike1Test() {
        List<Employee> list = employeeRepository.queryLike1("test");
        System.out.println(list);
    }

    @Test
    public void queryLike2Test() {
        List<Employee> list = employeeRepository.queryLike2("a");
        System.out.println(list);
    }

    @Test
    public void getCountTest() {
        System.out.println(employeeRepository.getCount());
    }

    @Test
    public void update() {
        employeeRepository.update(18,11);
    }

    /*
    测试分页
     */
    @Test
    public void pageTest() {
        //Page对象是Spring内置的对象,从第0页开始,每页显示5条记录
        Pageable page = new PageRequest(1, 5);//创建一个Page对象,第1页(即第二页),每页显示5条记录
        Page<Employee> employeePage = employeePagingAndSortingRepository.findAll(page);
        System.out.println("总页数:" + employeePage.getTotalPages());
        System.out.println("总记录数:" + employeePage.getTotalElements());
        System.out.println("当前页码(从第0页开始):" + employeePage.getNumber());
        System.out.println("当前页记录的集合:" + employeePage.getContent());
        System.out.println("当前页面包含的记录数:" + employeePage.getNumberOfElements());
    }

    @Test
    public void PageSortTest() {
        //创建排序对象(排序方式,按照那个字段排序),注意这里是先排序再分页
        Sort.Order order = new Sort.Order(Sort.Direction.DESC, "id");
        Sort sort = new Sort(order);
        Pageable page = new PageRequest(0, 8, sort);
        Page<Employee>  sortPage = employeePagingAndSortingRepository.findAll(page);
        System.out.println("当前页的记录数:" + sortPage.getNumberOfElements());
        System.out.println("当前页码:" + sortPage.getNumber());
        System.out.println("当前页记录的集合:" + sortPage.getContent());
        System.out.println("总记录数:" + sortPage.getTotalElements());
        System.out.println("总页数:" + sortPage.getTotalPages());
    }

    /**
     * 测试JpaRepository接口
     */
    @Test
    public void JpaTest() {
        Employee e = employeeJpaRepository.findOne(99);
        System.out.println(e);

        boolean r1 = employeeJpaRepository.exists(78);
        boolean r2 = employeeJpaRepository.exists(120);
        System.out.println("r1:" + r1);
        System.out.println("r2:" + r2);
    }

    /**
     * 测试JpaSpecificationExecutor接口
     *
     * 实现功能:分页(第一页,每页5条记录)+排序(按id降序)+查询条件(比如年龄大于50)
     */
    @Test
    public void jpaSpecificationTest() {
        Sort.Order order = new Sort.Order(Sort.Direction.DESC, "id");
        Sort sort = new Sort(order);

        Pageable pageable = new PageRequest(0, 5, sort);
        //创建Specification对象
        Specification<Employee> specification = new Specification<Employee>() {
            /***
             *
             * @param root 就是待查询的数据类型(这里就是Employee)
             * @param criteriaQuery 添加查询条件
             * @param criteriaBuilder 构建predicate返回
             * @return
             */
            @Override
            public Predicate toPredicate(Root<Employee> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                //root就是查询的对象Employee,从里面可以获取Employee中的age属性
                Path path = root.get("age");

                //criteriaBuilder就是构建的查询条件
                Predicate predicate = criteriaBuilder.gt(path, 50);
                return predicate;
            }
        };

        //这里可以将查询的条件添加进finadAll()方法中
        Page<Employee> page = employeeJpaSpecificationExecutor.findAll(specification, pageable);

        System.out.println("总页数:" + page.getTotalPages());
        System.out.println("总记录数:" + page.getTotalElements());
        System.out.println("当前页记录的集合:" + page.getContent());
        System.out.println("当前页的记录数:" + page.getNumberOfElements());
        System.out.println("当前页码:" + page.getNumber());
    }



    @After
    public void doAfter() {
        if(ctx!=null) {
            ctx = null;
        }
    }

}

【注意】最后需要提醒的是关于JPA里面的读操作和写操作的区别(利用@Query注解时写操作一定要加@Modifying注解允许修改,另外也必须加事务注解@Transactional(这个一般是加在Service层))。比如下面的Service层

package com.hhu.service;

import com.hhu.dao.Employee;
import com.hhu.repository.EmployeeCrudRepository;
import com.hhu.repository.EmployeeRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import java.util.List;

@Service
public class EmployeeService {

    @Autowired
    private EmployeeRepository employeeRepository;

    @Autowired
    private EmployeeCrudRepository employeeCrudRepository;

    @Transactional
    public void update(Integer age, Integer id) {
        employeeRepository.update(age, id);
    }

    @Transactional
    public void save(List<Employee> list) {
        employeeCrudRepository.save(list);
    }

}

完整代码见:https://github.com/Jacksonary/CodeRepository/tree/master/SpringData

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值