一对一映射

一对一指关系数据库中第一个表中的单个行只可以与第二个表中的一个行相关,且第二个表中的一个行也只可以与第一个表中的一个行相关。

下面将通过用户和用户身份证号码为例,介绍一对一关系。

表结构设计

通常,在一对一关系中,需要在主表的一方添加一个外键关联附表。如下图:

对象设计

(1)用户表对应的 User 实体,代码如下:

@Data
@Entity
@Table
public class User {
    @Id
    @GeneratedValue
    private int id;

    @Column
    private String name;

    // 这里是关键
    @OneToOne
    private IdNumber idNumber;
}

(2)用户身份证表对应的 IdNumber 实体,代码如下:

@Data
@Entity
@Table
public class IdNumber {
    @Id
    @GeneratedValue
    private int id;

    @Column
    private String number;
}

从上面代码可以看到,在表结构方面,我们应该是在 user(用户)表中添加外键列来维护用户的身份证号码。在对象设计方面,在 User 对象中关联 IdNumber 对象,来封装当前用户的身份证号码。

示例代码

(1)persistence.xml 配置

<persistence xmlns="http://java.sun.com/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0">
    <persistence-unit name="demo_onetoone" transaction-type="RESOURCE_LOCAL">
        <!-- JPA提供者 -->
        <provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
        <!-- 声明实体类 -->
        <class>com.hxstrive.openjpa.annotation.demo_onetoone.User</class>
        <class>com.hxstrive.openjpa.annotation.demo_onetoone.IdNumber</class>
        <!-- 配置JPA数据库属性 -->
        <properties>
            <property name="openjpa.ConnectionURL"
                      value="jdbc:mysql://localhost:3306/openjpa_learn?useSSL=false&amp;
					  serverTimezone=UTC&amp;useUnicode=true&amp;characterEncoding=UTF-8"/>
            <property name="openjpa.ConnectionDriverName" value="com.mysql.jdbc.Driver"/>
            <property name="openjpa.ConnectionUserName" value="root"/>
            <property name="openjpa.ConnectionPassword" value="aaaaaa"/>
            <property name="openjpa.Log" value="SQL=TRACE"/>
            <!-- 自动生成表 -->
            <property name="openjpa.jdbc.SynchronizeMappings"
                      value="buildSchema(ForeignKeys=true)"/>
            <!-- 不使用加载时强化和编译时强化,使用运行时Unenhanced(不能发挥OpenJPA的最大效能,所以也不推荐) -->
            <property name="openjpa.ClassLoadEnhancement" value="false"/>
            <property name="openjpa.DynamicEnhancementAgent" value="false"/>
            <property name="openjpa.RuntimeUnenhancedClasses" value="supported"/>
        </properties>
    </persistence-unit>
</persistence>

(2)User 用户实体

@Data
@Entity
@Table
public class User {
    @Id
    @GeneratedValue
    private int id;

    @Column
    private String name;

    @OneToOne
    private IdNumber idNumber;
}

(3)IdNumber 身份证实体

@Data
@Entity
@Table
public class IdNumber {
    @Id
    @GeneratedValue
    private int id;

    @Column
    private String number;
}

(4)客户端代码

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

public class Demo {
    /** 持久化单元名称 */
    private static final String NAME = "demo_onetoone";

    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory(NAME);
        EntityManager em = emf.createEntityManager();
        em.getTransaction().begin();

        // 身份证号码
        IdNumber idNumber = new IdNumber();
        idNumber.setNumber("身份证号码1");

        // 用户
        User user = new User();
        user.setName("用户1");
        user.setIdNumber(idNumber);

        em.persist(idNumber);
        em.persist(user);

        em.getTransaction().commit();
        em.close();
        emf.close();
        System.out.println("finished.");
    }

}

运行输出 SQL 日志如下:

INSERT INTO IdNumber (id, number) VALUES (?, ?) [params=?, ?]
INSERT INTO User (id, name, IDNUMBER_ID) VALUES (?, ?, ?) [params=?, ?, ?]

数据表数据如下图:

说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
公众号