spring data|spring data 详解(2)查询规则、@Query、事务

接上篇spring data(1)

目录

  • repository接口是spring data的核心接口,不提供任何方法
  • public interface Repository<T, ID extends Serializable>
  • 注解的使用
  • repository的子接口

repository 中查询方法定义规则和使用

规则

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

使用

查询以test开头,年龄大于12的员工

public interface EmployeeRepository extends Repository<Employee,Integer> {

    Employee findByName(String name);

    Employee findByNameStartingWithAndAgeAfter();
}

测试类

package com.dsdj.repository;

import com.dsdj.domain.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 java.util.List;

/**
 * @ClassName EmployeeRepository
 * @Description TODO
 * @Author dsdj
 * @Date 2018/10/31 下午8:47
 * @Version 1.0
 **/
public class EmployeeRepositoryTest {

    private ApplicationContext ctx = null;
    private EmployeeRepository employeeRepository = null;
    @Before
    public void setup(){
        ctx = new ClassPathXmlApplicationContext("bean-jpa.xml");
        employeeRepository = ctx.getBean(EmployeeRepository.class);
        System.out.println("setup");
    }

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

    @Test
    public void testFindByName(){
        Employee zhangsan = employeeRepository.findByName("zhangsan");
        System.out.println(zhangsan);
    }

    @Test
    public void testFindByNameStartingWithAndAgeAfter(){
        List<Employee> t = employeeRepository.findByNameStartingWithAndAgeAfter("t", 20);

        for (Employee e:t){
            System.out.println(e);
        }

    }

}

输出

setup
Hibernate: 
    select
        employee0_.id as id1_0_,
        employee0_.age as age2_0_,
        employee0_.name as name3_0_ 
    from
        employee employee0_ 
    where
        (
            employee0_.name like ?
        ) 
        and employee0_.age>?
Employee{id=3, name='test2', age=21}
Employee{id=4, name='test3', age=22}
Employee{id=6, name='test5', age=21}
Employee{id=7, name='test6', age=22}
Employee{id=8, name='test16', age=22}
tearDown

@Query注解查询

思考:对于命名规则进行查询有以下的缺点:
1)方法名会比较长: 约定大于配置
2)对于一些复杂的查询,是很难实现

因此引入了注解查询的方式

  • 在Respository方法中使用,不需要遵循查询方法命名规则
  • 只需要将@Query定义在Requsitory中的方法之上即可
  • 支持命名参数及索引参数的使用
  • 支持本地查询
coding
package com.dsdj.repository;

import com.dsdj.domain.Employee;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.Repository;
import org.springframework.data.repository.query.Param;

import java.util.List;

/**
 * @ClassName EmployeeRepository
 * @Description TODO
 * @Author dsdj
 * @Date 2018/10/31 下午8:44
 * @Version 1.0
 **/
public interface EmployeeRepository extends Repository<Employee,Integer> {

    Employee findByName(String name);

    List<Employee> findByNameStartingWithAndAgeAfter(String name, int age);

    /**
     * 使用注解查询:获取最大id的员工信息
     * 注意下面的sql写法,Employee不是代表表名,而是代表类名
     * 这里的sql不是原生的sql语句
     */
    @Query("select a from Employee a where id = (select max(id) from Employee b)")
    Employee getEmployeeByMaxId();

    /**
     * 占位符查询1
     */
    @Query("select o from Employee o where age=?2 and name=?1 ")
    List<Employee> queryParams1(String name,Integer age);

    /**
     * 占位符查询2
     * 使用冒号的形式 需要使用 @Param注解
     */
    @Query("select o from Employee o where age=:age and name=:name ")
    List<Employee> queryParams2(@Param("name") String name,@Param("age") Integer age);

    /**
     * 模糊查询
     * @param name
     * @return
     */
    @Query("select o from Employee o where o.name like %?1%")
    List<Employee> queryLike1(String name);

    @Query("select o from Employee o where o.name like %:name%")
    List<Employee> queryLike2(@Param("name")String name);
}

更新删除整合事务操作

  • @Mofidying注解的使用
  • @Modifying结合@Query注解执行更新操作
  • @Transactional在spring data中的使用
coding

编写一个更新操作

/**
 * 更新操作
 */
@Query("update Employee o set o.age = :age where o.id = :id")
void updata(@Param("id") Integer id,@Param("age") Integer age);

测试类

public class EmployeeRepositoryTest {
    private ApplicationContext ctx = null;
    private EmployeeRepository employeeRepository = null;
    @Before
    public void setup(){
        ctx = new ClassPathXmlApplicationContext("bean-jpa.xml");
        employeeRepository = ctx.getBean(EmployeeRepository.class);
        System.out.println("setup");
    }
    @After
    public void tearDown(){
        ctx = null;
        System.out.println("tearDown");
    }
    @Test
    public void testUpdate(){
        employeeRepository.updata(2,10);
    }

}

此时报错:

Not supported for DML operations [update com.dsdj.domain.Employee o set o.age = :age where o.id = :id]

错误表示不支持DML操作,这个时候说明需要添加注解@Mofidying

/**
 * 更新操作
 */
@Modifying
@Query("update Employee o set o.age = :age where o.id = :id")
void updata(@Param("id") Integer id,@Param("age") Integer age);

此时还是报错:

nested exception is javax.persistence.TransactionRequiredException: Executing an update/delete query

报错表示update和delete需要添加事务

因此需要添加事务

一般事务实在service中定义,代码如下

EmployeeService.java

package com.dsdj.service;

import com.dsdj.repository.EmployeeRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class EmployeeService {
    @Autowired
    private EmployeeRepository employeeRepository;

    /**
     * 添加事务
     */
    @Transactional
    public void updata(Integer id ,Integer age){
        employeeRepository.updata(id,age);
    }
}

测试代码

package com.dsdj.service;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @ClassName EmployeeServiceTest
 * @Description TODO
 * @Author dsdj
 * @Date 2018/11/4 下午2:56
 * @Version 1.0
 **/
public class EmployeeServiceTest {

    private EmployeeService employeeService = null;
    private ApplicationContext ctx = null;
    @Before
    public void before(){
        ctx = new ClassPathXmlApplicationContext("bean-jpa.xml");
        employeeService = (EmployeeService) ctx.getBean("employeeService");
    }
    @After
    public void after(){
        ctx = null;
        System.out.println("over");
    }

    @Test
    public void testUpdate(){
        employeeService.updata(1,9);
    }
}

输出:

Hibernate: 
    update
        employee 
    set
        age=? 
    where
        id=?
over

成功

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值