JPA
介绍
JPA(Java Persistence API),是Java EE 5的标准ORM接口,也是ejb3规范的一部分
spring中使用时的配置
配置文件:application.properties
spring.datasource.username = <用户名>
spring.datasource.password = <密码>
spring.datasource.url=jdbc:mysql://localhost:3306/<数据库名>
# 每次新启动项目时操作数据库的方式,可选值有:
# none:不操作
# create:新建表,如果已存在则清空数据
# create-drop:退出时删除表
# update:更新表,没有表会创建,已有数据不会清空。软更改表结构不会更新,比如新增约束、更改值是否可以为空
# validate:校验模型与数据库的字段是否相同,不同则报错
# 网友建议:不要使用create和create-drop
spring.jpa.hibernate.ddl-auto=update
# 数据库操作时显示SQL语句
spring.jpa.show-sql=true
# 解决 Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set 报错
# 设置默认引擎为InnoDB
spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
注解
@Entity
介绍
表明这个Class是实体类,并且使用默认的ORM规则,即class名对应数据库中的表名,class字段名即表中的列名
作用对象
参数
@Table
介绍
Table用来定义entity主表的name,catalog,schema等属性
作用对象
参数
name
:表名catalog
:对应关系数据库中的catalogschema
:对应关系数据库中的schemaUniqueConstraints
:定义一个UniqueConstraints数组,指定需要建唯一约束的列,在抽象父类上使用此方法无效。使用方法
// 设置表名、创建唯一约束 // 定义多个唯一性约束时,使用{}包括所有的@UniqueConstraint内容 // 在多个字段上创建唯一性约束时,columnNames参数指定多个值,这些值使用{}包括 @Table(name = "student", uniqueConstraints=@UniqueConstraint(name = "UK_work_num", columnNames="work_num")) public class StudentUser extends User{ }
@Id
介绍
作用对象
设置联合主键的方法
JPA需要定义一个特殊的ID类,该类使用@IdClass注释附加到实体类
package com.example.eduadministration.Model;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.io.Serializable;
/**
* @author 秋猫
* @version 2021-05-25 12:03
* @description 成绩表,学生选完课没有成绩时成绩字段为NULL
*/
@Entity
@Data
@NoArgsConstructor
@Table(name = "grade")
@IdClass(PrimaryKey.class)
public class Grade {
/**
* 学生学号
*/
@Id
@Column(length = 20)
private String studentId;
/**
* 课程代码
*/
@Id
@Column(length = 20)
private String courseId;
/**
* 分数
*/
@Column(precision = 5, scale = 1)
private double score;
}
/**
* 主键类,用于定义实体类的主键
*/
class PrimaryKey implements Serializable {
String studentId;
String courseId;
}
@GeneratedValue
介绍
作用对象
参数
strategy
:生成策略。默认值:GenerationType.AUTOgenerator
:生成器。默认值:""
@Query
介绍
作用对象
参数
value
:要执行的语句。默认空countQuery
:countProjection
:nativeQuery
:True表示执行原生SQL语句,默认为False,False代表使用JPQL。name
:countName
:使用方法
//为 @Query 注解传递参数的方式1: 命名参数的方式. 冒号后面的表示参数 @Query("SELECT p FROM Person p WHERE p.lastName = :lastName AND p.email = :email") List<Person> testQueryAnnotationParams2(@Param("email") String email, @Param("lastName") String lastName);
@Column
介绍
作用对象
参数
name
:指定映射的表列名,默认””unique
:是否设置唯一性约束,约束名为前缀UK_后面随机生成,默认falsenullable
:是否可以为空,默认truecolumnDefinition
:创建表时,该字段创建的SQL语句,一般用于使用Entity生成表时使用length
:最大长度precision
:字段类型为double时,表示数值的总长度scale
:字段类型为double时,表示小数点所占的位数
@Component
介绍
标记一个Spring组件,用于把普通POJO类实例化到spring容器中
作用对象
枚举类
GenerationType
介绍
枚举值
JPQL
介绍
Java Presistence Query Language(JPQL),java持久性查询语言。Java EE中,JPQL是专门为Java应用程序访问和导航实体实例设计的。它是JPA规范的重要组成部分,其实就是一种查询语言,语法类似于SQL,但与SQL有着本质的区别。
JPQL与SQL
- JPQL是面向对象的查询语言,因此它可以完全理解继承、多态和关联等特征。而且JPQL内置了大量函数,极大地方便了JPQL查询的功能。当然JPQL底层依然是基于SQL的,但JPQL到SQL的转换无须开发者关心,JPQL解析器会负责完成这种转换,并负责执行这种转换的SQL语句来更新数据库。
- SQL是面向关系数据库的查询语言,因此SQL操作的对象是数据表、数据列;而JQPL操作的对象是实体对象,对象属性。
-
代码对比
SQL:
// 原生SQL SELECT name, age, user_id FROM t_user
JPQL:
// 面向对象的JPQL语句 SELECT name, age, userId FROM User
BUG
unique失效
案例
@Column(name = "work_num", unique = true, nullable = false) private String workNum;
报错信息
Specified key was too long; max key length is 1000 bytes
解释
解决办法
指定字段的最大长度
@Column(name = "work_num", unique = true, nullable = false, length = 10) private String workNum;
使用技巧
实现联表查询以及Repository层查询结果模型转换
首先要定义想要的结果模型,其中需要定义构造器。
@Data @AllArgsConstructor public class StudentGrade { /** * 学生学号 */ private String studentId; /** * 课程代号 */ private int courseId; /** * 课程名称 */ private String courseName; /** * 课程成绩 */ private double score; /** * 学年 */ private String schoolYear; /** * 学期 */ private String schoolTerm; }
在Repository层接口的方法上使用@Query注解,注解的value参数设置为JPQL语句。查询的结果处使用new <结果模型>(字段)的方式将查询的结果转换成想要的模型。
- <结果模型>需要是类的全路径
- 冒号+参数可以使用方法中接收的参数
@Query("SELECT new com.example.eduadministration.DAO.StudentGrade(a.studentId, b.courseId, c.name, b.score, c.schoolYear, c.schoolTerm) " + "FROM StudentUser AS a, CourseStudent AS b, Course AS c " + "WHERE a.studentId = :studentId AND b.studentId = a.studentId AND c.courseId = b.courseId") List<StudentGrade> fetchAllCourseByStudentId(@Param("studentId") String studentId);