1 Spring Data JPA

1.Spring Data JPA的概念

在介绍Spring Data JPA的时候,我们首先认识下Hibernate。Hibernate是数据访问解决技术的绝对霸主,使用O/R映射(Object-Relational Mapping)技术实现数据访问,O/R映射即将领域模型类和数据库的表进行映射,通过程序操作对象而实现表数据操作的能力,让数据访问操作无须关注数据库相关的技术。
随着Hibernate的盛行,Hibernate主导了EJB 3.0的JPA规范,JPA即Java Persistence API。JPA是一个基于O/R映射的标准规范(目前最新版本是JPA 2.1)。所谓规范即只定义标准规则(如注解、接口),不提供实现,软件提供商可以按照标准规范来实现,而使用者只需按照规范中定义的方式来使用,而不用和软件提供商的实现打交道。JPA的主要实现由Hibernate、EclipseLink和OpenJPA等,这也意味着我们只要使用JPA来开发,无论是哪一个开发方式都是一样的。
Spring Data JPA是Spring Data的一个子项目,它通过提供基于JPA的Repository极大地减少了JPA作为数据访问方案的代码量。

2. 定义数据访问层

使用Spring Data JPA建立数据访问层十分简单,只需在dao层定义一个继承JpaRepository的接口即可,如:

package com.example.demo.dao;import com.example.demo.entity.SearchRecordEntity;
import org.springframework.data.jpa.repository.JpaRepository;/*** SearchRecordRepository*  定义数据访问操作的方法* @Description*/
public interface SearchRecordRepository extends JpaRepository<SearchRecordEntity,Integer> {}

3.配置使用Spring Data JPA

在Spring环境中,使用Spring Data JPA可通过@EnableJpaRepositories注解来开启Spring Data JPA的支持,@EnableJpaRepositories接收的value参数用来扫描数据访问层所在包下的数据访问的接口定义。

4.定义查询方法

在讲解查询方法前,假设我们有一张数据表叫 t_search_record,有ID(Number)、NAME(Varchar)、remark (Varchar)几个字段;对应的实体类叫SearchRecordEntity,分别有id(Long)、name(String)、remark(String)。下面我们就以这个简单的实体查询作为演示。
(1)根据属性名查询
Spring Data JPA支持通过定义在Repository接口中的方法名来定义查询,而方法名是根据实体类的属性名来确定的。
1)常规查询。根据属性名来定义查询方法,示例如下:

package com.example.demo.dao;import com.example.demo.entity.SearchRecordEntity;
import org.springframework.data.jpa.repository.JpaRepository;import java.util.List;/*** SearchRecordRepository*  定义数据访问操作的方法* @Description*/
public interface SearchRecordRepository extends JpaRepository<SearchRecordEntity,Integer> {/*** 通过名字精确查询,参数为name* @param name* @return*/List<SearchRecordEntity> findByName(String name);/*** 通过名字like查询,参数为name* @param name* @return*/List<SearchRecordEntity> findByNameLike(String name);/*** 通过名字和备注查询,参数为name、remark* @param name* @return*/List<SearchRecordEntity> findByNameAndRemark(String name,String remark);}

从代码可以看出,这里使用了findBy、Like、And这样的关键字。其中findBy可以用find、read、readBy、query、queryBy、get、getBy来代替。
2)限制结果数量。结果数量是用top和first关键字来实现的,例如:

package com.example.demo.dao;import com.example.demo.entity.SearchRecordEntity;
import org.springframework.data.jpa.repository.JpaRepository;import java.util.List;/*** SearchRecordRepository*  定义数据访问操作的方法* @Description*/
public interface SearchRecordRepository extends JpaRepository<SearchRecordEntity,Integer> {/*** 获取符合查询条件的前10条数据* @param name* @return*/List<SearchRecordEntity> findFirst10ByName(String name);/*** 获得符合查询条件的前30条数据* @param name* @return*/List<SearchRecordEntity> findTop30ByName(String name);}

(2)使用JPA的NamedQuery查询
Spring Data JPA支持用JPA的NameQuery来定义查询方法,即一个名称映射一个查询语句。例如:

