Spring Data JPA基本使用

JPA简介

JPA 即Java Persistence API。是一款持久层框架,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。JPA的对象关系映射(ORM)模型是基于Hibernate。是一款面向对象的ORM框架,JPA不需要关心数据库字段,通过注解将数据库表与实体完成映射,在java中的操作只需要对实体进行操作即可。

ORM简介

ORM(Object-Relational Mapping) 表示对象关系映射。在面向对象的软件开发中,通过ORM,就可以把对象映射到关系型数据库中。只要有一套程序能够做到建立对象与数据库的关联,操作对象就可以直接操作数据库数据,就可以说这套程序实现了ORM对象关系映射。也就是说ORM是建立了一个实体与数据库表的关系,使得开发者对实体的直接操作而不是对数据库的操作,但操作实体也就等同于操作了数据库。 ORM框架还有:MyBatis、Hibernate。

Spring Data JPA

Spring Data JPA 是 Spring 基于 ORM 框架、JPA 规范的基础上封装的一套JPA应用框架,可使开发者用极简的代码即可实现对数据库的访问和操作。 它提供了包括增删改查等在内的常用功能,且易于扩展!学习并使用 Spring Data JPA 可以极大提高开发效率! Spring Data JPA 让我们解脱了DAO层的操作,基本上所有CRUD都可以依赖于它来实现 在实际的工作工程中,推荐使用Spring Data JPA + ORM(如:hibernate)完成操作,这样在切换不同的ORM框架时提供了极大的方便,同时也使数据库层操作更加简单,方便解耦。

SpringBoot整合JPA

1、导入依赖

 <dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
        <version>2.3.0.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <version>2.3.0.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.20</version>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.12</version>
    </dependency>
</dependencies>

Spring Data JPA默认使用的ORM框架是Hibernate。

2、配置文件

spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT
    username: root
    password: 123456
    type: com.mysql.cj.jdbc.MysqlDataSource
  jpa:
    show-sql: true
    generate-ddl: true

3、创建Entity

@MappedSuperclass
public class BaseEntity {

    @Column(name = "is_del")
    private Integer isDel;

    @CreatedDate
    @Column(name = "created_at", updatable = false)
    private Date createdAt;

    @LastModifiedDate
    @Column(name = "modified_at")
    private Date modifiedAt;
}
@Table(name = "sys_user")
@Data
@Entity
@Builder
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class SysUser extends BaseEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name ="user_id")
    private Long userId;
    
    @Column(name = "userName", nullable = false,length = 255)
    private String userName;

    @Column(name = "password")
    private String password;

    @Column(name = "email")
    private String email;
}

3.1、JPA Entity常用注解

注解 解释
@Table 声明数据库中的表都名字实现实体与数据表映射
@Entity 声明一个类是实体类
@Id 声明主键
@GeneratedValue 设置自动生成策略
@Column 指定持久属性或字段的映射列
@MappedSuperclass 用于抽离出通用属性,并使用MappedSuperclass注解修饰。子类也可继承这些属性

注意:
1.标注为@MappedSuperclass的类将不是一个完整的实体类,他将不会映射到数据库表,但是他的属性都将映射到其子类的数据库字段中。
2.标注为@MappedSuperclass的类不能再标注@Entity或@Table注解,也无需实现序列化接口。

4、创建Repository

@Repository
public interface SysUserJpaRepo extends JpaRepository<User,Long>, JpaSpecificationExecutor<User> {
    
}

4.1、JPA Repository注解

注解 解释
@Repository 声明接口为Repository
@NoRepositoryBean 声明以排除存储库接口,从而避免创建实例。

4.2、JPA Repository接口

image.png

接口 作用
Repository Repository接口
CrudRepository 提供CRUD
PagingAndSortingRepository 提供分页和排序的方式查询
JpaRepository 继承PagingAndSortingRepository、QueryByExampleExecutor
JpaRepositoryImplementation 继承JpaSpecificationExecutor、JpaRepository
JpaSpecificationExecutor 提供通过Specification实例的方式查询
QueryByExampleExecutor 提供通过Example实例的方式查询

5、创建启动类,

@SpringBootApplication
@EnableJpaRepositories(basePackages = "me.demo.repo")
public class JpaApplication {
    public static void main(String[] args) {
        SpringApplication.run(JpaApplication.class);
    }
}

启动后,如果数据库未创建表结构,则自动创建。

6、查询

Spring Data JPA中可以在接⼝中⾃定义⽅法上⾯使⽤ @Query 注解,在该注解中可以使⽤JPQL或SQL来 指定此⽅法被调⽤的时候需要执⾏的sql语⾔是什么。

JPQL(JavaPersistence Query Language)是⼀种⾯向对象的查询语⾔,它在ORM框架中最终会 翻译成为sql进⾏执⾏。在hibernate框架中,这种语句叫做HQL(Hibernate Query Language)。

JPQL是⾯向对象的查询语⾔,在查询语句中,出现的不是表的名字、字段的名字,⽽是类的名字和类中 属性的名字,因为在ORM框架中,类和表,属性和字段都做好了映射关系,所以JPQL最后是可以根据映 射关系转换sql语句的。
JPQL的特点:

  • 语句中不能出现表名,列名,只能出现java的类名,属性名,并且区分⼤⼩写
  • 语句中出现的关键字和sql语句中的是⼀样的意思,不区分⼤⼩写
  • 语句中不能写select * ⽽是要写select 类的别名,或者写select 具体的属性名
@Query("select u from User u where u.name = ?1")
User findByUserName(String name);

该语句中的 ?1 代表第⼀个参数,?2 代表第⼆个参数,不是从0开始

