Spring Boot JPA

Spring Boot JPA

JPA(Java Persistence API)意即Java持久化API,主要包括三方面的技术

  • ORM元数据
  • API:操作实体对象进行CRUD操作
  • 查询语言:通过面向对象的JPQL查询数据

JPA与Hibernate、Spring Data JPA

JPA是一种ORM规范,提供了一些API接口,并不是ORM实现。

Hibernate Jpa则是Hibernate对JPA的具体实现,是一套ORM框架

Spring Data Jpa在JPA规范下统一了各种ORM框架的Repository层的实现

JPA 使用

  1. 声明一个自定义的Repository接口继承JpaRepository<Class,type>接口,Class是对应的实体类型,type是实体类型的主键的类型

  2. 在接口中声明方法,JPA根据方法名解析进行查询,JPA本身已经声明了诸如findById()、findAll()、save()等基本方法,JPA的save()方法会检查实体是否存在主键,如果存在则为更新操作,不存在则为插入操作。

    JPA接口方法命名规则

    关键字方法命名sql where字句
    AndfindByNameAndPwdwhere name= ? and pwd =?
    OrfindByNameOrSexwhere name= ? or sex=?
    Is,EqualsfindById,findByIdEqualswhere id= ?
    BetweenfindByIdBetweenwhere id between ? and ?
    LessThanfindByIdLessThanwhere id < ?
    LessThanEqualsfindByIdLessThanEqualswhere id <= ?
    GreaterThanfindByIdGreaterThanwhere id > ?
    GreaterThanEqualsfindByIdGreaterThanEqualswhere id > = ?
    AfterfindByIdAfterwhere id > ?
    BeforefindByIdBeforewhere id < ?
    IsNullfindByNameIsNullwhere name is null
    isNotNull,NotNullfindByNameNotNullwhere name is not null
    LikefindByNameLikewhere name like ?
    NotLikefindByNameNotLikewhere name not like ?
    StartingWithfindByNameStartingWithwhere name like ‘?%’
    EndingWithfindByNameEndingWithwhere name like ‘%?’
    ContainingfindByNameContainingwhere name like ‘%?%’
    OrderByfindByIdOrderByXDescwhere id=? order by x desc
    NotfindByNameNotwhere name <> ?
    InfindByIdIn(Collection<?> c)where id in (?)
    NotInfindByIdNotIn(Collection<?> c)where id not in (?)
    TruefindByAaaTuewhere aaa = true
    FalsefindByAaaFalsewhere aaa = false
    IgnoreCasefindByNameIgnoreCasewhere UPPER(name)=UPPER(?)
  3. 注入自定义的Repository就可以使用方法查询

  4. JPA支持自定义查询,在接口上面使用@Query注解加上JPQL语句即可,但是由于JPQL语法是以string类型写入,编译器无法发现错误,影响开发进度,因此尽量少使用JPQL。

JPA 实体建立

在JPA中维护one to one,one to many,many to one,many to many四种映射关系,在每个关系中,只有主表实体拥有连接列,从表实体不具有连接列,主表依赖于从表。

  • 多对一

在多对一关系中,主表实体为“多”的一方,拥有连接列,注解@JoinColumn用于指定连接列(外键列),注解属性name用于指明数据库列名,加在从表实体类型("一"的一方的类型)的属性上,一般与@ManyToOne一起使用,@ManyToOne标注在代表One的实体类型的属性上,@OneToMany注解标注在代表Many的实体类型的属性上,此属性属于“一”的一方,也就是从表实体,不拥有连接列,可以再使用mappedBy属性指明主表实体的连接属性名称,因此mappedBy和@JoinColumn不能同时使用,@OneToMany加在从表实体中list类型主表实体的属性上。在one to many或者many to one关系持久化时,总是先持久化"一"的一方,再持久化"多"的一方。示例Student和Grade是多对一关系。JPA的@Id位于javax.persistence.Id

/*
* Student类
*/
@Entity
@Table(name="student")
public class Student{

	@Id
	@Column(name="student_id") 
	private String id;
	
	@Column
	private String name;
	
	@JoinColumn(name="grade_id")
	@ManyToOne
	private Grade grade;
	//getter and setter
}

/*
* Grade类
*/
@Entity
@Table(name="grade")
public class Grade{

	@Id
	@Column(name="grade_id")
	private Integer id;
	
	@Column(name="grade_name")
	private String gradeName;
	
