SpringBoot中的基于JPA标准的Hibernate的Spring-data-jpa的简单应用
JPA是什么
JPA即Java Persistence API。是为POJO(Plain Ordinary Java Object)提供持久化的标准规范。
简单来说,使用基于JPA标准实现的框架可以实现对象与数据源的绑定,并将运行期的实体对象持久化到数据库中。
为什么要使用JPA
通过面向对象而非面向数据库的查询语言查询数据,避免程序的SQL语句紧密耦合。
解放双手,不用关心如何使用SQL语句操作数据库,让程序猿更关注业务本身。
什么是spring data jpa
spirng data jpa是spring提供的一套简化JPA开发的框架,基于Hibernate实现的JPA的进一步抽象封装。
如何使用
引入依赖
1 | <dependency> |
配置文件
在application.yml文件中添加如下配置
1 | spring: |
实体类配置
数据库与实体类的映射需要在实体类添加 @Entity 注释。
如需指定映射表的名称,则需要指定 @Table(name=”user”) 否则将根据实体类名称自动创建表,如UserBean类会自动生成user_bean表作为映射。
在类的属性上需要增加相关注释进行配置,类和属性的全部注释如下
注解 | 解释 |
---|---|
@Entity | 声明类为实体或表。 |
@Table | 声明表名。 |
@Basic | 指定非约束明确的各个字段。 |
@Embedded | 指定类或它的值是一个可嵌入的类的实例的实体的属性。 |
@Id | 指定的类的属性,用于识别(一个表中的主键)。 |
@GeneratedValue | 指定如何标识属性可以被初始化,例如自动、手动、或从序列表中获得的值。 |
@Transient | 指定的属性,它是不持久的,即:该值永远不会存储在数据库中。 |
@Column | 指定持久属性栏属性。 |
@SequenceGenerator | 指定在@GeneratedValue注解中指定的属性的值。它创建了一个序列。 |
@TableGenerator | 指定在@GeneratedValue批注指定属性的值发生器。它创造了的值生成的表。 |
@AccessType | 这种类型的注释用于设置访问类型。如果设置@AccessType(FIELD),则可以直接访问变量并且不需要getter和setter,但必须为public。如果设置@AccessType(PROPERTY),通过getter和setter方法访问Entity的变量。 |
@JoinColumn | 指定一个实体组织或实体的集合。这是用在多对一和一对多关联。 |
@UniqueConstraint | 指定的字段和用于主要或辅助表的唯一约束。 |
@ColumnResult | 参考使用select子句的SQL查询中的列名。 |
@ManyToMany | 定义了连接表之间的多对多一对多的关系。 |
@ManyToOne | 定义了连接表之间的多对一的关系。 |
@OneToMany | 定义了连接表之间存在一个一对多的关系。 |
@OneToOne | 定义了连接表之间有一个一对一的关系。 |
@NamedQueries | 指定命名查询的列表。 |
@NamedQuery | 指定使用静态名称的查询。 |
1 |
|
Repository类
只需要继承JpaRepository接口即可:
1 |
|
此时UserMapper有很多增删改查的默认API可以调用了:
1 | public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> { |
但是我们需求肯定是不止这些的,所以要自定义一些API,Spring提供了一套可以通过命名规则进行查询构建的机制。
这套机制会把方法名首先过滤一些关键字,比如 find…By, read…By, query…By, count…By 和 get…By。
系统会根据关键字将命名解析成2个子语句,第一个 By 是区分这两个子语句的关键词。这个 By 之前的子语句是查询子语句(指明返回要查询的对象),后面的部分是条件子语句。
定义关键词的命名规范和例子如下:
Keyword | Sample | JPQL snippet |
---|---|---|
And | findByLastnameAndFirstname | … where x.lastname = ?1 and |
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) |
…… |
这里如果我们想通过用户名和密码进行数据查询就可以这样写 findByNameAndPassword。
所以将自定义方法写入:
1 |
|
Service类接口
我们定义两个服务接口,一个是验证用户账号密码,一个是添加一个用户:
1 | public interface UserService { |
Service类的实现
增加用户:如果成功则返回success;验证用户:查询结果直接进行返回
1 |
|
Controller层接口
Controller层正常将相关接口写出来,可以忽略@Valid BindingResult等操作
1 |
|
接口验证
增加用户:
登陆:
控制台可以看到相关数据库执行日志:
1 | Hibernate: update hibernate_sequence set next_val= ? where next_val=? |
数据库中相关数据已经添加: