概述
JPA为对象关系映射提供了一种基于POJO的持久化模型,简化数据持久化代码的开发工作,为Java社区屏蔽不同的持久化API的差异
JPA常用注解
@Entity
每个持久化POJO类都是一个实体Bean,通过在类的定义中使用@Entity 注解来进行声明 ,将映射到指定的数据库表。如声明一个实体类Customer,将它映射到数据的coustomer表上
@Table
声明此对象映射到数据库的数据表。该注释不是必需的,如果没有, 系统就会使用默认值(实体的短类名)。@Table标注的常用选项是name,用于指明数据库的表名。
@Id
@GeneratedValue
用于标注主键的生成策略,通过strategy属性指定。默认情况下,JPA自动选择一个最合适底层数据库的主键生成策略:SqlServer对应identity,MySql对饮auto increment。
JPA提供的四种标准用法为TABLE,SEQUENCE,IDENTITY,AUTO.
TABLE:使用一个特定的数据库表格来保存主键。
SEQUENCE:根据底层数据库的序列来生成主键,条件是数据库支持序列。
IDENTITY:主键由数据库自动生成(主要是自动增长型)
AUTO:主键由程序控制
@Column
- 当实体的属性与其映射的数据库表的列不同名时需要使用@Column标注说明,该属性通常置于实体的属性声明语句之前,还可与@Id标注一起使用。
- @Column标注的常量属性是name,用于设置映射数据库表的列名。此外,该注解还包含其他多个属性,比如:unique,nullable,length等。
@Column标注的columnDefinition属性:表示该字段在数据中的实际类型,通常ORM框架可以根据属性类型自动判断数据中的字段的类型,但是对于Date类型仍无法确定数据库中字段类型究竟是Date,Time还是Timestamp。此外,String的默认类型为varchar,如果要将String类型映射到特定数据库的BLOB或Text字段类型。
@Transient
表示该属性并非一个到数据库表的字段的映射,ORM框架将忽略该属性。
如果一个属性并非数据库的字段映射,就务必将其标示为@Transient
@Temporal
在核心的JAVA API中并没有定义Date类型的精度(temporal precision)。而在数据库中,表示Date类型的数据类型有DATE,TIME和TEIMSTAMP三种精度(即单纯的日期,时间,或者两者兼备)。在运行属性映射是可使用
-
@DynamicUpdate
添加依赖
项目根目录
pom.xml添加依赖spring-boot-starter-data-jpamysql-connector-java```org.springframework.boot spring-boot-starter-data-jpa org.springframework.boot spring-boot-starter-web mysql mysql-connector-java runtime org.springframework.boot spring-boot-starter-test test
<a name="whSmi"></a>## 修改配置文件`application.yml````yamlspring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://127.0.0.1:3306/springboot?useUnicode=true&characterEncoding=utf-8&useSSL=trueusername: rootpassword: 123456jpa:database: mysqlhibernate:ddl-auto: createshow-sql: truedatabase-platform: org.hibernate.dialect.MySQL55Dialect
mysql相关配置
datasource数据源hibernate: 相关配置信息有以下几种类型ddl-auto:create: 每次运行加载不管之前是否有数据都会自动创建一个表,会造成数据丢失。ddl-auto:update: 第一次加载会创建新的数据接口,之后只会在原有表基础之上进行迭代。ddl-auto:validate: 验证类里面的属性与表结构是否一致。ddl-auto:create-drop: 每次退出时删除。ddl-auto:node: 默认什么都不做。
show-sql: 是否打印SQL,在开发时可以开启方便调试。-
CRUD操作
创建表
就是创建存储的User实体(User类)
是不需要手动去数据库创建表的,以下创建的User类和定义的属性会对应到数据库中的表和字段,这就需要应用jpa的特性了,看下以下注解。
@Entity: 代表此类映射为数据库的表结构@Id: 指定一个主键@GeneratedValue: 配置主键相关信息Table: 使用一个特定的数据库表来保存主键IDENTITY: 数据库自动生成AUTO: 主键由程序控制,默认值SEQUENCE: 通过数据库的序列产生主键,MYSQL不支持,部分数据库(Oracle,PostgreSQL,DB2)支持序列对象
User.java
package com.github.springboot.domain;import javax.persistence.*;@Entitypublic class User {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Integer id;@Column(length = 128,nullable = false)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;}}
创建数据访问接口
Repository类下没有任何接口,只是一个空类。Repository接口的子类有CrudRepository、 PagingAndSortingRepository 、 JpaRepository等。其中,CrudRepository类提供了基本的增删改查等接口 , PagingAndSortingRepository类提供了基本的分页和排序等接口,而JpaRepository是CrudRepository 和 PagingAndSortingRepository 的子类 , 继承了它们的所有接口 。
//// 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;@NoRepositoryBeanpublic 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);}
通过下面继承图可以知道接口的继承关系,一般都是都是JpaRepository类,加上自定义方法完成业务开发

