Spring-data-jpa的使用

一,spring-data-jpa的简单介绍

SpringData:Spring 的一个子项目。用于简化数据库访问,支持NoSQL 和 关系数据存储。其主要目标是使数据库的访问变得方便快捷。

SpringData的主要模块(子项目)
在这里插入图片描述
Spring Data JPA: 是springData的子项目,致力于减少数据访问层 (DAO) 的开发量, 开发者唯一要做的就只是声明持久层的接口,并继承Repository(或Repository的子接口即可),其他都交给 Spring Data JPA 来帮你完成!

二,spring-data-jpa的快速入门

创建一个maven java项目

在这里插入图片描述

导入的依赖:
spring-data-jpa
Hibernate相关依赖
mysql驱动
c3p0连接池
junit测试

pom.xml文件

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>cn.xiaogui.example</groupId>
  <artifactId>springdatajpa-example</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <name>springdatajpa-example</name>
  <description>spring-data-jpa的简单使用</description>
  
  
   <!-- 全局属性配置  -->
  <properties>
	<project.source.encoding>utf-8</project.source.encoding>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
     <!-- 防止控制输出台中文乱码 -->
     <argLine>-Dfile.encoding=UTF-8</argLine> 
  	<spring-data-jpa.version>1.10.4.RELEASE</spring-data-jpa.version>
  	<hibernate.version>5.0.11.Final</hibernate.version>
  	<junit.version>4.12</junit.version>
  	<mysql.version>5.1.41</mysql.version>
  	<c3p0.version>0.9.1.2</c3p0.version>
  </properties>
  
  
  <dependencies>
  <!-- spring-data-jpa相关依赖 
      (这个依赖自动把一堆spring的东西依赖进来了,所有可以不需要再引入spring的包)-->
  	<dependency>
  		<groupId>org.springframework.data</groupId>
  		<artifactId>spring-data-jpa</artifactId>
  		<version>${spring-data-jpa.version}</version>
  	</dependency>


  	<dependency>
  		<!-- 做测试使用 -->
  		<groupId>junit</groupId>
  		<artifactId>junit</artifactId>
  		<version>${junit.version}</version>
  		<!-- 这个包只在测试使用 -->
  		<scope>test</scope>
  	</dependency>

	<!-- hibernate相关依赖 -->
  	<dependency>
  		<groupId>org.hibernate</groupId>
  		<artifactId>hibernate-core</artifactId>
  		<version>${hibernate.version}</version>
  	</dependency>

  	<dependency>
  		<groupId>org.hibernate</groupId>
  		<artifactId>hibernate-entitymanager</artifactId>
  		<version>${hibernate.version}</version>
  	</dependency>
  	
  	<!-- mysql驱动 -->
  	<dependency>
  		<groupId>mysql</groupId>
  		<artifactId>mysql-connector-java</artifactId>
  		<version>${mysql.version}</version>
  	</dependency>
  	<!--c3p0连接池  -->
  	<dependency>
  		<groupId>c3p0</groupId>
  		<artifactId>c3p0</artifactId>
  		<version>${c3p0.version}</version>
  	</dependency>
  </dependencies>
  
  
  <build>
  	<plugins>
  		<plugin>
  			<groupId>org.apache.maven.plugins</groupId>
  			<artifactId>maven-compiler-plugin</artifactId>
  			<version>3.5.1</version>
  			<configuration>
  				<!--源码1.7  -->
  				<source>1.7</source>
  				<!-- 打包1.7 -->
  				<target>1.7</target>
  				<encoding>UTF-8</encoding>
  			</configuration>
  		</plugin>
  	</plugins>
  </build>
</project>

由于spring-data-jpa依赖了一堆spring相关的依赖,会自动导入spring相关的一些依赖,所以在pom.xml中不需要引入spring相关的依赖

在这里插入图片描述

Spring整合springDataJpa,applicationContext.xml配置

1.首先新建db.properties文件,配置数据库相关的信息

jdbcUrl=jdbc:mysql://localhost:3306/springdatajpa?characterEncoding=utf8
driverClass=com.mysql.jdbc.Driver
user=root
password=root
initialPoolSize=10
maxPoolSize=30

