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

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

在这里插入图片描述

  • 如果我们定义的接口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注解来实现同样的功能
    在这里插入图片描述
  • 这个接口有两个属性,同样也是类和主键的类型
@RepositoryDefinition(domainClass = Employee.class,idClass = Integer.class)
interface EmployeeRepository /*extends Repository<Employee, Integer>*/ {//类名 + 主键类型

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

}

  • 再打印这个接口同样也没问题的
二.Repository子接口
  • 结构
    在这里插入图片描述
  • CrudRepository:继承Repository,实现了CRUD相关的方法
  • PagingAndSortingRepository:继承CrudRepository,实现了分页排序相关的方法
  • JpaRepository:继承PagingAndSortingRepositor,实现JPA规范相关的方法
三.查询方法定义规则和使用
  • 了解Spring Data中查询方法名称的定义规则
  • 使用Spring Data完成复杂查询方法名称的命名
  • 规则视图如下
    在这里插入图片描述
@RepositoryDefinition(domainClass = Employee.class,idClass = Integer.class)
interface EmployeeRepository /*extends Repository<Employee, Integer>*/ {//类名 + 主键类型

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

    //where name like ?% and age < ?
    List<Employee> findByNameStartingWithAndAgeLessThan(String name,Integer age);
    //where name like %? and age < ?
    List<Employee> findByNameEndingWithAndAgeLessThan(String name,Integer age);
    //where name in () or age < ?
    List<Employee> findByNameInOrAgeLessThan(List<String> name,Integer age);
    //where name in () and age < ?
    List<Employee> findByNameInAndAgeLessThan(List<String> 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<Employee> employees = employeeRepository.findByNameStartingWithAndAgeLessThan("test",22);
        for(Employee employee:employees){
            System.out.println(employee);
        }

    }

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

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

    @Test
    public void findByNameInAndOrAgeLessThantest(){
        List<String> name = new ArrayList<>();
        name.add("test1");
        name.add("test2");
        name.add("test3");
        List<Employee> 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<Employee> listEmployeeByNameAndAge(String name,Integer age);

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

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

    /*
    自定义查询SQL,like,占位符进行参数绑定
     */
    @Query("select o from Employee o where o.name like %:name%")
    List<Employee> 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<Employee> employees = employeeRepository.listEmployeeByNameAndAge("test6",22);
        for(Employee employee:employees){
            System.out.println(employee);
        }
    }

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

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

    @Test
    public void listEmployeeByLikeName2test(){
        List<Employee> 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);
    }


}

在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值