Spring 一对一

mac2025-08-09  11

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要换成低版本的,高版本的会报错。

mysql mysql-connector-java 5.1.38 5 驱动类 将驱动类和入口main函数写在一同一个类中,让 入口main函数所在类实例接口org.springframework.boot.CommandLineRunner可以让学员专注于JPA技术学习。

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,可以前往下载

最新回复(0)