2.创建applicationContext.xml文件,配置内容如下:

2.2配置包扫描,扫描@Service,@Contorller @Repository
2.3加载springdb.properties文件
2.4配置数据源dataSource

2.5配置JPA的EntityManagerFactory,这里面配置主要包括:
(1)需要配置数据源dataSource
(2)配置包扫描packagesToScan,扫描实体类,找到实体类上有关JPA的注解;
(3)配置持久化提供者persistenceProvider
(4)配置jpa网络适配器jpaVendorAdapter,这个里面主要是关于是否自动建表generateDdl,使用的数据库database数据库方言databasePlatform,在控制台上显示sql语句showSql等配置

2.6配置事务管理器 transactionManager
2.7配置支持注解的事务
2.8配置SpringData这里包扫描是扫描dao层,扫描那些定义的接口

<?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-4.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
        http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
    
    <!-- 配置自动扫描的包,扫描@service @controller @Repository注解-->
   	<context:component-scan base-package="cn.xiaogui"/>
    <!-- 1. 配置数据源 -->
    <context:property-placeholder location="classpath:db.properties"/>
    
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="jdbcUrl" value="${jdbcUrl}"/>
        <property name="driverClass" value="${driverClass}"/>
        <property name="user" value="${user}"/>
        <property name="password" value="${password}"/>
        <property name="initialPoolSize" value="${initialPoolSize}"/>
        <property name="maxPoolSize" value="${maxPoolSize}"/>
    </bean>
    <!-- 2. 配置 JPA 的 EntityManagerFactory -->
    <bean id="entityManagerFactory"   class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
         <!-- 配置数据源 --> 
        <property name="dataSource" ref="dataSource"/>
         <!-- 配置包扫描,扫描实体 -->
        <property name="packagesToScan" value="cn.xiaogui.entity"/>
        <!-- 配置持久化提供者 -->
        <property name="persistenceProvider">
			<bean class="org.hibernate.ejb.HibernatePersistence" />
		</property>
        <!-- 配置jpa网络适配器 -->
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
            	<!-- 是否自动建表 -->
            	<property name="generateDdl" value="true" />
            	<!-- 使用的数据库 -->
				<property name="database" value="MYSQL" />
				<!--数据库方言  -->
				<property name="databasePlatform" value="org.hibernate.dialect.MySQL5InnoDBDialect" />
				<!-- 在控制台打印sql语句 -->
				<property name="showSql" value="true" />
            </bean>
        </property>
        <!--配置jpa方言  -->
        <property name="jpaDialect">
			<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
		</property>
    </bean>
    
    <!-- 3. 配置事务管理器 -->
    <bean id="transactionManager"
        class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"/>  
    </bean>
    <!-- 4. 配置支持注解的事务 -->
    <tx:annotation-driven transaction-manager="transactionManager"/>
    
    <!-- 5. 配置 SpringData,需要加入  jpa 的命名空间 -->
    <!-- base-package: 扫描 Repository Bean 所在的 package -->
    <jpa:repositories base-package="cn.xiaogui.dao" entity-manager-factory-ref="entityManagerFactory" />
</beans>

3.测试整合

3.1先测试spring容器是否整合成功
在cn.xiaogui.test包下,创建ConfigTest测试类,编写单元测试代码,主要内容:
通过静态代码块创建ClassPathXmlApplicationContext对象,加载applicationContext.xml文件,启动spring容器。通过Spring容器获取dataSource对象,如果成功获取,并且说明整合成功了。

测试代码

package cn.xiaogui.test;

import java.sql.SQLException;

import javax.sql.DataSource;

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

import cn.xiaogui.dao.UserRepository;
/**
 * 
 * @author xiaogui
 * 
 *  Spring整合测试
 *
 */
public class ConfigTest {
	
	private static ApplicationContext applicationContext;
	
