SpringBoot(三):整合JPA

郎家岭伯爵 2023年07月12日 362次浏览

前言

SpringBoot 整合 JPA

实现

理论

Spring Data 是 Spring 提供的一个操作数据的框架,Spring Data JPASpring Data 下的一个基于 JPA 标准的操作数据的模块。

JPA(Java Persistence API) 是 Java 母公司 Sun 公司提出的一套 Java 持久化规范。所谓规范,就是只定义标准,不提供实现

JPA 的提出主要是为了整合市面上已有的 ORM 框架,比如说 Hibernate、EclipseLink 等。官方觉得你们搞框架可以,但不要乱搞,得按照标准来。

Spring Data JPA 只是一个抽象层,它上接 JPA 下接 ORM 框架,通过基于 JPA 的 Respository 接口极大地减少了 JPA 作为数据访问方案的代码量,简化了持久层开发并且屏蔽了各大 ORM 框架的差异。

总结一下就是:

  • JPA 是规范,统一了规范才便于使用。
  • Hibernate 是 JPA 的实现,是一套成熟的 ORM 框架。
  • Spring Data JPA 是 Spring 提出的,它增加了一个抽象层,用来屏蔽不同 ORM 框架的差异。

SpringBoot

新建一个 SpringBoot 项目。

pom.xml

pom.xml 文件中导入以下依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.11</version>
</dependency>

application.properties

application.properties 中添加如下配置项:

spring.datasource.username=root
spring.datasource.password=
spring.datasource.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&useSSL=false

# 开启JPA的SQL输出
spring.jpa.show-sql=true

User实体类

创建 User 实体类。

package com.langjialing.jpademo.entity;

import lombok.Data;

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

/**
 * @author 郎家岭伯爵
 * @time 2023/7/12 10:56
 */
@Data
@Entity
@Table(name = "user")
public class User {
    @Id
    private Integer userId;
    private Integer age;
    private String userName;
    private String password;
}
  • @Data 注解为 lombok 注解,会自动为该类添加 getter/setter 方法。
  • @Entity@Table 注解都是 JDK 1.5 以后引入的元数据注解,遵循 JPA 规范中定义的查询语言 JPQL(Java Persistence Query Language) 执行数据库查询。JPQL 类似于 SQL,但是针对实体对象而不是数据库表,类似 SQL 语法,适用于 Java 类。
  • @Entity 表明该类是一个实体类,默认使用 ORM 规则,即类名为数据库表名,类中的字段名为数据库表中的字段名。
  • @Table 注解是非必选项,它的优先级高于 @Entity 注解,比如说 @Entity(name="user") 和 @Table(name="users") 同时存在的话,对应的表名为 users
  • @Id 表名该字段为主键字段,当声明了 @Entity 注解,@Id 就必须也得声明。

UserRepository接口类

创建 UserRepository 接口类。

package com.langjialing.jpademo.repository;

import com.langjialing.jpademo.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

import java.util.List;

/**
 * @author 郎家岭伯爵
 * @time 2023/7/12 13:18
 */
public interface UserRepository extends JpaRepository<User, Integer> {
    /**
     * 自定义查询方法
     * @param name name
     * @return List
     */
    @Query("select u from User u where u.userName like concat('%',?1,'%')")
    List<User> findByNameLikeIgnoreCase(String name);
}
  • 如果只是简单的对表进行增删改查操作,那么只需要继承 JpaRepository 接口,并传递两个参数(第一个为实体类,第二个为主键类型)即可。
  • @Query 注解中的 User 为实体类的类名,而非数据库的表名 user。这是 JPQL 和原生 SQL 的区别。

Service层

Service 接口类:

package com.langjialing.jpademo.service;

import com.langjialing.jpademo.entity.User;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

import java.util.List;

/**
 * @author 郎家岭伯爵
 * @time 2023/7/12 13:20
 */
public interface UserService {
    /**
     * 根据ID查询单个用户。
     * @param id id
     * @return user
     */
    User findById(Integer id);

    /**
     * 查找所有用户。
     * @return List
     */
    List<User> findAll();

    /**
     * 新增/更新用户。
     * @param user user
     * @return User
     */
    User save(User user);

    /**
     * 根据ID删除用户。
     * @param id ID
     */
    void delete(Integer id);

    /**
     * 查询所有用户(分页)。
     * @param pageable 分页参数
     * @return Page
     */
    Page<User> findAll(Pageable pageable);

    /**
     * 根性名字查询用户。
     * @param name name
     * @return List
     */
    List<User> findByNameLikeIgnoreCase(String name);
}

Service 接口实现类:

package com.langjialing.jpademo.service.impl;

import com.langjialing.jpademo.entity.User;
import com.langjialing.jpademo.repository.UserRepository;
import com.langjialing.jpademo.service.UserService;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;

/**
 * @author 郎家岭伯爵
 * @time 2023/7/12 13:23
 */
@Service
public class UserServiceImpl implements UserService {

    @Resource
    private UserRepository userRepository;

    @Override
    public User findById(Integer id) {
        return userRepository.findById(id).orElse(null);
    }

    @Override
    public List<User> findAll() {
        return userRepository.findAll();
    }

    @Override
    public User save(User user) {
        return userRepository.save(user);
    }

    @Override
    public void delete(Integer id) {
        userRepository.deleteById(id);
    }

    @Override
    public Page<User> findAll(Pageable pageable) {
        return userRepository.findAll(pageable);
    }

    @Override
    public List<User> findByNameLikeIgnoreCase(String name) {
        return userRepository.findByNameLikeIgnoreCase(name);
    }
}
  • @Resource@Autowired 注解都是用来自动装配对象的,可以用在字段上,也可以用在 setter 方法上。@Autowired 是 Spring 提供的注解,@Resource 是 Java 提供的注解,也就是说,如果项目没有使用 Spring 框架而是 JFinal 框架,@Resource 注解也是支持的。另外,@ResourcebyName 自动装配,@AutowiredbyType 自动装配,当有两个类型完全一样的对象时,@Autowired 就会出错了。

controller层

创建 UserController 测试方法。

package com.langjialing.jpademo.controller;

import com.langjialing.jpademo.entity.User;
import com.langjialing.jpademo.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.List;

/**
 * @author 郎家岭伯爵
 * @time 2023/7/12 13:34
 */
@RestController
@Slf4j
public class UserController {

    @Resource
    private UserService userService;

    @PostMapping("/save")
    public User save(@RequestBody User user) {
        return userService.save(user);
    }

    @GetMapping("/find")
    public User findById(@RequestParam Integer id) {
        return userService.findById(id);
    }

    @GetMapping("/findByNameLikeIgnoreCase")
    public List<User> findByNameLikeIgnoreCase(@RequestParam String name) {
        return userService.findByNameLikeIgnoreCase(name);
    }

    @GetMapping("/findAll")
    public List<User> findAll() {
        return userService.findAll();
    }

    @PostMapping("/findAllPage")
    public Page<User> findAllPage(Pageable pageable) {
        log.info("size:{}", pageable.getPageSize());
        log.info("page:{}", pageable.getPageNumber());
        return userService.findAll(pageable);
    }

    @GetMapping("/delete")
    public void delete(@RequestParam Integer id) {
        userService.delete(id);
    }
}

分页接口测试

删除接口测试

总结

SpringBoot 整合 JPA