现在版本?
本文参考了Spring Data JPA官方文档,引用了部分文档的代码
据文章编辑时,Springboot的版本已经是v2.1.7.RELEASE,Spring Data的版本已经是Lovelace-SR10
- 使用Springboot,springboot将会替你选择最新的spring data模块(Spring Boot selects a recent version of Spring Data modules for you. If you still want to upgrade to a newer version, configure the property spring-data-releasetrain.version to the train name and iteration you would like to use.)。
Spring Data Jpa 是什么?
Spring Data JPA是更大的Spring Data系列的一部分,可以轻松实现基于JPA的存储库。此模块处理对基于JPA的数据访问层的增强支持。它使构建使用数据访问技术的Spring驱动应用程序变得更加容易。在相当长的一段时间内,实现应用程序的数据访问层一直很麻烦。必须编写太多样板代码来执行简单查询以及执行分页和审计。Spring Data JPA旨在通过减少实际需要的工作量来显着改善数据访问层的实现。作为开发人员,您编写存储库接口,包括自定义查找器方法,Spring将自动提供实现。
代码层面
实体类
package me.superning.tmall.pojo;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import javax.persistence.*;
@Entity
@Table(name = "category")
//表名(严格区分大小写)
@JsonIgnoreProperties({"handler", "hibernateLazyInitializer"})
public class Category implements Serializable {
@Id
// 主键使用这个注解
@GeneratedValue(strategy = GenerationType.IDENTITY)
// 自增长策略
@Column(name = "id")
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
- 1.@Entity:标识实体类是JPA实体,告诉JPA在程序运行时生成实体类对应表
- 2.@Table:设置实体类在数据库所对应的表名
- 3.@Id:标识类里所在变量为主键
- 4.@GeneratedValue:设置主键生成策略,此方式依赖于具体的数据库
- 5.@Basic:表示简单属性到数据库表字段的映射(几乎不用)
- 6.@Column:表示属性所对应字段名进行个性化设置
- 7.@Transient:表示属性并非数据库表字段的映射,ORM框架将忽略该属性(在与密码有关的实体类会用到这个注解,后续详解于另一篇文章)
常用的注解如上,其他注解可能会以独立文章讲解。
持久层
Spring data的中央接口是Repository,
它还提供了扩展了持久层技术的接口例如
CrudRepository
MongoRepository
JpaRepository
CrudRepository和JpaRepository之间的区别
从上图你可以看出JpaRepository 继承了PagingAndSortingRepository,相应的也继承了CrudRepository
- CrudRepository 主要提供了CRUD的方法功能
- PagingAndSortingRepository,提供了分页和排序记录的方法
- JpaRepository 则拥有了它们两个所有的方法功能,并扩展了其他方法
用法
public interface OrderItemDAO
extends JpaRepository<OrderItem,Integer>
{
List<OrderItem> findByOrderOrderByIdDesc(Order order);
}
由代码可知,Dao接口首先继承一个JpaRepository接口,
JpaRepository<T, ID> T是泛型,ID是主键的类型。
接口本身已经为我们提供了基础的CRUD方法,但有时我们有
一些特殊的查询,接口无法为我们提供,这时就需要我们进行特殊参数处理。
特殊参数处理
Page<User> findByLastname(String lastname, Pageable pageable);
Slice<User> findByLastname(String lastname, Pageable pageable);
List<User> findByLastname(String lastname, Sort sort);
List<User> findByLastname(String lastname, Pageable pageable);
关于使用@Query("sql语句")在dao层的方法上写原生sql语句,
以后以独立文章介绍
关系映射
- 一对一
@OneToOne(cascade=CascadeType.ALL,optional=true)
@JoinColumn(name="addressID")//注释本表中指向另一个表的外键。
public Address getAddress() {
return address;
}
现假设有Person表和Address表,是一对一的关系,
在Person中有一个指向Address表主键的字段addressID,
所以主控方一定是Person,所谓主控方就是能改变关联关系的一方,
Person只要改变addressID就改变了关联关系,所以Person是主控方,
所以@JoinColumn写在Person类中
- 一对多单向
假如现在有Person表和Country表,那么一定是Person表中有country_id字段,由于我们是一对多的关系,所以站在一的角度,也就是Country的角度,在Country类中加入@JoinColumn
@OneToMany(cascade=CascadeType.ALL)
@JoinColumn(name="country_id")//注释的是另一个表指向本表的外键。
public List<Person> getPersons() {
return persons;
}
在一对多单向关系中,多的一方(Person)没有注解,一的一方(Country)有注解,如果一的一方不加@JoinColumn指定外键字段的话,Hibernate会自动生成一张中间表Country_PERSON来对Person和Country进行绑定。
- 多对一单向
一个产品可以属于多个分类,因此@JoinColumn放在Product类中
看看数据库
可以看到在Product表出现了一个对应Category表的外键
但是Category表中却没有外键,因此这就是单向的多对一