	static{
		//使用静态代码块,让程序来加载spring配置文件
		applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
	}
	
	
	 /** 测试spring容器是否实例化了数据源 。如果实例化了,说明Spring容器整合没问题 */
	    @Test
	    public void testDataSouce() throws SQLException {
	        DataSource dataSouce = (DataSource) applicationContext.getBean("dataSource");
	        System.out.println("数据源:"+ dataSouce);
	        System.out.println("连接:"+ dataSouce.getConnection());
	    }
    
}

输出结果:
在这里插入图片描述

说明spring整合成功

3.2测试spring整合JPA

整合JPA是否成功主要是看entityManagerFactory这个对象是否起作用,这个会起作用就会去扫描cn.xiaogui.entity包下的实体类,测试方法:

  (1)数据库提前创建出来,使用到的数据库springdatajpa我已经创建
  (2) 给实体类加上注解,然后开启Hibernate自动建表功能,启动Spring容器;

如果数据库自动建表成功,那就整合成功

实体类相对简单,只贴入关键部分

User类

@Entity   //表明这个一个实体
@Table(name="t_user")  //数据库中实体对应的表名
public class User {
	@Id    //id主键标识符
	@GeneratedValue(strategy=GenerationType.IDENTITY)  //主键生成策略,自动增长
	private Integer id;
	@Column    //对应数据表中的字段名,不写默认与实体类的属性名一致
	private String username;
	@Column
	private String city;
	
	@OneToMany(mappedBy="users",fetch=FetchType.EAGER)  //一对多,mappedBy:表示放弃主键维护,交给多的一方管理,一的一方fetch默认为FetchType.LAZY懒加载
	private List<Car> cars = new ArrayList<Car>();

Car类

@Entity   //表明这个一个实体
@Table(name="t_car")  //数据库中实体对应的表名
public class Car {
	@Id  //id主键标识符
	@GeneratedValue(strategy=GenerationType.IDENTITY)//主键生成策略,自动增长
	@Column //对应数据表中的字段名,不写默认与实体类的属性名一致
	private Integer id;
	@Column
	private String carName;
	@Column
	private Double price;
	
	@ManyToOne //多对一
	@JoinColumn(name="user_id") //外键在数据表中的字段
	private User users;

再次执行ConfigTest类中的测试代码,如果数据库中创建了User和Car两张数据表,表明整合JPA成功!

在这里插入图片描述

4.在dao层声明接口
在这里插入图片描述

在cn.xiaogui.dao包下创建UserRepository接口,并继承Repository接口或者Repository的子接口,由于Repository是一个空接口,博主选择继承Repository的子接口JpaRepository,在这个接口中提供了一些常规CRUD的操作。而JpaRepository的实现类SimpleJpaRepository对这些CRUD的操作进行了具体的实现,所以我们编写的UserRepository接口可以直接使用这些方法,而不需要进行具体的实现。

JpaRepository定义的规范:
在这里插入图片描述

SimpleJpaRepository对JpaRepository的实现

在这里插入图片描述

在这里插入图片描述

UserRepository接口代码

package cn.xiaogui.dao;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import cn.xiaogui.entity.User;

public interface UserRepository extends JpaRepository<User, Integer> {
	

}

在cn.xiaogui.test包下创建UserRepositoryTest测试类,通过这个类,我们进行springData的学习。

package cn.xiaogui.test;

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

import cn.xiaogui.dao.UserRepository;
import cn.xiaogui.entity.User;
/**
 * 
 * @author xiaogui
 * 
 *  Spring整合测试
 *
 */
public class UserRepositoryTest {
	
	private static ApplicationContext applicationContext;
	
	private static UserRepository userRepository;
	
	static{
		applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");  //使用静态代码块,让程序来加载spring配置文件
		userRepository = applicationContext.getBean(UserRepository.class);   //通过反射获取到UserRepository接口对象
	}
	
