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

 


https://docs.jboss.org/hibernate/orm/current/introduction/html_single/Hibernate_Introduction.html#one-to-one-fk

https://docs.jboss.org/hibernate/orm/current/userguide/html_single/Hibernate_User_Guide.html#associations-one-to-one

posted @ 2019-02-12 12:01  江湖小小白  阅读(2323)  评论(0编辑  收藏  举报