简介
基本概念
Jpa(Java Persistence API)即 java 持久化api规范,并不是一个ORM框架,而是一种访问数据的接口定义,通过与数据访问框架或者ORM框架配合,可以简单方便的处理与数据库的交互。这种概念有点类似 slf4j 和 logback 的关系。
SpringDataJpa是对JPA规范的封装,旨在提高开发效率,同时不失灵活性,它提供了一种简单、一致的方式来访问不同种类的数据源,包括关系数据库、非关系数据库、MapReduce 框架等。Spring Data JPA 还提供了一些高级特性,如动态查询、多表查询、嵌套查询、存储过程和函数调用等。
在SpringBoot中,jpa默认情况下的orm实现是 hibernate。
优点
封装了 JPA 的细节,提供了更高层次的抽象,简化了数据访问层的开发,提高了开发效率;支持多种数据源,包括关系型数据库和非关系型数据库;提供了一些高级特性,如动态查询、多表查询、嵌套查询、存储过程和函数调用等;可与其他 Spring 框架无缝集成,如 Spring Boot、Spring Cloud 等。
缺点
对于一些复杂的查询,仍需要手动编写 SQL 语句;默认的实现可能存在性能问题,需要手动优化。
基础实践
pom
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.20</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.76</version>
</dependency>
yml
主要配置了数据库访问参数,没有显示配置数据库连接池,默认使用的是 HikariPool 。
通过配置 show-sql = true 来打印sql
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://ip:3306/test?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false
username: root
password: 123456
jpa:
show-sql: true
entity
package com.ramble.ramblespringboot.springdatajpa.entity;
import lombok.Data;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import java.io.Serializable;
@Data
@Entity
@Table(name = "user")
public class UserEntity implements Serializable {
@Id
private String id;
@Column(name = "name")
private String name;
@Column(table = "user", name = "state")
private Integer state;
}
- Entity:表示此类为一个数据库实体
- Tabel:映射到数据库的哪个表
- Id:表的主键,必须
- Column:属性对应的表字段
repository
package com.ramble.ramblespringboot.springdatajpa.repository;
import com.ramble.ramblespringboot.springdatajpa.entity.UserEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface UserRepository extends JpaRepository<UserEntity, String> {
UserEntity findByName(String name );
@Query("select u from UserEntity u where u.name like %?1 and u.id = ?2")
List<UserEntity> find(String name, String id);
@Query(nativeQuery = true, value = " select * from user where name = ?1 ")
List<UserEntity> findByNativeQuery(String name);
//启动的时候报异常,不可 param.name 访问
// @Query("select u from UserEntity u where u.name like %:us.name and u.id = :us.id")
// List<UserEntity> findByParam(@Param("us") UserEntity us);
@Query("select u from UserEntity u where u.name like %:name and u.id = :id")
List<UserEntity> findByParam(@Param("id") String id, @Param("name") String name);
@Modifying
@Query(" update UserEntity u set u.state=?2 where u.id = ?1")
Integer updateSate(String id, Integer state);
}
- Repository:表示此接口是一个持久层,同时注入到容器中,供其他容器对象访问
- JpaRepository:实现JpaRepository 接口,便于使用默认的crud接口。其中第一个泛型参数UserEntity 为数据库实体的名字,第二泛型参数String 为数据库表主机的数据类型
- findByName:StringDataJpa会根据方法名称自行生成查询sql
- Query:显示指定查询的sql,这里又分为两种方式,一种是jpa方式,一种是本地查询方式,通过指定nativeQuery=true设置。
- JPAQuery:当为jpa模式的时候表名称写实体名称
- NativeQuery:表名写数据库表的名称
- 参数处理:参数赋值有多种方式:
- ?1: 表示获取方法第一个参数
- :id:表示通过param指定的参数名称获取参数
- Modifying:当update/delete操作的时候需要添加此注解
controller
package com.ramble.ramblespringboot.springdatajpa.controller;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.ramble.ramblespringboot.springdatajpa.entity.UserEntity;
import com.ramble.ramblespringboot.springdatajpa.repository.UserRepository;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.*;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@Slf4j
@AllArgsConstructor
@RestController
@RequestMapping("/test")
public class TestController {
private UserRepository userRepository;
@PostMapping("/")
public Boolean create() {
UserEntity user = new UserEntity();
user.setId(IdUtil.fastSimpleUUID());
user.setName(RandomUtil.randomString(4));
user.setState(RandomUtil.randomInt());
UserEntity result = userRepository.save(user);
return true;
}
@DeleteMapping("/{id}")
public Boolean delete(@PathVariable("id") String id) {
//userRepository.deleteById(id);
UserEntity user = new UserEntity();
user.setId(id);
userRepository.delete(user);
return true;
}
@GetMapping("/crud")
public String crud() {
long count = userRepository.count();
UserEntity byId = userRepository.getById("ecde5544eb0647ef8b005ca9f6ff68db");
List<UserEntity> all = userRepository.findAll();
List<UserEntity> all1 = userRepository.findAll(Sort.by("id"));
UserEntity user = new UserEntity();
user.setId("ecde5544eb0647ef8b005ca9f6ff68db");
user.setName("明");
ExampleMatcher matcher = ExampleMatcher.matching();
matcher.withMatcher("id", m -> m.startsWith());
matcher.withMatcher("name", m -> m.contains());
Example<UserEntity> example = Example.of(user, matcher);
List<UserEntity> allExample = userRepository.findAll(example);
Pageable page = PageRequest.of(0, 20);
Page<UserEntity> allPage = userRepository.findAll(example, page);
return JSON.toJSONString(allPage);
}
/**
* 执行 update /delete 必须添加 事务注解 Transactional
*
* @return
*/
@Transactional
@GetMapping("/query")
public Boolean query() {
UserEntity byName = userRepository.findByName("明");
List<UserEntity> find = userRepository.find("明", "f2bcbe98ef88450b955f76bb063c1cf8");
List<UserEntity> nativeQuery = userRepository.findByNativeQuery("明");
// UserEntity user = new UserEntity();
// user.setName("明");
// List<UserEntity> byParam = userRepository.findByParam(user);
Integer update = userRepository.updateSate("f2bcbe98ef88450b955f76bb063c1cf8", 2);
List<UserEntity> byParam = userRepository.findByParam("f2bcbe98ef88450b955f76bb063c1cf8", "明");
return true;
}
}
注意事项
- 执行 update /delete 必须添加 事务注解 Transactional
思考
-
repository接口传参如何传 dto , 测试代码中我传递 @Param(“us”) UserEntity us 这样一个参数,无法使用 :us.name 的方式获取
-
打印的sql没有输出参数,是不支持还是姿势不对?
没有回复内容