	/**
	 * 向t_user数据表中添加一条数据,并查询这条记录
	 */
	@Test
	public void insertUser() {
		User user = new User();
		user.setUsername("张三");
		user.setCity("北京");
		//向数据表中保存一条数据
		userRepository.save(user);
		
		//通过用户名,查询用户的信息
		user = userRepository.findOne(1);
	    System.out.println(user);
	}
    
}

执行结果如下图所示,我们dao层接口UserReository接口只继承了JpaRepository接口,就可以完成数据添加到数据库,从数据库中查询数据操作,这就是SpringData的魅力所在,大大简化了我们持久层的开发
在这里插入图片描述

三,spring-data-jpa原理分析

springData 出现的目的:为了简化,统一持久层 各种实现技术API,所以,springData 提供了一套标准的API 和 不同持久层整合技术的实现。

在这里插入图片描述

spring-data-commons :一套标准的API

在这里插入图片描述

spring-data-jpa:基于整合jpa实现,还对spring-data-commons的一套标准API进行了扩展

在这里插入图片描述

画图表示上述接口间的继承关系

在这里插入图片描述

对上述接口中的API进行讲解,其中Repository是空接口,不作讲解

CrudRepository接口API

在这里插入图片描述

PagingAndSortingRepository接口API

在这里插入图片描述

JpaRepository接口API

在这里插入图片描述

JpaSpecificationExecutor接口API(当需要进行带条件分页查询,多条件查询实体时,Dao层继承这个接口)

在这里插入图片描述

由于SimpleJpaRepository这个类对上述的这些API进行了具体的实现,所以我们dao层接口只要继承这些接口即可直接使用这些API。

在这里插入图片描述

画图简单分析调用方法的执行流程

在这里插入图片描述

四、spring data Query使用 实现条件查询

第一种方式:基于方法命名规则,自动生成JPQL查询语句

在这里插入图片描述

上图是对方法命名规则的说明

在cn.xiaogui.test包下创建UserRepositoryCriteriaQuery类,完成条件查询。

案例说明

基于一列的等值查询 findBy列名 例如:findByUsername(String name)

package cn.xiaogui.test;

import java.util.List;

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

import cn.xiaogui.dao.UserRepository;
import cn.xiaogui.entity.User;

public class UserRepositoryCriteriaQuery {
	
	private static ApplicationContext applicationContext;
	
	
	private static UserRepository userRepository; //UserRepository接口的代理对象
	
	static{
		//读取spring配置文件,加载spring容器
		applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
		userRepository = applicationContext.getBean(UserRepository.class);
	}
	/**
	 * 基于一列的等值查询
	 */
	@Test
	public void findByUsername() {
		List<User> list = userRepository.findByUsername("张三");
		
		System.out.println(list);
	}
}

dao层UserRepository接口只需要创建这个方法,不需要进行具体实现

package cn.xiaogui.dao;

import java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;

import cn.xiaogui.entity.User;

public interface UserRepository extends JpaRepository<User, Integer> {
	
	/**
	 * 基于一列的等值查询,不需要进行实现
	 * @param string
	 * @return
	 */
	List<User> findByUsername(String string);
	
}

控制台查询结果如下:

在这里插入图片描述

基于一列的模糊查询 findBy列名Like 例如:findByUsernameLike(String name)

由于在条件查询测试类UserRepositoryCriteriaQuery中,加载spring的配置文件,创建UserRepository接口的代理对象代码相同,以下的代码不再重复,只粘贴关键部分

UserRepositoryCriteriaQuery代码片段

	@Test
	public void findByUsernameLike() {
		List<User> list = userRepository.findByUsernameLike("%张%");  //注意:传入参数  %参数%
		System.out.println(list);
	}

UserRepository接口代码片段,同样这个方法也不需要具体实现


	/**
	 * 基于一列的模糊查询
	 * @param string
	 * @return
	 */

