接上篇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
成功