SpringData入门(三)-Spring Data JPA进阶

一.关于Respository接口

  • Repository接口是Spring Data的核心接口,不提供任何方法
  • Repository接口是一个空接口(标记接口)-没有包含任何方法声明的接口

SpringData入门(三)-Spring Data JPA进阶_第1张图片

  • 如果我们定义的接口extends Repository,自动会被Spring管理
  • 比如我们上一章讲得EmployeeRepository接口,就是 extends Repository,我们先来打印一下
public class EmployeeRepositoryTest {

    private ApplicationContext applicationContext = null;
    private EmployeeRepository employeeRepository = null;
    @Before
    public void init(){
        applicationContext = new AnnotationConfigApplicationContext(SpringConfigNew.class);
        employeeRepository = applicationContext.getBean(EmployeeRepository.class);
        System.out.println("init...");
    }

    @After
    public void destroy(){
        applicationContext=null;
        System.out.println("destroy...");
    }

    @Test
    public void findByNametest(){
        System.out.println(employeeRepository);
        Employee employee = employeeRepository.findByName("test1");
        System.out.println(employee);
    }
}

在这里插入图片描述

  • 如果我们自己的接口没有extends Repository,运行时会报错,找不到这个Bean。
  • 没有继承这个接口,就不会被spring管理
  • 可以用RepositoryDefinition注解来实现同样的功能
    SpringData入门(三)-Spring Data JPA进阶_第2张图片
  • 这个接口有两个属性,同样也是类和主键的类型
@RepositoryDefinition(domainClass = Employee.class,idClass = Integer.class)
interface EmployeeRepository /*extends Repository*/ {//类名 + 主键类型

    //获取雇员对象通过名称
    Employee findByName(String name);

}

  • 再打印这个接口同样也没问题的

二.Repository子接口

  • 结构
    SpringData入门(三)-Spring Data JPA进阶_第3张图片
  • CrudRepository:继承Repository,实现了CRUD相关的方法
  • PagingAndSortingRepository:继承CrudRepository,实现了分页排序相关的方法
  • JpaRepository:继承PagingAndSortingRepositor,实现JPA规范相关的方法

三.查询方法定义规则和使用

  • 了解Spring Data中查询方法名称的定义规则
  • 使用Spring Data完成复杂查询方法名称的命名
  • 规则视图如下
    SpringData入门(三)-Spring Data JPA进阶_第4张图片
@RepositoryDefinition(domainClass = Employee.class,idClass = Integer.class)
interface EmployeeRepository /*extends Repository*/ {//类名 + 主键类型

    //获取雇员对象通过名称
    Employee findByName(String name);

    //where name like ?% and age < ?
    List findByNameStartingWithAndAgeLessThan(String name,Integer age);
    //where name like %? and age < ?
    List findByNameEndingWithAndAgeLessThan(String name,Integer age);
    //where name in () or age < ?
    List findByNameInOrAgeLessThan(List name,Integer age);
    //where name in () and age < ?
    List findByNameInAndAgeLessThan(List name,Integer age);

}
  • 测试类
public class EmployeeRepositoryTest {

    private ApplicationContext applicationContext = null;
    private EmployeeRepository employeeRepository = null;
    @Before
    public void init(){
        applicationContext = new AnnotationConfigApplicationContext(SpringConfigNew.class);
        employeeRepository = applicationContext.getBean(EmployeeRepository.class);
        System.out.println("init...");
    }

    @After
    public void destroy(){
        applicationContext=null;
        System.out.println("destroy...");
    }

    @Test
    public void findByNametest(){
        System.out.println(employeeRepository);
        Employee employee = employeeRepository.findByName("test1");
        System.out.println(employee);
    }

    @Test
    public void findByNameStartingWithAndAgeLessThantest(){
        List employees = employeeRepository.findByNameStartingWithAndAgeLessThan("test",22);
        for(Employee employee:employees){
            System.out.println(employee);
        }

    }

    @Test
    public void findByNameEndingWithAndAgeLessThantest(){
        List employees = employeeRepository.findByNameEndingWithAndAgeLessThan("6",23);
        for(Employee employee:employees){
            System.out.println(employee);
        }
    }

    @Test
    public void findByNameInOrAgeLessThantest(){
        List name = new ArrayList<>();
        name.add("test1");
        name.add("test2");
        name.add("test3");
        List employees = employeeRepository.findByNameInOrAgeLessThan(name,23);
        for(Employee employee:employees){
            System.out.println(employee);
        }
    }