	List<User> findByUsernameLike(String string);

控制台输出结果
在这里插入图片描述

方法命名规则过多,自己可以尝试,不做过多赘述

第二种方式:不按命名规则我们自定义的查询方法,可以在dao层接口的执行方法上配置@Query注解,绑定JPQL语句或SQL语句

在UserRepository接口,自定义一个查询方法,由于没有按照方法命名规则,直接报错

在这里插入图片描述

可以在方法上配置@Query注解,表明这是一个查询方法,value绑定的是JPQL语句或SQL语句,这个有nativeQuery参数决定。默认为false,表示绑定的是JPQL语句,设置为true,绑定的是SQL语句

/**
	 * 自定义方法,基于两列的等值查询
	 * @param city
	 * @param username
	 * @return
	 */
	@Query(value="from User where username = ? and city = ?",nativeQuery=false)
	User queryUsernameAndCity(String city,String username);

UserRepositoryCriteriaQuery代码片段

/**
	 * 自定义的查询方法,基于两列的等值查询
	 */
	@Test
	public void queryUsernameAndCity() {
		User user = userRepository.queryUsernameAndCity("北京", "张三");
		System.out.println(user);
	}

控制台输出结果:
在这里插入图片描述

数据表中存在这条记录,却没有查询出来。检查UserRepository接口中定义的这个查询方法,原来传入的参数与绑定的JPQL语句中的占位符没有对应上。

解决方法:
(1) 在占位符后面添加标注,与传入的参数进行对应

	/**
	 * 自定义方法,基于两列的等值查询
	 * @param city
	 * @param username
	 * @return
	 */
	@Query(value="from User where username = ?2 and city = ?1",nativeQuery=false)
	User queryUsernameAndCity(String city,String username);

(2)在该方法传入的参数前面配置@param注解,@param中的参数名称要和value中的 :后面的名字对应

	/**
	 * 自定义方法,基于两列的等值查询
	 * @param city
	 * @param username
	 * @return
	 */
	@Query(value="from User where username = :userName and city = :city",nativeQuery=false)  //@param中的参数名称要和value中的 :后面的名字对应
	User queryUsernameAndCity(@Param("city") String city,@Param("userName") String username);

使用第二种解决方案,再次执行UserRepositoryCriteriaQuery中这个方法,查询到数据

在这里插入图片描述

第三种方式:不按命名规则我们自定义的查询方法,可以在dao层接口的执行方法上配置@Query注解,将JPQL语句或SQL语句绑定到实体类上

UserRepository接口代码片段

/**
	 * 自定义方法,基于两列的等值查询
	 * @param city
	 * @param username
	 * @return
	 */
	@Query
	User queryUsernameAndCity2(@Param("city")String city, @Param("username")String username);

User实体类代码片段

@NamedQueries({
	@NamedQuery(name="User.queryUsernameAndCity2", 
			query = "from User where username = :username and city = :city")})
public class User {
	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	private Integer id;
	@Column
	private String username;
	@Column
	private String city;

UserRepositoryCriteriaQuery条件查询测试类调用方法,可以查询到结果数据

在这里插入图片描述

上述三种条件查询方式,推荐使用第一种方法命名规则查询,不建议使用第三种,过于繁琐

五,带条件的 修改和删除操作

使用@Query注解,搭配@Modifying注解完成 带条件的修改,删除操作

案例说明:根据id修改用户名

在UserRepository接口代码片段

	/**
	 * 自定义修改操作,根据id修改用户名
	 * UPDATE 或 DELETE 操作需要使用事务, 此时需要定义 Service 层. 在 Service 层的方法上添加事务操作. 
     * 默认情况下, SpringData 的每个方法上有事务, 但都是一个只读事务. 他们不能完成修改操作!
	 */
	@Query(value="update User set username= ?2 where id = ?1") 
	@Modifying //表示更新操作(修改或删除)
	void updateUsername(Integer id,String username);

由于修改和删除都是更新操作,只读事务是不能实现的,因此新建UserService类,在Service方法中添加事务注解

UserService代码片段

package cn.xiaogui.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import cn.xiaogui.dao.UserRepository;

@Service
public class UserService {
	@Autowired
	private UserRepository userRepository; //注入dao层接口对象
	
	/**
	 * 根据id修改用户名
	 */
	public void updateUsername() {
		userRepository.updateUsername(1, "小鬼");
	}
}

在UserRepositoryCriteriaUpdate测试类中调用UserService中的这个方法测试

package cn.xiaogui.test;

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

import cn.xiaogui.service.UserService;

public class UserRepositoryCriteriaUpdate {
	
	private static ApplicationContext applicationContext;
	
	private static UserService userService;
	
	static{
		//读取spring配置文件,加载spring容器
		applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
		userService = applicationContext.getBean(UserService.class);
	}
	