package com.example.demo.entity;import lombok.Data;
import org.hibernate.annotations.NamedQuery;import javax.persistence.Entity;/*** SearchRecordEntity** @Description*/
@Data
@Entity
@NamedQuery(name = "SearchRecordEntity.findByName",query = "select sr from SearchRecordEntity sr where sr.name=?1")
public class SearchRecordEntity {/*** 主键ID*/private Integer id;/*** 名称*/private String name;/*** 备注*/private String remark;}

使用如下语句:

package com.example.demo.dao;import com.example.demo.entity.SearchRecordEntity;
import org.springframework.data.jpa.repository.JpaRepository;import java.util.List;/*** SearchRecordRepository*  定义数据访问操作的方法* @Description*/
public interface SearchRecordRepository extends JpaRepository<SearchRecordEntity,Integer> {/*** 这时我们使用的是NamedQuery里定义的查询语句,而不是根据方法名称查询* @param name* @return*/List<SearchRecordEntity> findByName(String name);}

(3)使用@Query查询
1)使用参数索引。Spring Data JPA还支持用@Query注解在接口的方法上实现查询,例如:

package com.example.demo.dao;import com.example.demo.entity.SearchRecordEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;import java.util.List;/*** SearchRecordRepository*  定义数据访问操作的方法* @Description*/
public interface SearchRecordRepository extends JpaRepository<SearchRecordEntity,Integer> {/*** 通过名字精确查询,参数为name* @param name* @return*/@Query("select sr from SearchRecordEntity sr where sr.name = ?1")List<SearchRecordEntity> findByName(String name);}

2)使用命名参数。上面的例子是使用参数的索引号来查询的,在Spring Data JPA里还支持在语句里用名称来匹配查询参数,例如:

package com.example.demo.dao;import com.example.demo.entity.SearchRecordEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;import java.util.List;/*** SearchRecordRepository*  定义数据访问操作的方法* @Description*/
public interface SearchRecordRepository extends JpaRepository<SearchRecordEntity,Integer> {/*** 通过名字精确查询,参数为name* @param name* @return*/@Query("select sr from SearchRecordEntity sr where sr.name = :name")List<SearchRecordEntity> findByName(String name);}

3)更新查询。Spring Data JPA支持@Modifying和@Query注解组合来实现更新查询,例如:

package com.example.demo.dao;import com.example.demo.entity.SearchRecordEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.transaction.annotation.Transactional;import java.util.List;/*** SearchRecordRepository*  定义数据访问操作的方法* @Description*/
public interface SearchRecordRepository extends JpaRepository<SearchRecordEntity,Integer> {/*** * @param name* @return  返回更新语句影响的行数*/@Modifying@Transactional@Query("update SearchRecordEntity sr  set  sr.name = ?1")int setName(String name);}

(4)Specification
JPA提供了基于准则查询的方式,即Criteria查询。而Spring Data JPA提供了一个Specification(规范)接口让我们可以更方便地构造准则查询,Specification接口定义了一个toPredicate方法用来构造查询条件。
1)定义。我们的接口类必需实现JpaSpecificationExecutor接口,代码如下:

package com.example.demo.dao;import com.example.demo.entity.SearchRecordEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;import java.util.List;/*** SearchRecordRepository*  定义数据访问操作的方法* @Description*/
public interface SearchRecordRepository extends JpaRepository<SearchRecordEntity,Integer>,JpaSpecificationExecutor<SearchRecordEntity> {}

然后需要定义Criterial查询,代码如下:

package com.example.demo.config;import com.example.demo.entity.SearchRecordEntity;
import org.springframework.data.jpa.domain.Specification;import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;/*** CustomerSpecs** @Description*/
public class CustomerSpecs {public static Specification<SearchRecordEntity>  getSearchRecord(String name){return new Specification<SearchRecordEntity>() {@Overridepublic Predicate toPredicate(Root<SearchRecordEntity> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {return criteriaBuilder.equal(root.get("name"),name);}};}}

我们使用Root来获得需要查询的属性,通过CriteriaBuilder构造查询条件。
注意:CriteriaBuilder、CriteriaQuery、Predicate、Root都是来自JPA的接口。
CriteriaBuilder包含的条件构造有:exists、and、or、not、conjunction、disjunction、isTrue、isFalse、isNull、isNotNull、equal、notEqual、greaterThan、greaterThanOrEqualTo、lessThan、lessThanOrEqualTo、between等,详细请查看CriteriaBuilder的API。
2)使用静态导入:

