Springboot版本为2.1.8.RELEASE
本文包含内容,怎么使用SpringBoot-JPA进行数据查询。不定期更新。
依赖
<!--springboot 整合的数据连接-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<!--主角JPA-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!--web框架用于页面测试-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--mysql连接-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
配置文件application.properties
# mysql 数据库连接
spring.datasource.driverClassName = com.mysql.cj.jdbc.Driver
spring.datasource.url = jdbc:mysql://IP地址:3306/test?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&autoReconnect=true
spring.datasource.username =用户名
spring.datasource.password =密码
spring.datasource.hikari.max-lifetime=120000
#
#如果数据库中没有这个表 则根据entity直接创建
Spring.jpa.hibernate.ddl-auto =update
Spring.jpa.show-sql =true
spring.main.allow-bean-definition-overriding=true
怎么使用jpa
创建一个entity实体类。 new entity.Student
在类上标识@Entity 表名这是一个Entity类 @Table(name="数据库中对应的表名")
对于属性: 主键给@Id 表名这是一个主键 @GeneratedValue(stratefy=GenerationType.IDENTITY)设置自增策略为自动
注意Entity一定需要一个空的构造方法,不然springboot没法创建这个类。(源码为反射的无参构造,clazz.newInstance();)。
其余属性可以给@Column,包含长短、表结构中对应的列名等等。
package com.huangyichun.jpalearn.entity;
import javax.persistence.*;
@Entity
@Table(name = "user") // 不配置为驼峰
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column
private String name;
private Integer old;
public Student() {
}
public Student(String name, Integer old) {
this.name = name;
this.old = old;
}
@Override
public String toString() {
return "User{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", old=" + old +
'}';
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getOld() {
return old;
}
public void setOld(Integer old) {
this.old = old;
}
}
创建repository.StudentRepository.interface extends JpaRepository<Student, Integer>
关注JpaRepository<对应的类, 类中主键的类型>
创建就已经完毕。
在使用处,比如直接在controller中
@Autowired
StudentRepository studentRepository;
@ResponseBody
@RequestMapping("/")
public String root(){
Student student= new Student("姓名", 年龄);
studentRepository.save(student);
System.out.println(student.toString());
return student.toString();
}
@ResponseBody
@RequestMapping("/delete/{id}")
public String delete(@PathVariable Integer id){
Optional<Student> s = studentRepository.findById(id);
studentRepository.deleteById(id);
return s.get().toString() + "已经被删除";
}
@ResponseBody
@RequestMapping("/update/{id}/{name}")
public String update(@PathVariable Integer id, @PathVariable String name){
/*获取以后,再重新赋值 其实有其他更好的办法*/
Student student = studentRepository.findById(id).get();
student.setName(name);
studentRepository.save(student);
return student.toString();
}
@ResponseBody
@RequestMapping("/{id}")
public String find(@PathVariable Integer id){
Optional<Student> s = studentRepository.findById(id);
return s.get().toString();
}
以上分别对应增删改查。
用到的指令也就只有 .save() / .deleteById() / .findById()
为什么我们什么sql语句都没有写就能实现这些呢?
原因是jpa已经帮我们定制了这些方法。查看JpaRepository接口
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package org.springframework.data.jpa.repository;
import java.util.List;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Sort;
import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.data.repository.query.QueryByExampleExecutor;
@NoRepositoryBean
public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {
List<T> findAll();
List<T> findAll(Sort var1);
List<T> findAllById(Iterable<ID> var1);
<S extends T> List<S> saveAll(Iterable<S> var1);
void flush();
<S extends T> S saveAndFlush(S var1);
void deleteInBatch(Iterable<T> var1);
void deleteAllInBatch();
T getOne(ID var1);
<S extends T> List<S> findAll(Example<S> var1);
<S extends T> List<S> findAll(Example<S> var1, Sort var2);
}
可以看到,已经帮我们定制了一些最常用的方法,但是,你会发现并没有实现的类。为什么在接口里面定义了方法就能使用呢?
反射,利用定义的方法名,来生成sql语句。这里原理不扯远,我们只谈使用方法。
以上的方法不够用怎么办?在我们自己定义的StudentRepository中自己定义方法即可。
public interface StudentRepository extends JpaRepository<Student, Integer> {
public Optional<Student> findById(Integer id);
public List<Student> findByOld(Integer old);
@Query(nativeQuery = true, value = "select * from user where id=?1")
public Optional<Student> findById2(Integer id);
}
注意点:
- 怎么定义名字:如果是查询的话直接find,如果要添加条件By什么条件Id
- 如果能确认返回值只有一个或者0个,推荐使用Optional包装返回的Entity
- 如果返回值可能有多个,则需要List来封装
- 为什么有个方法上面添加了@Query? 这个是用来定义一些自己的参数 比如查询的sql是什么等等,感兴趣直接看他源码就知道了。