当前位置 : 主页 > 编程语言 > java >

SpringBoot中JPA的基本使用

来源:互联网 收集:自由互联 发布时间:2023-02-04
1、Jpa 是什么 JPA顾名思义就是Java Persistence API的意思,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。 2、优势 2.1标准化 JPA 是 JCP 组织发布的

1、Jpa 是什么

JPA顾名思义就是Java Persistence API的意思,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。

SpringBoot中JPA的基本使用_spring

2、优势

2.1标准化

JPA 是 JCP 组织发布的 Java EE 标准之一,因此任何声称符合 JPA 标准的框架都遵循同样的架构,提供相同的访问API,这保证了基于JPA开发的企业应用能够经过少量的修改就能够在不同的JPA框架下运行。

2.2容器级特性的支持

JPA框架中支持大数据集、事务、并发等容器级事务,这使得 JPA 超越了简单持久化框架的局限,在企业应用发挥更大的作用。

2.3简单方便

JPA的主要目标之一就是提供更加简单的编程模型:在JPA框架下创建实体和创建Java 类一样简单,没有任何的约束和限制,只需要使用 javax.persistence.Entity进行注释,JPA的框架和接口也都非常简单,没有太多特别的规则和设计模式的要求,开发者可以很容易的掌握。JPA基于非侵入式原则设计,因此可以很容易的和其它框架或者容器集成。

2.4查询能力

JPA的查询语言是面向对象而非面向数据库的,它以面向对象的自然语法构造查询语句,可以看成是Hibernate HQL的等价物。JPA定义了独特的JPQL(Java Persistence Query Language),JPQL是EJB QL的一种扩展,它是针对实体的一种查询语言,操作对象是实体,而不是关系数据库的表,而且能够支持批量更新和修改、JOIN、GROUP BY、HAVING 等通常只有 SQL 才能够提供的高级查询特性,甚至还能够支持子查询。

2.4高级特性

JPA 中能够支持面向对象的高级特性,如类之间的继承、多态和类之间的复杂关系,这样的支持能够让开发者最大限度的使用面向对象的模型设计企业应用,而不需要自行处理这些特性在关系数据库的持久化。

Spring Boot Jpa 让我们解脱了 DAO 层的操作,基本上所有 CRUD 都可以依赖于它来实现

3、代码实现

添加依赖及配置

pom.xml

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency>

application.properties

spring.datasource.url=jdbc:mysql://localhost:3306/test?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=truespring.datasource.username=rootspring.datasource.password=rootspring.datasource.driver-class-name=com.mysql.cj.jdbc.Driverspring.jpa.properties.hibernate.hbm2ddl.auto=createspring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect#sql\u8F93\u51FAspring.jpa.show-sql=true#format\u4E00\u4E0Bsql\u8FDB\u884C\u8F93\u51FAspring.jpa.properties.hibernate.format_sql=true

一.基本查询

基本查询也分为两种:

一种是 Spring Data 默认已经实现,

一种是根据查询的方法来自动解析成 SQL。

预先生成方法

Spring Boot Jpa 默认预先生成了一些基本的CURD的方法,例如:增、删、改等等

1 继承 JpaRepository

public interface UserRepository extends JpaRepository<User, Long> {}

2 使用默认方法