package com.example.demo.service;import com.example.demo.dao.SearchRecordRepository;
import com.example.demo.entity.SearchRecordEntity;
import org.springframework.stereotype.Service;import javax.annotation.Resource;
import java.util.List;
import static com.example.demo.config.CustomerSpecs.*;/*** SearchRecordService** @Description*/
@Service
public class SearchRecordService {@Resourceprivate SearchRecordRepository searchRecordRepository;public List<SearchRecordEntity> findByName(String name){List<SearchRecordEntity> all = searchRecordRepository.findAll(getSearchRecord(name));return all;}}

(5)排序与分页
Spring Data JPA充分考虑了在实际开发中所必需的排序和分页的场景,为我们提供了Sort类以及Page接口和Pageable接口。
1)定义:

package com.example.demo.dao;import com.example.demo.entity.SearchRecordEntity;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.stereotype.Repository;import java.util.List;/*** SearchRecordRepository*  定义数据访问操作的方法* @Description*/
@Repository
public interface SearchRecordRepository extends JpaRepository<SearchRecordEntity,Integer>,JpaSpecificationExecutor<SearchRecordEntity> {/*** 支持排序* @param name* @param sort* @return*/List<SearchRecordEntity> findByName(String name, Sort sort);/*** 支持分页* @param name* @param pageable* @return*/Page<SearchRecordEntity> findByName(String name, Pageable pageable);}

2)使用排序:

package com.example.demo.service;import com.example.demo.dao.SearchRecordRepository;
import com.example.demo.entity.SearchRecordEntity;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import static com.example.demo.config.CustomerSpecs.*;/*** SearchRecordService** @Description*/
@Service
public class SearchRecordService {@Resourceprivate SearchRecordRepository searchRecordRepository;public List<SearchRecordEntity> findByNameAndSort(String name){List<SearchRecordEntity> searchRecordEntities = searchRecordRepository.findByName(name, Sort.by(Sort.Direction.DESC,"id"));return searchRecordEntities;}}

3)使用分页:

package com.example.demo.service;import com.example.demo.dao.SearchRecordRepository;
import com.example.demo.entity.SearchRecordEntity;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import static com.example.demo.config.CustomerSpecs.*;/*** SearchRecordService** @Description*/
@Service
public class SearchRecordService {@Resourceprivate SearchRecordRepository searchRecordRepository;public Page<SearchRecordEntity> findByNamePage(String name){Page<SearchRecordEntity> searchRecordEntities = searchRecordRepository.findByName(name, PageRequest.of(0, 10));return searchRecordEntities;}}

其中Page接口可以获得当前页面的记录、总页数、总记录数、是否有上一页或下一页等。

5.自定义Repository的实现

Spring Data提供了和CrudRepository、PagingAndSortingRepository;Spring Data JPA也提供了JpaRepository。如果我们想把自己常用的数据库操作封装起来,像JpaRepository一样提供给我们领域类的Repository接口使用,应该怎么操做呢?
(1)定义自定义Repository接口

package com.example.demo.dao;import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.data.repository.PagingAndSortingRepository;import java.io.Serializable;/*** CustomRepository*  @NoRepositoryBean指明当前这个接口不是我们领域类的接口(如PersonRepository。*  我们自定义的Repository实现PagingAndSortingRepository接口,具备分页和排序的能力。* @Description*/
@NoRepositoryBean
public interface CustomRepository<T,ID extends Serializable> extends PagingAndSortingRepository<T,ID> {/*** 要定义的数据操作方法在接口中的定义* @param id* @return*/public T getById(ID id);}

(2)定义接口实现类

