Spring与JPA
Spring Data是一个非常大的伞形项目,由多个子项目组成,其中大多数子项目都关注对不同的数据库类型进行数据持久化。比较流行的几个Spring Data项目包括:
- Spring Data JPA:基于关系型数据库进行JPA持久化。 Spring Data MongoDB:持久化到Mongo文档数据库。
- Spring Data Neo4j:持久化到Neo4j图数据库。 Spring Data Redis:持久化到Redis
- key-value存储。 Spring Data Cassandra:持久化到Cassandra数据库。 Spring
- Data为所有项目提供了一项最有趣且最有用的特性,就是基于repository规范接口自动生成repository的功能。
Sping Boot中使用JPA
在Spring Boot中使用JPA只需要引入相关的starter
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
配置文件中增加相关的配置
spring:
jpa:
show-sql: true
hibernate:
ddl-auto: update
将领域对象标注为实体
这里以用户与角色的多对多关系为例
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Data
@Entity
@Table(name = "sys_user")
public class SysUser{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "user_id")
private long userId;
@Column(name = "user_name")
private String userName;
@Column(name = "gender")
private String gender;
@Column(name = "account",unique = true,nullable = false)
private String account;
@Column(name = "password",nullable = false)
private String password;
@Column(name = "city")
private String city;
@Column(name = "created_by")
private String createdBy;
@Column(name = "created_time")
private Date createdTime;
@Column(name = "updated_by")
private String updatedBy;
@Column(name = "updated_time")
private Date updatedTime;
@JsonIgnoreProperties("users")
@ManyToMany(targetEntity = SysRole.class)
@JoinTable(name = "sys_user_role",
joinColumns = @JoinColumn(name = "user_id",referencedColumnName = "user_id"),
inverseJoinColumns = @JoinColumn(name = "role_id",referencedColumnName = "role_id"))
private List<SysRole> roles;
@PrePersist
void createdTime(){
this.createdTime = new Date();
}
}
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Data
@Entity
@Table(name = "sys_role")
public class SysRole{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "role_id")
private long roleId;
@Column(name = "role_name",nullable = false,unique = true)
private String roleName;
@Column(name = "created_by")
private String createdBy;
@Column(name = "created_time")
private Date createdTime;
@Column(name = "updated_by")
private String updatedBy;
@Column(name = "updated_time")
private Date updatedTime;
@JsonIgnoreProperties("roles")
//mappedBy 放弃维护多对多关系
@ManyToMany(targetEntity = SysUser.class,mappedBy = "roles")
private List<SysUser> users;
@PrePersist
void createdTime(){
this.createdTime = new Date();
}
}
@Entity注解
将领域类声明为JPA实体。
@Id注解
领域类中标注@Id注解的属性对应数据库表中的主键字段。
@GeneratedValue(strategy = GenerationType.AUTO)
依赖数据库自动生成ID值。
@ManyToMany
user可以有多个role,而每个role可以被多个用户使用。
@PrePersist
对象持久化之前调用此方法,为对象中的属性赋值。一个领域类中只能有一个此注解。
@Table
对应数据库中表的名字。
@JoinTable
如果不想使用JPA自动生成的中间表,可以使用此注解自定义中间表的名字及相关字段的映射关系。
@JsonIgnoreProperties
解决双向关联时,生成JSON数据进入死循环的问题。
在SysUser中private List roles;字段上配置@JsonIgnoreProperties(“users”)代表的意思是:忽略roles中每个Role对象中的User对象,并不忽略User类中的roles属性。
声明Repository并继承JPA提供的Repository
public interface UserRepository extends CrudRepository<SysUser,Long> {
SysUser findByAccount(String account);
@Query(value = "SELECT a.account,a.user_name as userName FROM sys_user a,sys_role b,sys_user_role c " +
"WHERE a.user_id = c.user_id " +
"AND b.role_id = c.role_id " +
"AND b.role_name = :roleName",nativeQuery = true)
List<Map<String,Object>> findSysUserByRoleName(@Param("roleName") String roleName);
}
CrudRepository定义了很多用于CRUD(创建、读取、更新、删除)操作的方法。注意,它是参数化的,第一个参数是repository要持久化的实体类型,第二个参数是实体ID属性的类型。
不用编写实现类,当应用启动的时候,Spring Data JPA会在运行期自动生成实现类。
当创建repository实现的时候,Spring Data会检查repository接口的所有方法,解析方法的名称,并基于被持久化的对象来试图推测方法的目的。本质上,Spring Data定义了一组小型的领域特定语言(Domain-Specific Language,DSL),在这里持久化的细节都是通过repository方法的签名来描述的。
repository方法是由一个动词、一个可选的主题(Subject)、关键词By以及一个断言所组成的。详细的介绍可以查阅官方文档。
Spring Data会将get、read和find视为同义词,它们都是用来获取一个或多个实体的。另外,我们还可以使用count作为动词,它会返回一个int值,代表匹配实体的数量。
通过使用@Query,可以自己编写SQL。