	/**
	 * 根据id修改用户名
	 */
	
	@Test
	public void updateUsername() {
		userService.updateUsername();
	}
	
	
}

控制台输出

在这里插入图片描述

根据控制台报出的错误,我们需要在UserService中设置事物

/**
	 * 根据id修改用户名
	 */
	@Transactional
	public void updateUsername() {
		userRepository.updateUsername(1, "小鬼");
	}

再次在UserRepositoryCriteriaUpdate测试类中调用UserService中的这个方法测试,数据修改成功

在这里插入图片描述

查询数据表
在这里插入图片描述

删除操作不再赘述,大家可以自己进行尝试!

六,带条件的分页查询

首先在数据表t_user中添加数据

在这里插入图片描述

实现带条件的分页查询,主要使用到前面提到的JpaSpecificationExecutor接口中定义的API,这个接口的主要作用就是进行带条件的查询

在这里插入图片描述
进行带条件的分页查询,使用的API是这个接口中的
Page findAll(Specification spec, Pageable pageable);

参数:
spec:构造Specification对象条件查询对象(类似hibernate的QBC查询),由于这个参数是一个接口对象,通过匿名对象创建

pageable:封装了请求分页的信息: page,size,sort三个参数,其中page索引从0开始,表示第一页

在这里插入图片描述

PageRequest类实现了Pageable接口

由于JpaSpecificationExecutor接口不属于Repository体系,所以我们要使用带条件的分页查询,dao层接口需要同时继承JpaRepository,JpaSpecificationExecutor这两个接口

在这里插入图片描述

在UserRepositoryCriteriaQuery测试类中编写带条件的分页查询代码

   /**
	 * 实现带条件的分页查询
	 */
	@Test
	public void  findPageData() {
		
		 // 目标:查询id<5 并且city为北京的 的第1页的数据,每页显示为5条记录
		
		//创建pageable对象  
		Pageable pageable = new PageRequest(1-1, 5);  //0 表示从第一页开始  5 表示每页显示多少条数据
		
		//根据查询条件,构造Specification对象条件查询对象(类似hibernate的QBC查询)
		Specification<User> spec = new Specification<User>() {
			
			/**
			 * 构造条件查询方法,如果返回值为null,表示无条件查询,查询所有
			 * 
			 * root参数:代表查询的实体类,用来 获取条件表达式  username = ? city =? 等
			 * query参数:可以从中可到 Root 对象, 即告知 JPA Criteria 查询要查询哪一个实体类. 还可以
			 * 来添加查询条件, 还可以结合 EntityManager 对象得到最终查询的 TypedQuery 对象 
			 * cb参数:构造Predicate对象 条件对象,构造复杂查询效果
			 * @return: Predicate 类型, 代表一个查询条件. 
			 */
			@Override
			public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				//在开发过程中,一般使用root和cb这两个参数
				
				
				//定义一个list集合,用于存放多个条件
				List<Predicate> predicates = new ArrayList<Predicate>();
				
				//查询id小于5的数据
				Predicate p1 = cb.lt(root.get("id").as(Integer.class), 5);
				
				predicates.add(p1);
				
				Predicate p2 = cb.equal(root.get("city"), "北京");
				
				predicates.add(p2);
				
				//当predicates中没有元素时,表示无条件查询
				return cb.and(predicates.toArray(new Predicate[predicates.size()]));
			}
		};
		//得到分页对象
		Page<User> page = userRepository.findAll(spec , pageable);
		
		//输出查询到的结果
		System.out.println(page.getContent());
	}

在控制台输出结果

在这里插入图片描述

小结:
主要对springdatajpa的常用操作进行了简单的说明介绍。

1.如何使用springdata自带的API及springdatajpa自身扩展的API

2.根据方法命名规则进行条件查询,以及通过@query注解,进行自定义方法进行条件查询

3.使用@query ,@modifying注解完成修改或删除的更新操作

4.最后使用JpaSpecificationExecutor接口中的Page findAll(Specification spec, Pageable pageable)方法,完成带条件的分页查询

分享示例项目在码云上的地址:https://gitee.com/xiaoguixiaogege/springdatajpa

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值