package com.example.demo.dao;import org.springframework.data.jpa.repository.support.SimpleJpaRepository;import javax.persistence.EntityManager;
import java.io.Serializable;/*** CustomRepositoryImpl*  首先要实现CustomRepository接口,继承SimpleJpaRepository类让我们可以使用其提供的方法(如findAll)。* @Description*/
public class CustomRepositoryImpl<T, ID extends Serializable> extends SimpleJpaRepository<T, ID> implements CustomRepository<T, ID> {/*** 让数据操作方法中可以使用entityManager*/private final EntityManager entityManager;/*** CustomRepositoryImpl的构造函数,需当前处理的领域类类型和entityManager作为构造参数,在这里也给我们的entityManager赋值了。* @param clazz* @param entityManager*/public CustomRepositoryImpl(Class<T> clazz, EntityManager entityManager) {super(clazz, entityManager);this.entityManager = entityManager;}@Overridepublic T getById(ID id) {//在此处定义数据访问操作,如调用findAll方法并构造一些查询条件。T t = null;return t;}}

(3)自定义RepositoryFactoryBean。

自定义JpaRepositoryFactoryBean替代默认RepositoryFactoryBean,我们会获得一个RepositoryFactory,RepositoryFactory将会注册我们自定义的Repository的实现:

package com.example.demo.dao;import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.support.*;
import org.springframework.data.repository.core.RepositoryInformation;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.core.support.RepositoryFactorySupport;
import org.springframework.util.Assert;import javax.persistence.EntityManager;
import java.io.Serializable;/*** CustomRepositoryFactoryBean* 自定义RepositoryFactoryBean,继承JpaRepositoryFactoryBean** @Description*/
public class CustomRepositoryFactoryBean<T extends JpaRepository<S,ID>,S,ID extends Serializable> extends JpaRepositoryFactoryBean<T,S,ID> {public CustomRepositoryFactoryBean(Class<? extends T> repositoryInterface) {super(repositoryInterface);}/*** 重写createRepositoryFactory方法,用当前的CustomRepositoryFactory创建实例* @param entityManager* @return*/@Overrideprotected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager){return new CustomRepositoryFactory(entityManager);}/*** 创建CustomRepositoryFactory,并继承JpaRepositoryFactory*/private static class CustomRepositoryFactory extends JpaRepositoryFactory {public CustomRepositoryFactory(EntityManager entityManager) {super(entityManager);}/*** 重写getTargetRepository方法,获得当前自定义的Repository实现* @param information* @param entityManager* @return*/@Override@SuppressWarnings({"unchecked"})protected SimpleJpaRepository<?, ?> getTargetRepository(RepositoryInformation information, EntityManager entityManager) {return new CustomRepositoryImpl(information.getDomainType(), entityManager);}/*** 重写getRepositoryBaseClass,获得当前自定义的Repository实现的类型* @param metadata* @return*/@Overrideprotected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata){return CustomRepositoryImpl.class;}}}

(4)开启自定义支持使用@EnableJpaRepositories的repositoryFactoryBeanClass来指定FactoryBean即可,代码如下:
@EnableJpaRepositories(repositoryFactoryBeanClass= CustomRepositoryFactoryBean.class)

2 Spring Boot的支持

1.JDBC的自动配置

spring-boot-starter-data-jpa依赖于spring-boot-starter-jdbc,而Spring Boot对JDBC做了一些自动配置。源码在org.springframework.boot.autoconfigure.jdbc下

从源码分析可以看出,通过“spring.datasoure”为前缀的属性自动配置dataSource;Spring Boot自动开启了注解事务的支持(@EnableTransactionManagement);还配置了一个jdbcTemplate。
Spring Boot还提供了一个初始化数据的功能:放置在类路径下的schema.sql文件会自动用来初始化表结构;放置在类路径下的data.sql文件会自动用来填充表数据。

2.对JPA的自动配置

Spring Boot对JPA的自动配置放置在org.springframework.boot.autoconfigure.orm.jpa下

从HibernateJpaAutoConfiguration可以看出,Spring Boot默认JPA的实现者是Hibernate;HibernateJpaAutoConfiguration依赖于DataSourceAutoConfiguration。从JpaProperties的源码可以看出,配置JPA可以使用spring.jpa为前缀的属性在application.properties中配置。
从JpaBaseConfiguration的源码中可以看出,Spring Boot为我们配置了transactionManager、jpaVendorAdapter、entityManagerFactory等Bean。JpaBaseConfiguration还有一个getPackagesToScan方法,可以自动扫描注解有@Entity的实体类。
在Web项目中我们经常会遇到在控制器或者页面访问数据的时候出现会话连接已关闭的错误,这时候我们会配置一个Open EntityManager(Session)In View这个过滤器。令人惊喜的是,Spring Boot为我们自动配置了OpenEntityManagerInViewInterceptor这个Bean,并注册到Spring MVC的拦截器中。

3.对Spring Data JPA的自动配置

而Spring Boot对Spring Data JPA的自动配置放置在org.springframework.boot.autoconfigure.data.jpa下

