第十二章 关系型数据库其他持久化操作 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.MySQL8Dialect3.创建实体类
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(); // 总页数