创建接口User的数据访问UserRepository继承于JpaRepository
package com.github.springboot.repository;import com.github.springboot.domain.User;import org.springframework.data.jpa.repository.JpaRepository;import java.util.List;public interface UserRepository extends JpaRepository<User,Integer> {public List<User>findByName(String name);}
创建UserController
UserController.java保存一个用户
package com.github.springboot.controller;import com.github.springboot.domain.User;import com.github.springboot.repository.UserRepository;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.*;import java.util.List;import java.util.Optional;@RestController@RequestMapping("api/v1/user")public class UserController {@Autowiredprivate UserRepository userRepository;@PostMapping()public User userAdd(@RequestBody User user){return userRepository.save(user);}@GetMapping("list")public List<User> userList() {return userRepository.findAll();}@GetMapping("{id}")public Optional<User> userFindOne(@PathVariable("id") Integer id) {return userRepository.findById(id);}@GetMapping()public List<User> findUserListByName(@RequestParam(name="name",required = true) String name) {return userRepository.findByName(name);}@PutMapping(value = "{id}")public User userUpdate(@PathVariable("id") Integer id, @RequestParam("name") String name,@RequestParam("age") Integer age) {User user = new User();user.setId(id);user.setName(name);user.setAge(age);return userRepository.save(user);}@DeleteMapping("{id}")public void deleteUser(@PathVariable("id") Integer id) {userRepository.deleteById(id);}}
注意, spring-data-jpa 2.0.5.RELEASE 版本之后获取单个对象的数据源需要用findById(),SpringBoot1.x版本可以使用findOne()
Github 地址 https://github.com/baxiang/SpringBoot-Note/tree/master/springboot-jpa
curl 测试
增加用户数据
curl -X POST 'http://127.0.0.1:8080/api/v1/user' -d '{"name":"qiang","age":30}' -H 'Content-Type: application/json'{"id":1,"name":"qiang","age":30}% ➜ springboot-jpa git:(master) ✗ curl -X POST 'http://127.0.0.1:8080/api/v1/user' -d '{"name":"ming","age":20}' -H 'Content-Type: application/json'✗ curl -X POST 'http://127.0.0.1:8080/api/v1/user' -d '{"name":"ming","age":20}' -H 'Content-Type: application/json'{"id":2,"name":"ming","age":20}%
查询用户数据
curl -X GET 'http://localhost:8080/api/v1/user/list'[{"id":1,"name":"qiang","age":30},{"id":2,"name":"ming","age":20}]%
按照id 查询
curl -X GET 'http://localhost:8080/api/v1/user/1'{"id":1,"name":"qiang","age":30}
安装名称查询
curl -X GET 'http://localhost:8080/api/v1/user?name=ming'[{"id":2,"name":"ming","age":20}]%
修改用户数据
curl -X PUT 'http://127.0.0.1:8080/api/v1/user/1?name=hong&age=18'{"id":1,"name":"hong","age":18}
删除用户数据
curl -X DELETE 'http://127.0.0.1:8080/api/v1/user/1'
参考
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.repositories
