Skip to content

第十二章 关系型数据库其他持久化操作 v1.0 ​

除了MyBatis之外,Spring还提供了其他持久化方案,常用的有JdbcTemplate和Spring Data JPA

第一部分 JdbcTemplate ​

Spring对JDBC的封装,简化数据库操作,适合简单场景

一、基本使用 ​

1.引入依赖 ​

xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>

2.配置数据源 ​

yaml
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/test?useSSL=false&serverTimezone=UTC
    username: root
    password: 123456

二、CRUD操作 ​

1.注入JdbcTemplate ​

java
@Service
public class UserService {
    @Autowired
    private JdbcTemplate jdbcTemplate;
}

2.插入数据 ​

java
public int insert(User user) {
    String sql = "INSERT INTO user(name, age) VALUES(?, ?)";
    return jdbcTemplate.update(sql, user.getName(), user.getAge());
}

3.更新数据 ​

java
public int update(User user) {
    String sql = "UPDATE user SET name=?, age=? WHERE id=?";
    return jdbcTemplate.update(sql, user.getName(), user.getAge(), user.getId());
}

4.删除数据 ​

java
public int delete(Long id) {
    String sql = "DELETE FROM user WHERE id=?";
    return jdbcTemplate.update(sql, id);
}

5.查询单条数据 ​

java
public User findById(Long id) {
    String sql = "SELECT * FROM user WHERE id=?";
    return jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(User.class), id);
}

6.查询列表 ​

java
public List<User> findAll() {
    String sql = "SELECT * FROM user";
    return jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(User.class));
}

7.查询聚合函数 ​

java
public int count() {
    String sql = "SELECT COUNT(*) FROM user";
    return jdbcTemplate.queryForObject(sql, Integer.class);
}

三、批量操作 ​

java
public int[] batchInsert(List<User> users) {
    String sql = "INSERT INTO user(name, age) VALUES(?, ?)";
    return jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
        @Override
        public void setValues(PreparedStatement ps, int i) throws SQLException {
            ps.setString(1, users.get(i).getName());
            ps.setInt(2, users.get(i).getAge());
        }
        @Override
        public int getBatchSize() {
            return users.size();
        }
    });
}

第二部分 Spring Data JPA ​

基于JPA规范的持久层框架,通过方法名自动生成SQL,适合快速开发

一、基本使用 ​

1.引入依赖 ​

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

2.配置JPA ​

yaml
spring:
  jpa:
    hibernate:
      ddl-auto: update   # 自动建表策略:none/update/create/create-drop
    show-sql: true        # 控制台显示SQL
    database-platform: org.hibernate.dialect.MySQL8Dialect

3.创建实体类 ​

java
import javax.persistence.*;

@Entity
@Table(name = "user")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "name", length = 50)
    private String name;

    @Column(name = "age")
    private Integer age;

    // getter/setter...
}

二、Repository接口 ​

1.创建Repository ​

java
import org.springframework.data.jpa.repository.JpaRepository;

public interface UserRepository extends JpaRepository<User, Long> {
}

2.内置CRUD方法 ​

JpaRepository已内置了常用方法,直接调用即可:

java
@Autowired
private UserRepository userRepository;

// 新增/更新
userRepository.save(user);
userRepository.saveAll(userList);

// 根据ID查询
Optional<User> user = userRepository.findById(1L);

// 查询全部
List<User> all = userRepository.findAll();

// 删除
userRepository.deleteById(1L);
userRepository.delete(user);

// 统计数量
long count = userRepository.count();

// 判断是否存在
boolean exists = userRepository.existsById(1L);

3.自定义查询方法 ​

通过方法名自动生成SQL,无需写任何SQL语句:

java
public interface UserRepository extends JpaRepository<User, Long> {
    // SELECT * FROM user WHERE name = ?
    List<User> findByName(String name);

    // SELECT * FROM user WHERE age > ?
    List<User> findByAgeGreaterThan(Integer age);

    // SELECT * FROM user WHERE name LIKE '%keyword%'
    List<User> findByNameLike(String name);

    // SELECT * FROM user ORDER BY age DESC
    List<User> findAllByOrderByAgeDesc();

    // SELECT * FROM user WHERE age BETWEEN ? AND ?
    List<User> findByAgeBetween(Integer start, Integer end);
}

4.@Query自定义SQL ​

当方法名无法满足时,可以使用@Query注解:

java
public interface UserRepository extends JpaRepository<User, Long> {
    // JPQL查询(面向对象)
    @Query("SELECT u FROM User u WHERE u.name = :name AND u.age > :age")
    List<User> findByNameAndAge(@Param("name") String name, @Param("age") Integer age);

    // 原生SQL查询
    @Query(value = "SELECT * FROM user WHERE name = ?1", nativeQuery = true)
    List<User> findByNameNative(String name);

    // 更新操作(需要加@Transactional和@Modifying)
    @Transactional
    @Modifying
    @Query("UPDATE User u SET u.age = :age WHERE u.id = :id")
    int updateAge(@Param("id") Long id, @Param("age") Integer age);
}

三、分页与排序 ​

java
// 排序
Sort sort = Sort.by(Sort.Direction.DESC, "age");
List<User> users = userRepository.findAll(sort);

// 分页
Pageable pageable = PageRequest.of(0, 10); // 第1页,每页10条
Page<User> page = userRepository.findAll(pageable);

// 分页+排序
Pageable pageable = PageRequest.of(0, 10, Sort.by("age").descending());
Page<User> page = userRepository.findAll(pageable);

// 获取分页信息
List<User> content = page.getContent();      // 当前页数据
long totalElements = page.getTotalElements(); // 总记录数
int totalPages = page.getTotalPages();        // 总页数