    @Test
    public void findByNameInAndOrAgeLessThantest(){
        List name = new ArrayList<>();
        name.add("test1");
        name.add("test2");
        name.add("test3");
        List employees = employeeRepository.findByNameInAndAgeLessThan(name,23);
        for(Employee employee:employees){
            System.out.println(employee);
        }
    }
}

  • 对于按照方法命名规则来使用的话,有弊端:
    • 方法名比较长:约定大于配置
    • 对于一些复杂的查询,是很难实现
    • 这些问题可以使用@Query注解来解决

四.Query注解使用

  • 在Respository方法中使用,不需要遵循查询方法命令规则

  • 只需要将@Query定义在Respository中的方法之上即可

  • 命名参数及索引参数的使用

  • 本地查询

  • EmployeeRepository接口

	//Query注解
    @Query("select o from Employee o where id = (select max(id) from Employee t1)")//注意这里是根据类来查 不是表
    Employee getEmployeeByMaxId();

    /*
    使用占位符进行参数绑定
     */
    @Query("select o from Employee o where o.name = ?1 and o.age = ?2")
    List listEmployeeByNameAndAge(String name,Integer age);

    /*
    使用命名参数进行参数绑定
     */
    @Query("select o from Employee o where o.name = :name and o.age = :age")
    List listEmployeeByNameAndAge2(@Param("name")String name,@Param("age")Integer age);

    /*
    自定义查询SQL,like,占位符进行参数绑定
     */
    @Query("select o from Employee o where o.name like %?1%")
    List listEmployeeByLikeName(String name);

    /*
    自定义查询SQL,like,占位符进行参数绑定
     */
    @Query("select o from Employee o where o.name like %:name%")
    List listEmployeeByLikeName2(@Param("name") String name);

    /*
    使用原生态SQL查询
     */
    @Query(nativeQuery = true,value="select count(1) from employee")//这才是表查询 默认支持原生态为false 改成true
    long getCount();
  • 测试类
@Test
    public void getEmployeeByMaxIdtest(){
        Employee employee = employeeRepository.getEmployeeByMaxId();
        System.out.println(employee);
    }
    @Test
    public void listEmployeeByNameAndAgetest(){
        List employees = employeeRepository.listEmployeeByNameAndAge("test6",22);
        for(Employee employee:employees){
            System.out.println(employee);
        }
    }

    @Test
    public void listEmployeeByNameAndAge2test(){
        List employees = employeeRepository.listEmployeeByNameAndAge2("test6",22);
        for(Employee employee:employees){
            System.out.println(employee);
        }
    }

    @Test
    public void listEmployeeByLikeNametest(){
        List employees = employeeRepository.listEmployeeByLikeName("test");
        for(Employee employee:employees){
            System.out.println(employee);
        }
    }

    @Test
    public void listEmployeeByLikeName2test(){
        List employees = employeeRepository.listEmployeeByLikeName2("6");
        for(Employee employee:employees){
            System.out.println(employee);
        }
    }

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

五.更新操作整合事务使用

  • 更新及删除操作整合事务的使用
   @Modifying注解使用
   @Modifying结合@Query注解执行更新操作
   @Transaction在Spring Data中的使用
  • 事务在Spring data中的使用
	@Modifying
    @Query("update Employee o set o.age=:age where o.id=:id ")
    void  update(@Param("id")Integer id,@Param("age")Integer age);
  • 事务一般是在Service层(因为一个service层 可能存在多个DAO层的调用 必须要保证多个DAO都保存在一个事务里面)
  • 实际开发中,需要定义接口
@Service
public class EmployeeService {

    @Autowired
    private EmployeeRepository employeeRepository;

    @Transactional
    public void update(Integer id,Integer age){
        employeeRepository.update(id,age);
    }
}
  • 测试类
public class EmployeeServiceTest {

    private ApplicationContext ctx = null;

    private EmployeeService employeeService = null;
    @Before
    public void init(){
        ctx = new AnnotationConfigApplicationContext(SpringConfigNew.class);
        employeeService = ctx.getBean(EmployeeService.class);
        System.out.println("init...");
    }

    @After
    public void destroy(){
        ctx=null;
        System.out.println("destroy...");
    }

    @Test
    public void update(){
          employeeService.update(1,50);
    }


}

SpringData入门(三)-Spring Data JPA进阶_第5张图片
SpringData入门(三)-Spring Data JPA进阶_第6张图片

你可能感兴趣的:(Spring,data)