Spring Boot学习笔记二:使用JPA
前面已经初步搭建好了SpringBoot,那么在日常开发中不可避免的会用到数据库,那么现在我们开始在SpringBoot上使用JPA吧。
那么什么是JPA(Java Persistence API),中文名Java持久层API。是一套Sun公司Java官方制定的ORM 方案
ORM是什么
ORM(Object Relational Mapping)对象关系映射。简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将程序中的对象自动持久化到关系数据库中。
ORM有什么用?
在操作数据库之前,先把数据表与实体类关联起来。然后通过实体类的对象操作(增删改查)数据库表,这个就是ORM的行为!
所以ORM是一个实现使用对象操作数据库的设计思想。
所以JPA只是一套实现ORM理论的接口,我们必须要有具体的实现者(Hibernate,TopLink,JDO)才可以完成ORM操作功能的实现。
使用流程
首先在pom.xml文件中添加依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
接下来需要我们在application.properties中配置数据源和jpa的基本的相关属性,如下:
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://填写自己的机器:3306/填写自己的库?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
spring.datasource.username=填写自己的
spring.datasource.password=填写自己的
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jackson.serialization.indent_output=true
1.第一行表示驱动的名称,这个和具体的数据库驱动有关,视情况而定,我这里使用了MySql数据库,所以驱动名为com.mysql.cj.jdbc.Driver
2.第二行表示数据库连接地址,当然也是视情况而定
3.第三四行表示数据库连接的用户名和密码
4.第五行则配置了实体类维护数据库表结构的具体行为,update表示当实体类的属性发生变化时,表结构跟着更新,这里我们也可以取值create,这个create表示启动的时候删除上一次生成的表,并根据实体类重新生成表,这个时候之前表中的数据就会被清空;还可以取值create-drop,这个表示启动时根据实体类生成表,但是当sessionFactory关闭的时候表会被删除;validate表示启动时验证实体类和数据表是否一致;none表示啥都不做。
5.第六行表示hibernate在操作的时候在控制台打印真实的sql语句
6.第七行表示格式化输出的json字符串
以上就是我们在application.properties中对JPA进行的一个简单配置。
然后定义相应的实体类,在Project启动时,系统会根据实体类创建相应的数据表
@Entity
@Table(name="t_user",catalog = "hd_text")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String name;
private Integer age;
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 getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
@Entity注解:这个表示这是一个和数据库表映射的实体类
@Table:声明此对象映射到数据库的数据表,通过它可以为实体指定表(talbe),name 用来命名当前实体类 对应的数据库表的名字,catalog用于设置表所属的数据库目录或模式,通常为数据库名
@Id注解:表示该字段是一个id
@GeneratedValue注解:则表示该字段自增
接下来我们定义数据访问接口了,我们的数据访问接口需要继承JpaRepository类
public interface UserRepository extends JpaRepository<User,Integer> {
User findByName(String name);
List<User>findByAge(Integer age);
@Query("select u from t_user u where u.age=:age order by u.age desc")
List<User>findByAgeSort(Integer age);
}
1.当我们继承JpaRepository接口后,我们就自动具备了如下数据访问方法:
List<T> findAll();
List<T> findAll(Sort var1);
List<T> findAll(Iterable<ID> var1);
<S extends T> List<S> save(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);
2.我们可以在接口中定义查询方法,可以按照属性名来查询,但是方法的命名方式是固定的,比如第一个方法和第二个方法,第一个方法表示根据一个属性查询,第二个方法表示根据多个属性查询,findBy、And等可以算作是这里的查询关键字了,如果写作其他名称则系统不能识别,类似的关键字还有Like、Or、Is、Equals、Between等,而这里的findBy关键字又可以被find、read、readBy、query、queryBy、get、getBy等来代替。
3.在查询的过程中我们也可以限制查询结果,这里使用的关键字是top、first等
4.我们也可以向第三个方法那样添加@Query注解,就是使用原生的sql语句(根据数据库的不同,在sql的语法或结构方面可能有所区别)进行查询数据库的操作
接下来就差一个Controller了,我们写一个简单的Controller,用来测试一下上文中的数据访问接口是否正确
@Controller
public class TextController {
@Autowired
UserRepository userRepository;
@RequestMapping("/save")
public User save(String name,Integer age) {
User user = new User();
user.setAge(age);
user.setName(name);
userRepository.save(user);
return user;
}
}
然后发现启动的时候一直报错:Validation failed for query for method public abstract
image.png
去网上找,发现使用原生sql要加上nativeQuery = true
@Query(value = "select u from t_user u where u.age=:age order by u.age desc",nativeQuery = true)
List<User>findByAgeSort(Integer age);
OK,启动成功
用Postman测试一下
image.png
OK,这样我们就可以使用JPA了