Spring Data JPA
:
Spring Data JPA
是
spring data
项目下的一个模块。提供了一套基于
JPA标准操作数据库的简化方案。底层默认的是依赖
Hibernate JPA
来实现的。
Spring Data JPA
的技术特点:我们只需要定义接口并集成
Spring Data JPA
中所提供的接口就可以了。不需要编写接口实现类。
jar包
修改配置文件
<?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/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!--配置读取properties文件的工具类-->
<context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
<!--配置c3p0数据库连接池-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="driverClass" value="${jdbc.driver.class}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!-- Spring 整合 JPA 配置 EntityManagerFactory-->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<!-- hibernate 相关的属性的注入 -->
<!-- 配置数据库类型 -->
<property name="database" value="MYSQL"/>
<!-- 正向工程 自动创建表 -->
<property name="generateDdl" value="true"/>
<!-- 显示执行的 SQL -->
<property name="showSql" value="true"/>
</bean>
</property>
<!--扫描实体包-->
<property name="packagesToScan">
<list>
<value>com.bjsxt.pojo</value>
</list>
</property>
</bean>
<!-- 配置 Hibernate 的事务管理器 -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<!-- 配置开启注解事务处理 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
<!-- 配置springIOC的注解扫描 -->
<context:component-scan base-package="com.bjsxt"/>
<!-- Spring Data JPA 的配置 -->
<!-- base-package:扫描dao接口所在的包 -->
<jpa:repositories base-package="com.bjsxt.dao"/>
</beans>
Dao层接口继承JpaRepository
package com.bjsxt.dao;
import com.bjsxt.pojo.Users;
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserDao extends JpaRepository<Users,Integer> {
}
不需要实现类
测试插入
@Test
@Transactional// 在测试类对于事务提交方式默认的是回滚
@Rollback(false)
public void testInsertUsers(){
Users users=new Users();
users.setUserage(17);
users.setUsername("张四");
userDao.save(users);
}
查询所有
@Test
@Transactional// 在测试类对于事务提交方式默认的是回滚
@Rollback(false)
public void findAllUsers(){
List<Users> list = userDao.findAll();
for (Users users:list){
System.out.println(users);
}
}
查询单个的俩种方法:
@Test
@Transactional// 在测试类对于事务提交方式默认的是回滚
@Rollback(false)
public void getOne(){
Users one = userDao.getOne(1);
System.out.println(one);
}
@Test
@Transactional// 在测试类对于事务提交方式默认的是回滚
@Rollback(false)
public void findOne(){
Users one = userDao.getOne(1);
System.out.println(one);
}
Spring Data JPA
的接口继承结构
Spring Data JPA
的运行原理
Repository
接口
Repository
接口是
Spring Data JPA
中为我我们提供的所有接口中的顶层接口
Repository
提供了两种查询方式的支持
1
)基于方法名称命名规则查询
2
)基于
@Query
注解查询
方法名称命名规则查询
规则:findBy(关键字)+属性名称(属性名称的首字母大写)+查询条件(首字母大写)
创建接口
方法命名,注解Query,以及不转译的三种方法,且都不需要实现类
JPQL:通过 Hibernate 的 HQL 演变过来的。他和 HQL 语法及其相似。
package com.bjsxt.dao;
import com.bjsxt.pojo.Users;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.Repository;
import java.util.List;
public interface UserDao extends Repository<Users,Integer> {
//通过Repository的方法命名来
List<Users> findByUsernameIs(String name);
List<Users> findByUsernameLike(String name);
List<Users> findByUsernameAndUserageGreaterThanEqual(String name,Integer age);
//通过@Query注解来写
@Query(value = "from Users where username=?")
List<Users> queryByname(String name);
@Query(value = "from Users where username like ?")
List<Users> queryBynameLike(String name);
@Query(value = "from Users where username=? and userage >=?")
List<Users> queryBynameAndage(String name,Integer age);
//使用@Query 注解查询 SQL
//nativeQuery:默认的是false.表示不开启sql查询。是否对value中的语句做转义。
@Query(value = "select * from t_users where username=?",nativeQuery = true)
List<Users> findBynameSql(String name);
@Query(value = "select * from t_users where username like ? ",nativeQuery = true)
List<Users> findBynameLikeSql(String name);
@Query(value = "select * from t_users where username=? and userage>=?",nativeQuery = true)
List<Users> findBynameAndage(String name,Integer age);
//使用@Query将数据更新
@Query(value = "update Users set userage=? where username=?")
@Modifying
void updateage(Integer age,String name);
}
测试类
package com.bjsxt.test;
import com.bjsxt.dao.CrudRepositoryDao;
import com.bjsxt.dao.UserDao;
import com.bjsxt.pojo.Users;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class HibernateTest {
@Autowired
private UserDao userDao;
@Autowired
private CrudRepositoryDao crudRepositoryDao;
@Test
public void testFindUsers(){
List<Users> usersList = userDao.findByUsernameIs("张四");
for (Users users:usersList){
System.out.println(users);
}
}
/**
* 测试like关键字
*/
@Test
public void testFindUsersLike(){
List<Users> usersList = userDao.findByUsernameLike("张%");
for (Users users:usersList){
System.out.println(users);
}
}
/**
* 测试多条件
*/
@Test
public void testFindUsersgt(){
List<Users> usersList = userDao.findByUsernameAndUserageGreaterThanEqual("张四",17);
for (Users users:usersList){
System.out.println(users);
}
}
/**
* 测试@Query 查询 JPQL
*/
@Test
public void testQueryByname(){
List<Users> usersList = userDao.queryByname("张四");
for (Users users:usersList){
System.out.println(users);
}
}
/**
* 测试@Query 查询 JPQL
*/
@Test
public void testQueryBynameLike(){
List<Users> usersList = userDao.queryBynameLike("张%");
for (Users users:usersList){
System.out.println(users);
}
}
/**
* 测试@Query 查询 JPQL
*/
@Test
public void testQueryBynameAndage(){
List<Users> usersList = userDao.queryBynameAndage("张四",17);
for (Users users:usersList){
System.out.println(users);
}
}
/**
* 测试@Query 查询 SQL
*/
@Test
public void testQueryBynameSql(){
List<Users> usersList = userDao.findBynameSql("张四");
for (Users users:usersList){
System.out.println(users);
}
}
/**
* 测试@Query 查询 Sql
*/
@Test
public void testQueryBynameLikeSql(){
List<Users> usersList = userDao.findBynameLikeSql("张%");
for (Users users:usersList){
System.out.println(users);
}
}
/**
* 测试@Query 查询 Sql
*/
@Test
public void testQueryBynameAndageSql(){
List<Users> usersList = userDao.findBynameAndage("张四",17);
for (Users users:usersList){
System.out.println(users);
}
}
/**
* 测试@Query update JPQL
*/
@Test
@Transactional
@Rollback(false)
public void testUpdateage(){
try {
userDao.updateage(22,"张四");
System.out.println("操作成功");
testQueryBynameSql();
}catch (Exception e){
System.out.println("操作失败");
e.printStackTrace();
}
}
}
CrudRepository
接口
package com.bjsxt.dao;
import com.bjsxt.pojo.Users;
import org.springframework.data.repository.CrudRepository;
public interface CrudRepositoryDao extends CrudRepository<Users,Integer> {
}
测试类
@Test
@Transactional
@Rollback(false)
public void testaddUsers(){
Users users=new Users();
users.setUsername("王五");
users.setUserage(28);
crudRepositoryDao.save(users);
}
@Test
public void testfindAll(){
Iterable<Users> UsersList = crudRepositoryDao.findAll();
for (Users users : UsersList) {
System.out.println(users);
}
}
@Test
public void testfindOne(){
Users one = crudRepositoryDao.findOne(6);
System.out.println(one);
}
@Test
public void testupdate(){
Users user = crudRepositoryDao.findOne(6);
System.out.println(user);
user.setUsername("李思思");
user.setUserage(27);
crudRepositoryDao.save(user);
testfindAll();
}
@Test
@Transactional
@Rollback(false)
public void testupdateSecond(){
Users user = crudRepositoryDao.findOne(7);
user.setUsername("李思纯");
user.setUserage(27);
testfindAll();
}
/**
* 批量添加
*/
@Test
@Transactional
@Rollback(false)
public void testAddMany(){
Users users=new Users();
users.setUsername("一户");
users.setUserage(29);
Users users1=new Users();
users1.setUsername("织姬");
users1.setUserage(25);
List<Users> usersList=new ArrayList<>();
usersList.add(users);
usersList.add(users1);
crudRepositoryDao.save(usersList);
testfindAll();
}
@Test
@Transactional
@Rollback(false)
public void testdelete(){
crudRepositoryDao.delete(4);
testfindAll();
}
PagingAndSortingRepository
接口
分页处理
接口
package com.bjsxt.dao;
import com.bjsxt.pojo.Users;
import org.springframework.data.repository.PagingAndSortingRepository;
public interface PageDao extends PagingAndSortingRepository<Users,Integer> {
}
排序测试:单列排序,多列排序
package com.bjsxt.test;
import com.bjsxt.dao.PageDao;
import com.bjsxt.pojo.Users;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
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.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.List;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class PageTest {
@Autowired
PageDao pageDao;
/**
* 分页
*/
@Test
public void testPage(){
int page=2;
int size=2;
Pageable pageable=new PageRequest(page,size);
Page<Users> users = pageDao.findAll(pageable);
System.out.println("总页数:"+users.getTotalPages());
System.out.println("总条数:"+users.getTotalElements());
List<Users> list = users.getContent();
for (Users user : list) {
System.out.println(user);
}
}
/**
* 排序
* 1.单列排序
* 2.多列排序
*/
@Test
public void testSort(){
Sort sort=new Sort(Sort.Direction.DESC,"userid");
List<Users> users = (List<Users>) pageDao.findAll(sort);
for (Users user : users) {
System.out.println(user);
}
}
/**
* 多列排序的时候,首先按照第一个条件排,如有相同,按照第二个条件
*/
@Test
public void testSortMany(){
Sort.Order order1=new Sort.Order(Sort.Direction.DESC,"userage");
Sort.Order order2=new Sort.Order(Sort.Direction.ASC,"userid");
Sort sort=new Sort(order1,order2);
List<Users> users = (List<Users>) pageDao.findAll(sort);
for (Users user : users) {
System.out.println(user);
}
}
}
JpaRepository
接口
JpaRepository
接口是我们开发时使用的最多的接口。其特点是可以帮助我们将其他接口的方法的返回值做适配处理。可以使得我们在开发时更方便的使用这些方法。
接口
package com.bjsxt.dao;
import com.bjsxt.pojo.Users;
import org.springframework.data.jpa.repository.JpaRepository;
public interface JpaRepositoryDao extends JpaRepository<Users,Integer> {
}
测试代码
@Test
public void testFindll(){
List<Users> users = jpaDao.findAll();
for (Users user : users) {
System.out.println(user);
}
}
JpaSpecificationExecutor
接口
完成多条件查询,并且支持分页与排序
接口:
package com.bjsxt.dao;
import com.bjsxt.pojo.Users;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
public interface JpaSpecificationExecutorDao extends JpaRepository<Users,Integer>, JpaSpecificationExecutor<Users> {
}
测试类:
/**
* 单条件查询
*/
@Test
public void testFindOne(){
Specification<Users> spec=new Specification<Users>() {
/**
* @return Predicate:定义了查询条件
* @param root<Users> root:根对象。封装了查询条件的对象
* @param criteriaQuery<?> query:定义了一个基本的查询。一般不使用
* @param criteriaBuilder cb:创建一个查询条件
*/
@Override
public Predicate toPredicate(Root<Users> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
Predicate pre = criteriaBuilder.equal(root.get("username"), "一户");
return pre;
}
};
List<Users> usersList = jpasDao.findAll(spec);
for (Users users : usersList) {
System.out.println(users);
}
}
/**
* 多条件查询
* 方式一
*/
@Test
public void testManyFindOne(){
Specification<Users> spec=new Specification<Users>() {
/**
* @return Predicate:定义了查询条件
* @param root<Users> root:根对象。封装了查询条件的对象
* @param criteriaQuery<?> query:定义了一个基本的查询。一般不使用
* @param criteriaBuilder cb:创建一个查询条件
*/
@Override
public Predicate toPredicate(Root<Users> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
List<Predicate> list=new ArrayList<>();
list.add(criteriaBuilder.equal(root.get("username"),"张四"));
list.add(criteriaBuilder.equal(root.get("userage"),22));
Predicate[] pre=new Predicate[list.size()];
return criteriaBuilder.and(list.toArray(pre));
}
};
List<Users> usersList = jpasDao.findAll(spec);
for (Users users : usersList) {
System.out.println(users);
}
}
/**
* 多条件查询
* 方式二
*/
@Test
public void testFindOneOR(){
Specification<Users> spec=new Specification<Users>() {
/**
* @return Predicate:定义了查询条件
* @param root<Users> root:根对象。封装了查询条件的对象
* @param criteriaQuery<?> query:定义了一个基本的查询。一般不使用
* @param criteriaBuilder cb:创建一个查询条件
*/
@Override
public Predicate toPredicate(Root<Users> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
return criteriaBuilder.or(criteriaBuilder.equal(root.get("userage"),22),criteriaBuilder.equal(root.get("username"),"一户"));
}
};
List<Users> usersList = jpasDao.findAll(spec);
for (Users users : usersList) {
System.out.println(users);
}
}
/**
* 多条件查询
* 分页
*/
@Test
public void testFindOnePage(){
Specification<Users> spec=new Specification<Users>() {
/**
* @return Predicate:定义了查询条件
* @param root<Users> root:根对象。封装了查询条件的对象
* @param criteriaQuery<?> query:定义了一个基本的查询。一般不使用
* @param criteriaBuilder cb:创建一个查询条件
*/
@Override
public Predicate toPredicate(Root<Users> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
return criteriaBuilder.like(root.get("username").as(String.class),"张%");
}
};
//分页操作
Pageable pageable=new PageRequest(0,2);
Page<Users> page = jpasDao.findAll(spec,pageable);
System.out.println("总页数:"+page.getTotalPages());
System.out.println("总条数"+page.getTotalElements());
List<Users> users = page.getContent();
for (Users user : users) {
System.out.println(user);
}
}