JPA 一对一 @OneToOne
手机数量和手机详情分开存
@Entity public class Phone { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) Long id; String number; @OneToOne // Phone 表会添加 details_id 字段 PhoneDetails details; } @Entity public class PhoneDetails { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) Long id; String provider; String technology; }
结果
[Hibernate] create table Phone ( id bigint not null auto_increment, number varchar(255), details_id bigint, primary key (id) ) engine=InnoDB [Hibernate] create table PhoneDetails ( id bigint not null auto_increment, provider varchar(255), technology varchar(255), primary key (id) ) engine=InnoDB [Hibernate] alter table Phone drop index UK_gs46ghbb2k3ly6c5xk1g4e29k [Hibernate] alter table Phone add constraint UK_gs46ghbb2k3ly6c5xk1g4e29k unique (details_id) [Hibernate] alter table Phone add constraint FKnoj7cj83ppfqbnvqqa5kolub7 foreign key (details_id) references PhoneDetails (id)
使用 @OneToOne 双向关联
@Entity public class Phone { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) Long id; String number; @OneToOne // Phone 表会添加 details_id 字段 PhoneDetails details; } @Entity public class PhoneDetails { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) Long id; String provider; String technology; @OneToOne(mappedBy = "details") // 需要 mappedBy 属性,不然就变成两个单向一对一 Phone phone; }
结果
[Hibernate] create table Phone ( id bigint not null auto_increment, number varchar(255), details_id bigint, primary key (id) ) engine=InnoDB [Hibernate] create table PhoneDetails ( id bigint not null auto_increment, provider varchar(255), technology varchar(255), primary key (id) ) engine=InnoDB [Hibernate] alter table Phone drop index UK_gs46ghbb2k3ly6c5xk1g4e29k [Hibernate] alter table Phone add constraint UK_gs46ghbb2k3ly6c5xk1g4e29k unique (details_id) [Hibernate] alter table Phone add constraint FKnoj7cj83ppfqbnvqqa5kolub7 foreign key (details_id) references PhoneDetails (id)
使用 @JoinColumn 手动设置关联信息
@Entity public class Phone { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) Long id; String number; @OneToOne @JoinColumn(name = "details_id", referencedColumnName = "id", foreignKey = @ForeignKey(name = "PhoneDetails_ID_FK") ) // Phone 表会增加 details_id 字段与 Phone 表 id(不写默认主键) 关联 PhoneDetails details; } @Entity public class PhoneDetails { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) Long id; String provider; String technology; }
结果
[Hibernate] create table Phone ( id bigint not null auto_increment, number varchar(255), details_id bigint, primary key (id) ) engine=InnoDB [Hibernate] create table PhoneDetails ( id bigint not null auto_increment, provider varchar(255), technology varchar(255), primary key (id) ) engine=InnoDB [Hibernate] alter table Phone drop index UK_gs46ghbb2k3ly6c5xk1g4e29k [Hibernate] alter table Phone add constraint UK_gs46ghbb2k3ly6c5xk1g4e29k unique (details_id) [Hibernate] alter table Phone add constraint PhoneDetails_ID_FK foreign key (details_id) references PhoneDetails (id)
测试
src/main/resources/META-INF/persistence.xml
<persistence xmlns="https://jakarta.ee/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence https://jakarta.ee/xml/ns/persistence/persistence_3_0.xsd" version="3.0"> <persistence-unit name="persistenceUnitName"> <properties><!-- org.hibernate.cfg.JdbcSettings --> <property name="jakarta.persistence.jdbc.user" value="root"/> <property name="jakarta.persistence.jdbc.password" value="root"/> <property name="jakarta.persistence.jdbc.url" value="jdbc:mysql://127.0.0.1:3306/jpa"/> <property name="jakarta.persistence.jdbc.driver" value="com.mysql.cj.jdbc.Driver"/> <property name="hibernate.show_sql" value="true"/> <property name="hibernate.format_sql" value="true"/> <property name="hibernate.highlight_sql" value="true"/> <property name="hibernate.hbm2ddl.auto" value="update"/> </properties> </persistence-unit> </persistence>
Main
Persistence.createEntityManagerFactory("persistenceUnitName"); // 双向 1-1 的关联关系, 建议先保存不维护关联关系的一方, 即没有外键的一方, 这样不会多出 UPDATE 语句 // 查询获取维护关联关系的一方, 默认情况下, 获取维护关联关系的一方, 会通过左外连接获取其关联的对象,非懒加载模式, 可以通过 @OntToOne 的 fetch 属性来修改加载策略 // 查询获取不维护关联关系的一方, 默认情况下, 获取不维护关联关系的一方, 是通过左外连接获取其关联的对象 // 可以通过 @OneToOne 的 fetch 属性来修改加载策略. 但依然会再发送 SQL 语句来初始化其关联的对象, 这说明在不维护关联关系的一方, 不建议修改 fetch 属性
基于主键映射 @PrimaryKeyJoinColumn