从JpaRepositoriesAutoConfiguration和JpaRepositoriesAutoConfigureRegistrar源码可以看出,JpaRepositoriesAutoConfiguration是依赖于HibernateJpaAutoConfiguration配置的,且Spring Boot自动开启了对Spring Data JPA的支持,即我们无须在配置类显示声明@EnableJpaRepositories。

4.Spring Boot下的Spring Data JPA

由以上分析可知,我们在Spring Boot下使用Spring Data JPA,在项目的Maven依赖里添加spring-boot-stater-data-jpa,然后只需定义DataSource、实体类和数据访问层,并在需要使用数据访问的地方注入数据访问层的Bean即可,无须任何额外配置。

3  代码示例

1.entity层

package com.example.demo.entity;import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import lombok.Data;
import org.hibernate.annotations.NamedQuery;import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;/*** SearchRecordEntity* @Entity注解指明这是一个和数据库表映射的实体类* @Description*/
@Data
@Entity
@AllArgsConstructor
@NoArgsConstructor
@NamedQuery(name = "SearchRecordEntity.withNameAndRemarkQueryList",query = "select sr from SearchRecordEntity sr where sr.name=?1 and remark=?2")
public class SearchRecordEntity {/*** 主键ID* @Id注解指明这个属性映射为数据库的主键* @GeneratedValue注解默认使用主键生成方式为自增,hibernate会为我们自动生成一个名为HIBERNATE_SEQUENCE的序列*/@Id@GeneratedValueprivate Integer id;/*** 名称*/private String name;/*** 备注*/private String remark;
}

在此例中使用的注解也许和你平时经常使用的注解实体类不大一样,比如没有使用@Table(实体类映射表名)、@Column(属性映射字段名)注解。这是因为我们是采用正向工程通过实体类生成表结构,而不是通过逆向工程从表结构生成数据库。
在这里,我们没有通过@Column注解来注解普通属性,@Column是用来映射属性名和字段名,不注解的时候hibernate会自动根据属性名生成数据表的字段名。如属性名name映射成字段NAME;多字母属性如testName会自动映射为TEST_NAME。表名的映射规则也如此。

2.定义数据访问接口

package com.example.demo.dao;import com.example.demo.entity.SearchRecordEntity;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;import java.util.List;/*** SearchRecordRepository*  定义数据访问操作的方法* @Description*/
@Repository
public interface SearchRecordRepository extends JpaRepository<SearchRecordEntity,Integer>,JpaSpecificationExecutor<SearchRecordEntity> {/*** 通过名字精确查询,参数为name*  使用方法名查询,接受一个name参数,返回值为列表。* @param name* @return*/List<SearchRecordEntity> findByName(String name);/**** 使用方法名查询,接受name 和 remark,返回值为单个对象* @param name* @return*/List<SearchRecordEntity> findByNameAndRemark(String name,String remark);/*** 使用@Query查询,参数按照名称绑定* @param name* @param remark* @return*/@Query("select sr from SearchRecordEntity sr where sr.name = :name and sr.remark = :remark")List<SearchRecordEntity> withNameAndRemarkQuery(@Param("name") String name,@Param("remark") String remark);/*** 使用@NamedQuery查询,请注意我们在实体类中做的@NamedQuery的定义* @param name* @param remark* @return*/List<SearchRecordEntity> withNameAndRemarkQueryList(String name, String remark);}

3.controller层