	@OneToMany(mappedBy="grade")
	private List<Student> studentList;
	//getter and setter
}
  • 多对多

必须指定多对多关系中的一方为主表实体,另一方为从表实体,在主表实体中使用@JoinTable的name属性指明多对多关系的连接表,joinColumns用于指定连接表中主表连接的列名,inverseJoinColumns用于指定连接表中从表连接的列名,主表中@JoinTable与@ManyToMany一般同时注解在对方实体List类型的属性上。示例Employee和Projuct是多对一关系。

/*
* Employee类
*/
@Entity
@Table("name="employee")
public class Employee{
    
    @Id
    @Column(name="id")
    private String id;
    
    @Column(name="name")
    private String employee_name;
    
    @JoinTable(name="employee_project_inner",
              joinColumns={@JoinColumn(name="employee_id",referencedColumnName="id")},
              inverseJoinColumns={@JoinColumn(name="project_id",referencedColumnName="id")})
	@ManyToMany
    private List<ProjectInfo> projects;
    //getter and setter
}
    
/*
* Project类
*/
@Entity
@Table(name="project")
public class Project{
    
    @Id
    @Column(name="id")
    private Integer id;
    
    @Column(name="name")
    private String project_name;
    
    @ManyToMany(mappedBy="projects")
    private List<Employee> employees;
    //getter and setter
}
  • 一对一
/*
* Customer类
*/
@Entity
@Table(name="customer")
public class Customer{
    
    @Id
    @Column(name="id")
    private String id;
    
    @Column(name="name")
    private String name;
    
    @JoinColumn(name="ps_id")
    @OneToOne
    private ParkingSpace parkingSpace;
    //getter and setter
}

/*
* ParkingSpace类
*/
@Entity
@Table(name="parking_space")
public class ParkingSpace{
    
    @Id
    @Column(name="id")
    private String id;
    
    @Column(name="location")
    private String location;
    
    @OneToOne(mappedBy="parkingSpace")
    private Employee employee;
}
  • 注1:on update cascade级联更新:主键表更新了id,外键表的外键随之更新;on delete cascade级联删除:主键表删除某id行,外键表删除对应外键行,建立的实体应该与数据库设计一致,至少无冲突,互补也是可以的,详细的实体设计大概是为了从代码生成数据库表,如果更喜欢使用SQL语句创建数据表的话,类似索引的信息可以不用在实体类上标注
  • 注2:使用了JPA这种实体间的关联后,每次查询主表实体或者从表实体都能查询到对应的对方的实体信息,非常简便
  • 注3:相关MySQL表
/*一对一*/
CREATE TABLE parking_space(
	id VARCHAR(32) NOT NULL,
	location VARCHAR(50) NOT NULL COMMENT '停车位置',
	PRIMARY KEY (id)
) COMMENT '停车位表'

CREATE TABLE customer(
	id VARCHAR(32) NOT NULL,
	name VARCHAR(50) NOT NULL COMMENT '顾客名字',
	ps_id VARCHAR(32) NOT NULL COMMENT '停车位id,外键',
	PRIMARY KEY (id),
	FOREIGN KEY (ps_id) REFERENCES parking_space (id) ON DELETE CASCADE ON UPDATE CASCADE
) COMMENT '顾客表'

/*多对多*/
CREATE TABLE employee(
	id VARCHAR(32) NOT NULL,
	employee_name VARCHAR(50) NOT NULL COMMENT '名字',
	PRIMARY KEY (id)
) COMMENT '雇员表'

CREATE TABLE project(
	id VARCHAR(32) NOT NULL,
	project_name VARCHAR(50) NOT NULL COMMENT '项目名称',
	PRIMARY KEY (id)
) COMMENT '项目表'

DROP TABLE employee_project_inner

CREATE TABLE employee_project_inner(
	employee_id VARCHAR(32) NOT NULL COMMENT '雇员id',
	project_id VARCHAR(32) NOT NULL COMMENT '项目id',
	PRIMARY KEY (employee_id,project_id),#联合主键
	FOREIGN KEY (employee_id) REFERENCES employee (id) ON UPDATE CASCADE ON DELETE CASCADE,#外键
	FOREIGN KEY (project_id) REFERENCES project (id) ON UPDATE CASCADE ON DELETE CASCADE,#外键
	UNIQUE KEY uqe_emp_pjt (employee_id,project_id) #复合唯一索引
) COMMENT '雇员项目关系表'
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值