1 概述
在管理系统中,实体之间的关系从来都是复杂的。常见的有一对一,一对多,多对多等关系,这些关系组成了复杂的实体关系,得以完成现实中复杂的需求。
Spring Data JPA基于功能强大JPA规范,实现这些实体关系豪不费力。
2 实体关系
有两个实体,学校和地址,一个学校对应一个地址。它们的关系如上图。
在实体类中代码如下:
School.java
package com.wangshenghua.entity;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
@Entity
public class School {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String name;
@OneToOne(cascade = CascadeType.ALL) //级联操作
@JoinColumn(name = "address_id") // 定义外键列
private Address address;
public School() {}
public School(String name, Address address) {
this.name = name;
this.address = address;
}
// Getter and Setter
}
@OneToOne表示一对一关系,即一个学校对应一个地址。参数cascade 表示级联关系。级联关系有以下6类。
级联关系 说明
CascadeType.PERSIST 级联新增。 当School实体保存时, Address中实体也会保存。
CascadeType.REMOVE 级联删除操作。删除当前实体时,与它有映射关系的实体也会跟着被删除。
CascadeType.MERGE 级联更新(合并)操作。当School中的数据改变,会相应地更新Address中的数据。
CascadeType.DETACH 级联脱管/游离操作。
CascadeType.REFRESH 级联刷新操作。刷新 School 实体时,也会刷新 Address 实体。
CascadeType.ALL 拥有以上所有级联操作权限。
@JoinColumn表示指向一个外键,这里是 Address 实体的主键,即 School 实体中的address_id外键。
Address.java
package com.wangshenghua.entity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToOne;
@Entity
public class Address {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String street;
private String zipCode;
@OneToOne(mappedBy = "address")
private School School;
public Address() {}
// Getter and Setter
}
参数mappedBy指向反向关系。一个学校对应一个地址,反过来,一个地址对应一个学校,mappedBy的值必为本类在另一方的属性名。
3 数据访问接口
以上两个实体的Spring Data JPA接口。
SchoolRepository.java
package com.wangshenghua.dao;
import org.springframework.data.jpa.repository.JpaRepository;
import com.wangshenghua.entity.School;
public interface SchoolRepository extends JpaRepository<School, Integer> {
}
AddressRepository.java
package com.wangshenghua.dao;
import org.springframework.data.jpa.repository.JpaRepository;
import com.wangshenghua.entity.Address;
public interface AddressRepository extends JpaRepository<Address, Integer> {
}
4 数据库连接配置
application.properties
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://192.168.237.131:3306/testdb?useUnicode=true&characterEncoding=UTF-8
spring.datasource.username=testdb
spring.datasource.password=testdb
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.hibernate.ddl-auto = update
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type=TRACE
数据库使用MySQL 5.1.73,在Spring boot工程的pom.xml依赖mysql-connector-java要换成低版本的,高版本的会报错。
package com.wangshenghua.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import com.wangshenghua.dao.AddressRepository;
import com.wangshenghua.dao.SchoolRepository;
import com.wangshenghua.entity.Address;
import com.wangshenghua.entity.School;
@SpringBootApplication
@EnableJpaRepositories(basePackages = “com.wangshenghua.dao”)
@EntityScan(basePackages = “com.wangshenghua.entity”)
public class HibernateOneToOneMappingApplication implements CommandLineRunner{
@Autowired
private SchoolRepository schoolRepository;
@Autowired
private AddressRepository addressRepository;
public static void main(String[] args) {
SpringApplication.run(HibernateOneToOneMappingApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
// 清除表
schoolRepository.deleteAllInBatch();
addressRepository.deleteAllInBatch();
// 建立数据
Address address = new Address();
address.setStreet("郴州市南岭大道385号");
address.setZipCode("423000");
School school = new School("湘南IT",address);
schoolRepository.save(school);
}
}
6 总结
JPA关系比较多,操作起来工作量也比大,学习时需要有耐心。Java体系庞大,若版本不在近一两年的框架搭配,可能会出现问题,排除这些问题不仅要基础知识扎实,还要细心。
本节课程源码已经上传到github,可以前往下载