package com.example.demo.controller;import com.example.demo.dao.SearchRecordRepository;
import com.example.demo.entity.SearchRecordEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.List;/*** SearchRecordController** @Description*/
@RestController
@RequestMapping("/api/search")
public class SearchRecordController {@Autowiredprivate SearchRecordRepository searchRecordRepository;/*** 增加数据** @param name* @param remark* @return*/@RequestMapping("/save")public SearchRecordEntity save(String name, String remark) {SearchRecordEntity sr = searchRecordRepository.save(new SearchRecordEntity(null, name, remark));return sr;}/*** 测试 findByName** @param name* @return*/@RequestMapping("/q1")public List<SearchRecordEntity> q1(String name) {List<SearchRecordEntity> searchRecordEntityList = searchRecordRepository.findByName(name);return searchRecordEntityList;}/*** 测试findByNameAndAddress** @param name* @param remark* @return*/@RequestMapping("/q2")public List<SearchRecordEntity> q2(String name, String remark) {List<SearchRecordEntity> searchRecordEntities = searchRecordRepository.findByNameAndRemark(name, remark);return searchRecordEntities;}/*** withNameAndRemarkQuery* @param name* @param remark* @return*/@RequestMapping("/q3")public List<SearchRecordEntity> q3(String name, String remark) {List<SearchRecordEntity> searchRecordEntities = searchRecordRepository.withNameAndRemarkQuery(name, remark);return searchRecordEntities;}/*** 测试withNameAndRemarkQueryList* @param name* @param address* @return*/@RequestMapping("/q4")public List<SearchRecordEntity> q4(String name, String address) {List<SearchRecordEntity> searchRecordEntities = searchRecordRepository.withNameAndRemarkQueryList(name, address);return searchRecordEntities;}/*** 测试排序*/@RequestMapping("/sort")public List<SearchRecordEntity> sort() {List<SearchRecordEntity> searchRecordEntities = searchRecordRepository.findAll(Sort.by(Sort.Direction.DESC, "id"));return searchRecordEntities;}/*** 测试分页*/@RequestMapping("/page")public Page<SearchRecordEntity> page() {Page<SearchRecordEntity> pagePeople = searchRecordRepository.findAll(PageRequest.of(1, 2));return pagePeople;}}

4.启动类

package com.example.demo;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.transaction.annotation.EnableTransactionManagement;@SpringBootApplication
@EnableJpaRepositories(value = "com.example.demo.dao")
@EnableTransactionManagement
public class DemoApplication {public static void main(String[] args) {SpringApplication.run(DemoApplication.class, args);}}

5.配置文件

server.port=8080
# mysql
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.url=jdbc:mysql://localhost:3306/data-portrait?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC&allowPublicKeyRetrieval=true
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
logging.file.name=logs/springboot-jpa.log
spring.jpa.database=mysql
# hibernate提供了根据实体类自动维护数据库表结构的功能,可通过spring.jpa.hibernate.ddl-auto来配置:
# create:启动时删除上一次生成的表,并根据实体类生成表,表中数据会被清空。
# create-drop:启动时根据实体类生成表,sessionFactory关闭时表会被删除。
# update:启动时会根据实体类生成表,当实体类属性变动的时候,表结构也会更新,在初期开发阶段使用此选项。
# validate:启动时验证实体类和数据表是否一致,在我们数据结构稳定时采用此选项。
# none:不采取任何措施。
spring.jpa.hibernate.ddl-auto=none
# spring.jpa.show-sql用来设置hibernate操作的时候在控制台显示其真实的sql语句
spring.jpa.show-sql=true
# 让控制器输出的json字符串格式更美观
spring.jackson.serialization.indent-output=true

6.测试

1》服务启动后,发现新建了两张表,hibernate会为我们自动生成一个名为HIBERNATE_SEQUENCE的序列表,用来记录search_record_entity表的主键信息

2》 插入数据(sql或接口均可),为保险起见,建表语句还是尽量不自动生成,自己规范定义即可。

数据准备:

hibernate_sequence表用于记录search_record_entity表下一条数据的主键值。

3》查询接口

调用:http://localhost:8080/api/search/q1?name=全省影视

注意:这里有个小问题,SearchRecordEntity需要提供默认的无参构造方法,添加注解@NoArgsConstructor即可。

调用:​​​​​​http://localhost:8080/api/search/q2?name=全省影视&remark=备注1

调用:​​​​​​http://localhost:8080/api/search/q3?name=全省影视&remark=备注1

调用:​​​​​​http://localhost:8080/api/search/q4?name=全省影视&remark=备注1

调用:http://localhost:8080/api/search/sort

调用:http://localhost:8080/api/search/page

7.总结

springdatajpa支持查询方式有3种:

1》使用springdatajpa中规范定义的方法名查询,不需要写查询语句,即可完成查询。

规范定义的方法名,如findBy、getBy、deleteBy等开头的,如下:

2》在entity层使用@NamedQuery注解查询

3》在接口层使用@Query注解自定义查询语句