@Testpublic void testBaseQuery() throws Exception { User user=new User(); userRepository.findAll(); userRepository.findOne(1l); userRepository.save(user); userRepository.delete(user); userRepository.count(); userRepository.exists(1l); // ...}

自定义简单查询

自定义的简单查询就是根据方法名来自动生成 SQL,

主要的语法是​​findXXBy​​,​​readAXXBy​​,​​queryXXBy​​,​​countXXBy​​, ​​getXXBy​​后面跟属性名称:

User findByUserName(String userName);

也使用一些加一些关键字​​And​​、 ​​Or​​

User findByUserNameOrEmail(String username, String email);

修改、删除、统计也是类似语法

Long deleteById(Long id);Long countByUserName(String userName)

基本上 SQL 体系中的关键词都可以使用,例如:​​LIKE​​、 ​​IgnoreCase​​、 ​​OrderBy​​。

List<User> findByEmailLike(String email);User findByUserNameIgnoreCase(String userName);List<User> findByUserNameOrderByEmailDesc(String email);

具体的关键字,使用方法和生产成SQL如下表所示

Keyword

Sample

JPQL snippet

And

findByLastnameAndFirstname

… where x.lastname = ?1 and x.firstname = ?2

Or

findByLastnameOrFirstname

… where x.lastname = ?1 or x.firstname = ?2

Is,Equals

findByFirstnameIs,findByFirstnameEquals

… where x.firstname = ?1

Between

findByStartDateBetween

… where x.startDate between ?1 and ?2

LessThan

findByAgeLessThan

… where x.age < ?1

LessThanEqual

findByAgeLessThanEqual

… where x.age ⇐ ?1

GreaterThan

findByAgeGreaterThan

… where x.age > ?1

GreaterThanEqual

findByAgeGreaterThanEqual

… where x.age >= ?1

After

findByStartDateAfter

… where x.startDate > ?1

Before

findByStartDateBefore

… where x.startDate < ?1

IsNull

findByAgeIsNull

… where x.age is null

IsNotNull,NotNull

findByAge(Is)NotNull

… where x.age not null

Like

findByFirstnameLike

… where x.firstname like ?1

NotLike

findByFirstnameNotLike

… where x.firstname not like ?1

StartingWith

findByFirstnameStartingWith

… where x.firstname like ?1 (parameter bound with appended %)

EndingWith

findByFirstnameEndingWith

… where x.firstname like ?1 (parameter bound with prepended %)

Containing

findByFirstnameContaining

… where x.firstname like ?1 (parameter bound wrapped in %)

OrderBy

findByAgeOrderByLastnameDesc

… where x.age = ?1 order by x.lastname desc

Not

findByLastnameNot

… where x.lastname <> ?1

In

findByAgeIn(Collection ages)

… where x.age in ?1

NotIn

findByAgeNotIn(Collection age)

… where x.age not in ?1

TRUE

findByActiveTrue()

… where x.active = true

FALSE

findByActiveFalse()

… where x.active = false

IgnoreCase

findByFirstnameIgnoreCase

… where UPPER(x.firstame) = UPPER(?1)

二.复杂查询

在实际的开发中我们需要用到分页、删选、连表等查询的时候就需要特殊的方法或者自定义 SQL

分页查询

分页查询在实际使用中非常普遍了,Spring Boot Jpa 已经帮我们实现了分页的功能,在查询的方法中,需要传入参数​​Pageable​​ ,当查询中有多个参数的时候​​Pageable​​建议做为最后一个参数传入.

Page<User> findALL(Pageable pageable);Page<User> findByUserName(String userName,Pageable pageable);

​​Pageable​​ 是 Spring 封装的分页实现类,使用的时候需要传入页数、每页条数和排序规则

@Testpublic void testPageQuery() throws Exception { int page=1,size=10; Sort sort = new Sort(Direction.DESC, "id"); Pageable pageable = new PageRequest(page, size, sort); userRepository.findALL(pageable); userRepository.findByUserName("testName", pageable);}

限制查询

有时候我们只需要查询前N个元素,或者只取前一个实体。

User findFirstByOrderByLastnameAsc();User findTopByOrderByAgeDesc();Page<User> queryFirst10ByLastname(String lastname, Pageable pageable);List<User> findFirst10ByLastname(String lastname, Sort sort);List<User> findTop10ByLastname(String lastname, Pageable pageable);

自定义SQL查询

其实 Spring Data 觉大部分的 SQL 都可以根据方法名定义的方式来实现,但是由于某些原因我们想使用自定义的 SQL 来查询,

Spring Data 也是完美支持的;

在 SQL 的查询方法上面使用 ​​@Query​​注解,如涉及到删除和修改在需要加上 ​​@Modifying​​.也可以根据需要添加 ​​@Transactional​​对事物的支持,查询超时的设置等。

@Modifying@Query("update User u set u.userName = ?1 where u.id = ?2")int modifyByIdAndUserId(String userName, Long id);@Transactional@Modifying@Query("delete from User where id = ?1")void deleteByUserId(Long id);@Transactional(timeout = 10)@Query("select u from User u where u.emailAddress = ?1")User findByEmailAddress(String emailAddress);

多表查询

多表查询 Spring Boot Jpa 中有两种实现方式,第一种是利用 Hibernate 的级联查询来实现,第二种是创建一个结果集的接口来接收连表查询后的结果,这里主要第二种方式。

首先需要定义一个结果集的接口类。

public interface HotelSummary { City getCity(); String getName(); Double getAverageRating(); default Integer getAverageRatingRounded() { return getAverageRating() == null ? null : (int) Math.round(getAverageRating()); }}

查询的方法返回类型设置为新创建的接口

@Query("select h.city as city, h.name as name, avg(r.rating) as averageRating " + "from Hotel h left outer join h.reviews r where h.city = ?1 group by h")Page<HotelSummary> findByCity(City city, Pageable pageable);@Query("select h.name as name, avg(r.rating) as averageRating " + "from Hotel h left outer join h.reviews r group by h")Page<HotelSummary> findByCity(Pageable pageable);

使用

Page<HotelSummary> hotels = this.hotelRepository.findByCity(new PageRequest(0, 10, Direction.ASC, "name"));for(HotelSummary summay:hotels){ System.out.println("Name" +summay.getName()); }

在运行中 Spring 会给接口(HotelSummary)自动生产一个代理类来接收返回的结果,代码汇总使用 ​​getXX​​的形式来获取

网友评论