Spring Data JPA
一、简介
1.1 何为JPA
JPA是 Java Persistene API简介、中文名Java持久层API,是由Sun官网提出来的Java持久层框架。设计的目的是为了简化现有的持久化开发工作和整合ORM技术
JAP使用xml文件或注解(JDK 5.0或更高版本)来描述对象-关系表的映射关系,能够将运行期的实体对象持久化到数据库,它为Java开发人员提供了一种ORM工具来管理Java应用中的关系数据。
由于JPA充分吸收了现有Hibernate、TopLink、JDO等ORM框架的基础上发展而来,因而具备易于使用、伸缩性强等优点。
Spring Data JPA是Spring基于Spring Data框架,在JPA规范的基础上开发而来的框架,使得Spring Data JPA可以极大地简化JPA的写法,可以在几乎不写实现的情况下实现对数据库的访问和操作,除了CRUD外,还包括分页和排序等一些常见的功能。
1.2 JPA与MyBatis对比
jpa是对象与对象之间
的映射,而Mybatis是对象和结果集之间
的映射。
jpa移植性比较好,不用关注操作什么数据库。
MyBatis自由写sql语句,当项目移植的时候还需要改sql。修改字段时JPA更简单,MyBatis需要修改一堆xml、mapper,JPA只适合简单的单标sql。
MyBatis和JPA各有优势,如果SQL简单,则JPA使用效率更高,如果SQL较复杂,需要自定义,则使用MyBatis更顺手。
二、项目初上手
<!--jpa-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependency>
appplication.yml中的配置
spring:
data:
jpa:
repositories:
# 开启jpa
enabled: true
bootstrap-mode: default
jpa:
# 数据库方言
database-platform: org.hibernate.dialect.MySQL57Dialect
open-in-view: false
# 打印SQL
show-sql: true
properties:
# 格式化输出的SQL语句
hibernate.format_sql: true
hibernate:
# 自动建表策略
ddl-auto: update
datasource:
url: jdbc:mysql://127.0.0.1/favorites?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.zaxxer.hikari.HikariDataSource
创建启动类 FavoriteApplication.java启动类,入口类需要添加@EnableJpaRepositories注解。
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
/**
* @date 2022/11/8 20:26
*/
@SpringBootApplication
@EnableJpaRepositories(basePackages = {"com.hbis.favorite.repository"})
public class FavoriteApplication {
public static void main(String[] args) {
SpringApplication.run(FavoriteApplication.class,args);
}
}
在@EnableJpaRepositories
中指定repository包路径
2.1 创建实体类
- User对象实体类
@Entity
@Data
@EntityListeners(AuditingEntityListener.class)
@DynamicUpdate
@Table(name = "user")
public class User implements Serializable {
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false,unique = true,length = 20) // 列字段, 非空且唯一,字符最大长度20
private String username;
@Column(nullable = false,length = 20)
private String password;
@Column(insertable = false,columnDefinition = "timestamp not null default current_timestamp")
@CreatedDate
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
@Column(insertable = false,columnDefinition = "timestamp not null default current_timestamp ON UPDATE current_timestamp")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@LastModifiedDate
private Date updateTime;
}
常见的表中注解
注解 | 作用 |
---|---|
@Entity | 指定当前类是一个实体类,对应于数据库中的一张表 |
@Table | 指定表明, 当实体类与其映射的数据库表名不同名时,需要指定@Table进行注解说明,若同名可以省略 |
@Id | 指定当前字段是主键 |
@GeneratedValue | 指定主键的生成策略。属性:strategy指定主键生成策略。 |
@Column | 指定实体类属性和数据库表的列属性对应关系,常见属性有 |
@Basic | 为隐藏字段,一般不加。@Entity会默认添加上@Basic,并使用默认值 |
@Transient | 如果希望该字段并不在数据库中生成,添加@Transient |
对于GeneatedValue的参数选项。
- GeneationType.IDENTITY:自增,底层数据库必须支持自增(mysql)
- GenerationType.SEQUENCE:序列,底层数据库必须支持序列(oracle)
- Generationtype.TABLE:JPA提供的一种策略,同生成一张表的方式完成主键自增,这张表存储了下一次添加的主键的值。
- GenerationType.AUTO:由程序自动选择的一种策略(默认)
对于Column常见的参数选项
- name: 指定数据库表的列名称,默认列名为属性名
- unique: 是否唯一
- nullable: 是否可以为空
- length:对于字符型列,length属性指定列的最大字符长度
对于日期类型,创建和更新动作由数据库自行更新,因此insertable字段设置为false。同时,如果更新时间失败,
2.2 创建Repository
- JpaRepository<操作的实体类类型,实体类中主键属性的类型>,封装了基本的CRUD操作
- JpaSpecificationExecutor<操作的实体类类型>,封装了复杂查询(分页)
- UserRepository
public interface UserRepository extends JpaRepository<User,Long> {
@Query(value = "select * from user where username=?1",nativeQuery = true)
User findUserByUsername(String username);
@Transactional
@Query(value = "update user u set u.username=:username where u.id=:id",nativeQuery = true)
int updateUserNameById(@Param("username") String username, @Param("id") Long id);
}
其中UserRepository要继承JpaRepository,其中User表示实体模型,Long代表主键类型。
对于更新方法,使用JPQL语句具名参数方式,编写Query语句。
使用JPQL方式操作数据
2.3 插入数据
@Test
public void testSave(){
User user = new User();
user.setUsername("shine123789");
user.setPassword("123456");
User resUser = userRepository.save(user);
log.info("resUser {}",resUser);
}
2.4 更新数据
@Test
public void testUpdate(){
int result= userRepository.updateUserNameById("shine456",1L);
log.info("update result:{}",result);
}
2.5 查询数据
@Test
public void testFindAll(){
List<User> userList = userRepository.findAll();
log.info("userList :{}",userList);
}
@Test
public void testFindUsername(){
User user = userRepository.findUserByUsername("shine123789");
log.info("user= {}",user);
}
2.6 删除数据
@Test
public void testDelete(){
userRepository.deleteById(1L);
}
三、规定方法名
先下载插件 JPA Buddy,在编写Repository时会有方法名称提示。详细使用方式见(https://blog.csdn.net/allway2/article/details/127899659)
3.1查询数据
/**
* 根据规定方法名进行查询
* @param username 用户名
*/
List<User> findByUsername(String username);
3.2 删除数据
/**
* 根据原生方法
* @param id 自增id
* @return
*/
Integer removeById(Long id);
四、QueryDSL
QueryDSL是基于ORM框架或SQL平台上的一个通用查询框架。借助QueryDSL可以在任何支持的ORM框架或者SQL平台上以通用API方式构建查询。JPA是QUeryDSL的主要集成技术,是JPQL和Criteria查询的代替方法。目前QueryDSL支持的平台包括JPA、JDO、SQL和MongoDB等。
QueryDSL扩展能让我们以链式方式代码编写查询方法。该扩展需要一个接口QueryDslPredicteExecutor,它定义了很多查询方法。
step1: 引入依赖
<!--querydsl-->
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
<scope>provided</scope>
</dependency>
step2:引入插件,用于生成查询实例
<!--该插件可以生成querysdl需要的查询对象,执行mvn compile即可-->
<plugin>
<groupId>com.mysema.maven</groupId>
<artifactId>apt-maven-plugin</artifactId>
<version>1.1.3</version>
<executions>
<execution>
<goals>
<goal>process</goal>
</goals>
<configuration>
<outputDirectory>target/generated-sources/java</outputDirectory>
<processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>
</configuration>
</execution>
</executions>
</plugin>
执行mvn complile
之后,可以在target/generated-sources/java
中找到Q类
创建查询接口集成QueryDslPredicteExecutor,实例代码如下
public interface UserQueryDSLRepository extends PagingAndSortingRepository<User,Long>, QuerydslPredicateExecutor<User> {
}
4.1 QSDL示例
@Test
public void testFindOneById(){
QUser user = QUser.user;
//查询并返回结果集
BooleanExpression eq = user.id.eq(1L);
System.out.println(repository.findOne(eq));
}
@Test
public void testIn(){
QUser user = QUser.user;
BooleanExpression eq = user.id.in(1L, 5L).and(user.username.in("王五"));
System.out.println(repository.findAll(eq));
}