Springboot整合Spring Data JPA相关推荐

  1. 第九章SpringBoot整合Spring Data JPA

    目录 1 概述 2 Spring Data JPA整合 2.1 pom文件 2.2 配置文件 2.3 实体类 2.4 Dao接口 2.5 启动类 2.6 编写测试类 3 Spring Data JPA ...

  2. springboot整合hibernate_峰哥说技术系列-17 .Spring Boot 整合 Spring Data JPA

    今日份主题 Spring Boot 整合 Spring Data JPA JPA(Java Persistence API)是用于对象持久化的 API,是Java EE 5.0 平台标准的 ORM 规 ...

  3. spring-boot (三) spring data jpa

    学习文章来自:http://www.ityouknow.com/spring-boot.html spring data jpa介绍 首先了解JPA是什么? JPA(Java Persistence ...

  4. SpringBoot整合Spring Data Elasticsearch

    特点: 分布式,无需人工搭建集群(solr就需要人为配置,使用Zookeeper作为注册中心) Restful风格,一切API都遵循Rest原则,容易上手 近实时搜索,数据更新在Elasticsear ...

  5. springboot学习笔记(三)使用JDBC以及整合spring data jpa

    spring boot JDBC的使用: 1.引入依赖 <dependency><groupId>mysql</groupId><artifactId> ...

  6. Spring Boot整合Spring Data JPA操作数据

    一. Sping Data JPA 简介 Spring Data JPA 是 Spring 基于 ORM 框架.JPA 规范的基础上封装的一套 JPA 应用框架,底层使用了 Hibernate 的 J ...

  7. Spring Boot 应用系列 1 -- Spring Boot 2 整合Spring Data JPA和Druid,双数据源

    最近Team开始尝试使用Spring Boot + Spring Data JPA作为数据层的解决方案,在网上逛了几圈之后发现大家并不待见JPA,理由是(1)MyBatis简单直观够用,(2)以Hib ...

  8. SpringBoot集成Spring Data JPA多数据源(二)

    目录 1.引入依赖 2.application.yml配置文件 3.AtomikosJtaPlatform 4.事务管理器JPAAtomikosTransactionConfig 5.主数据源配置 6 ...

  9. Spring Boot 整合 Spring Data JPA

    JPA 是一个基于 O/R 映射的 Java 持久化规范,其定义了一系列对象持久化的标准,目前实现这一规范的产品有 Hibernate.EclipseLink.OpenJPA.TopLink 等,这也 ...

最新文章

  1. 团队作业——Alpha冲刺 6/12
  2. Spring3:AOP
  3. Know more about RAC GES STATISTICS
  4. 请给你的短信验证码接口加上SSL双向验证
  5. linux脚本编程(shell)浅介 (转载)
  6. 优酷背后的大数据秘密:资源弹性,可支撑EB级存储
  7. Springboot之actuator配置不当漏洞RCE(jolokia)
  8. MySQL----商品表及商品分类表例子
  9. 关于PPC软件的开发库
  10. xcode armv6 armv7 armv7s arm64架构分析
  11. 支持单个生成的DM码制作工具(测试)
  12. 三种获取当前时间戳的方式
  13. 我的2018OKR年终回顾与2019OKR初步规划
  14. 超级表格从四个维度为您实现精细化的表格数据共享【点击查看】
  15. 16.集合框架(ArrayList,Vector,LinkedList,泛型(Generic),可变参数,增强for循环)
  16. 基础语法(整型:uint、uint8、uint16、uint32、uint64、uintptr)
  17. 如何成为当下一个合格的算法工程师
  18. 一次性修改AD原理图中元器件PCB封装库路径
  19. 史上最全软件测试工程师常见的面试题总结(百度、oppo、中软国际、华为)
  20. ATmega 32u4 熔丝位 解析

热门文章

  1. 什么是SCRM 客户scrm管理系统 - whale 帷幄
  2. 【转】MT7688学习笔记(6)——OpenWrt下串口编程
  3. html表格制作旅游网页,简单实用的网页表格特效_html
  4. 《MATLAB 神经网络43个案例分析》:第34章 广义神经网络的聚类算法——网络入侵聚类
  5. python求三位数的最大公约数和最小公倍数(3种算法)
  6. excel表显示为数字但是却无法进行数值运算
  7. wmware16如何安装win7---超详细
  8. 微信wifi路由器怎么连接服务器,介绍下微信WIFI路由器怎么设置的方法
  9. 【转】DotNetNuke常用扩展模块
  10. Tcp/Udp端口对照表