Fork me on Gitee

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 创建实体类

  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<操作的实体类类型>,封装了复杂查询(分页)
  1. 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)

image-20221117115758240

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类

image-20221216214306631

创建查询接口集成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));
    }
posted @ 2022-11-15 17:56  shine-rainbow  阅读(188)  评论(0编辑  收藏  举报