【spring 官方ORM框架】spring-data-jpa详细教程


部分内容参照 spring-data-jpa V2.6.5官方文档

一、框架特性

在这里插入图片描述

  • 基于Spring和JPA强大支持构建数据库
  • 支持查询领域特定语言Querydsl(domain specification language)
  • 模型类(实体类)的透明审计
  • 分页查询、支持动态查询、整合自定义的数据访问程序
  • 启动时注解查询验证
  • 基于XML实体映射
  • 注解@EnableJpaRepositories配置数据库

二、框架实战

框架核心的类就是Repository库。看一下该类的UML图。
在这里插入图片描述
框架支持两种查询方法,其一是根据方法名派生,又叫做命名查询,无需写SQL语言;其二是使用@Query注解,又称为注解查询

2.1 命名查询

下表是命名查询支持的方法名及其对应的持久化查询语句。

命名查询支持的方法名
关键字例子JPQL (Java持久化查询语言)

Distinct

findDistinctByLastnameAndFirstname

select distinct …​ where x.lastname = ?1 and x.firstname = ?2

And

findByLastnameAndFirstname

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

Or

findByLastnameOrFirstname

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

Is, Equals

findByFirstname,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, Null

findByAge(Is)Null

… 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 (参数后追加%)

EndingWith

findByFirstnameEndingWith

… where x.firstname like ?1 (参数前追加 %)

Containing

findByFirstnameContaining

… where x.firstname like ?1 (参数封装在 %内)

OrderBy

findByAgeOrderByLastnameDesc

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

Not

findByLastnameNot

… where x.lastname <> ?1

In

findByAgeIn(Collection<Age> ages)参数支持数组和可变参数类型

… where x.age in ?1

NotIn

findByAgeNotIn(Collection<Age> ages)参数支持数组和可变参数类型

… where x.age not in ?1

True

findByActiveTrue()

… where x.active = true

False

findByActiveFalse()

… where x.active = false

IgnoreCase

findByFirstnameIgnoreCase

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

2.2 注解查询@Query

2.2.1 基本用法

?是占位符,解释后面的数字代表的参数,称为基于位置的参数。

public interface UserRepository extends JpaRepository<User, Long> {
  @Query("select u from User u where u.emailAddress = ?1")
  User findByEmailAddress(String emailAddress);
}

2.2.2 like用法

%表示like表达式的占位符。

public interface UserRepository extends JpaRepository<User, Long> {

  @Query("select u from User u where u.firstname like %?1")
  List<User> findByFirstnameEndsWith(String firstname);
}

2.2.3 命名参数

默认使用基于位置的参数,也可以使用下述命名参数。这种方式写的太复杂,没有基于位置的好用。

public interface UserRepository extends JpaRepository<User, Long> {

  @Query("select u from User u where u.firstname = :firstname or u.lastname = :lastname")
  User findByLastnameOrFirstname(@Param("lastname") String lastname,
                                 @Param("firstname") String firstname);
}

2.2.4 SpEL( Spring Expression Language)

@Query注解支持Spring表达式语言,这种方法也是太多复杂,不过我们遇到也要知道是可以这样写的。

@Entity
public class User {

  @Id
  @GeneratedValue
  Long id;

  String lastname;
}

public interface UserRepository extends JpaRepository<User,Long> {

  @Query("select u from #{#entityName} u where u.lastname = ?1")
  List<User> findByLastname(String lastname);
}

2.2.5 更新语句

JPA的更新操作很复杂,首先要开启事务,接着告诉框架是执行什么操作,最后是在@Query注解里写更新SQL。

@Transactional
@Modifying
@Query("update User u set u.firstname = ?1 where u.lastname = ?2")
int setFixedFirstnameFor(String firstname, String lastname);

当然还有另一种方法就是,首先更新模型类,再执行save操作。这个过程执行了两次数据IO,第一次是查询旧的模型类,然后对象更新,再进行保存。

2.2.6 删除语句

interface UserRepository extends Repository<User, Long> {

  void deleteByRoleId(long roleId);
  @Transactional
  @Modifying
  @Query("delete from User u where u.role.id = ?1")
  void deleteInBulkByRoleId(long roleId);
}

2.3 实体状态监测策略

  • 版本和ID属性检测

2.4 排序

public interface UserRepository extends JpaRepository<User, Long> {

  @Query("select u from User u where u.lastname like ?1%")
  List<User> findByAndSort(String lastname, Sort sort);

  @Query("select u.id, LENGTH(u.firstname) as fn_len from User u where u.lastname like ?1%")
  List<Object[]> findByAsArrayAndSort(String lastname, Sort sort);
}

repo.findByAndSort("lannister", Sort.by("firstname"));                
repo.findByAndSort("stark", Sort.by("LENGTH(firstname)"));            
repo.findByAndSort("targaryen", JpaSort.unsafe("LENGTH(firstname)")); 
repo.findByAsArrayAndSort("bolton", Sort.by("fn_len"));      

2.2 表关系

2.2.1 如何设计库表

确定表与表之间的关联关系,一对一、一对多、多对多。

关系使用频次例子备注建表原则
一对一较少学生表可以制作成一张表,特殊的一对多关系,太复杂时,采用分表策略主表的主键和从表的外键(唯一),形成主外键关系,外键唯一unique;主表的主键和从表的主键,形成主外键关系
一对多非常多院系和学生,部门和员工,客户和订单,分类和商品从表中建外键与主表进行关联在从表(多方)创建一个字段,字段作为外键指向主表(一方)的主键
多对多较多学生表和课表,老师和学生表,用户和角色表创建中间关系表创建第三张表,中间表中至少两个字段,这两个字段分别作为外键指向各自一方的主键

设计数据库表时,不要想太复杂,就根据这三种关系进行字段的设计。
在这里插入图片描述

2.2.2 JPA关系表操作步骤

使用注解标注列完成表关系的建立。
@OneToOne
@OneToMany
@ManyToMany

番外篇

FW1 Querydsl是啥

Querydsl是一个Java开源框架,它支持构造静态类型的类似sql的查询。不需要将查询写成内联字符串或外部化到XML文件中。目前 Querydsl 支持的平台包括 JPA,JDO,SQL,Java Collections,RDF,Lucene,Hibernate Search。

与简单的字符串相比,使用流畅的API的好处是:

  • IDE中的代码完成
  • 几乎不允许语法上无效的查询
  • 可以安全地引用域类型和属性
  • 更好地对域类型的更改进行重构
  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

追寻上飞

鼓励一下这只勤劳的小蜜蜂吧

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值