也可以配合 @Param 注解使⽤命名参数(Named Parameters)的⽅式:

@Query("select u from User u where u.firstname = :firstname or u.lastname = :lastname")
User findByLastnameOrFirstname(@Param("lastname") String lastname, @Param("firstname") String firstname);

@Query 注解除了⽀持JPQL之外,还可以⽀持原⽣sql语句的编写:

6.1、解析方法名查询

默认的JPA支持解析方法名,创建SQL语句。
如果启动类设置@EnableJpaRepositories(basePackages = "me.demo.repo",queryLookupStrategy = QueryLookupStrategy.Key.USE_DECLARED_QUERY),那么将不支持此方式。

@Repository
public interface SysUserJpaRepo extends JpaRepository<SysUser,Long>, JpaSpecificationExecutor<SysUser> {
    SysUser findByUserName(String userName);
    SysUser findByUserNameAndEmail(String userName, String email);
    SysUser findByUserNameLike(String userName);
}

6.2、分页查询

JPA实现分页在方法中加入Pageable参数

@Repository
public interface SysUserJpaRepo extends JpaRepository<SysUser,Long>, JpaSpecificationExecutor<SysUser> {
    Page<SysUser> findByUserNameLike(String userName, Pageable pageable);
}

6.3、Native SQL查询

@Repository
public interface SysUserJpaRepo extends JpaRepository<SysUser,Long>, JpaSpecificationExecutor<SysUser> {
    
    @Query(value = "select * from sys_user where user_name= :username", nativeQuery = true)
    Page<SysUser> findUserByName(@Param("username") String userName, Pageable pageable);
}

6.4、HQL

@Repository
public interface SysUserJpaRepo extends JpaRepository<SysUser,Long>, JpaSpecificationExecutor<SysUser> {
    @Query(value = "select u from SysUser u where  u.userName like :username")
    Page<SysUser> findUser(@Param("username") String userName, Pageable pageable);
}

6.5、返回自定义对象

@Data
@Builder
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class SysUserBo {
    private Long userId;

    private String userName;

    private String password;

    private String email;
}
@Repository
public interface SysUserJpaRepo extends JpaRepository<SysUser,Long>, JpaSpecificationExecutor<SysUser> {
     //需要全部参数的构造器
    @Query(value = "select new me.zk.bo.SysUserBo(u.userId,u.userName,u.password,u.email) " +
            "from SysUser u where u.userName= :username")
    Page<SysUserBo> findByName(@Param("username") String userName, Pageable pageable);
}

6.6、Example查询

UserJpaRepo继承JpaRepository,拥有QueryByExampleExecutor的能力

@SpringBootTest(classes = JpaApplication.class)
public class JpaTest {
    @Autowired
    private SysUserJpaRepo sysUserJpaRepo;
 	@Test
    public void testExample() {
        SysUser sysUser = new SysUser();
        sysUser.setUserName("zk,zjw");
        Example<SysUser> example = Example.of(sysUser);
        Page<SysUser> all = sysUserJpaRepo.findAll(example, Pageable.unpaged());
        System.out.println("find:" + all.getContent());
    }

    @Test
    public void testExampleMatcher() {
        SysUser sysUser = new SysUser();
        sysUser.setUserName("zk,zjw");
        ExampleMatcher matcher = ExampleMatcher.matching().withIgnoreNullValues();
        Example<SysUser> example = Example.of(sysUser,matcher);
        Page<SysUser> all = sysUserJpaRepo.findAll(example, Pageable.unpaged());
        System.out.println("find:" + all.getContent());
    }

}

6.7、动态查询(自定义where条件)

@SpringBootTest(classes = JpaApplication.class)
public class JpaTest {
    @Autowired
    private SysUserJpaRepo sysUserJpaRepo;
 	 //动态条件查询
    @Test
    public void testDynamicSearch() {
        Specification<SysUser> specification = new Specification<SysUser>() {
            @Override
            public Predicate toPredicate(Root<SysUser> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                List<Predicate> list = new ArrayList<>();
                list.add(criteriaBuilder.like(root.get("userName"),"z%"));
                return query.where(list.toArray(new Predicate[list.size()])).getRestriction();
            }
        };
        Page<SysUser> all = sysUserJpaRepo.findAll(specification, Pageable.unpaged());
        System.out.println(all.getContent());
    }

}

6.8、返回Object,自定义转换

@Repository
public interface SysUserJpaRepo extends JpaRepository<SysUser,Long>, JpaSpecificationExecutor<SysUser> {
    @Query(value = "select user_id,user_name,email from sys_user where user_name= :username", nativeQuery = true)
    List<Map<String,Object>> queryUserByName(@Param("username") String userName);
}

7、自定义删除操作

7.1 Native SQL

@Repository
public interface SysUserJpaRepo extends JpaRepository<SysUser,Long>, JpaSpecificationExecutor<SysUser> {
	@Query(nativeQuery = true, value = "delete from sys_user where user_name = :username ")
    @Modifying
    @Transactional
    int deleteByName(@Param("username") String userName);
}

7.2 HQL

@Repository
public interface SysUserJpaRepo extends JpaRepository<SysUser,Long>, JpaSpecificationExecutor<SysUser> {
	@Query(value = "delete from SysUser s where s.userId = ?1 ")
    @Modifying
    @Transactional
    int deleteByUserId(Long userId);
}

8、参考

官网
自动化SQL编写Springboot整合Springdata-jpa—让编程更简单

posted @ 2022-11-28 19:12  往事随雨  阅读(164)  评论(0编辑  收藏  举报