一对一模型概述

在数据库设计中,1对1模型(One-to-One Relationship)是一种实体关系,用于表示两张表之间一条记录只能关联另一张表中的一条记录的关系。

1对1关系的特点

  • 唯一性:表A中的每一行记录只能与表B中的一行记录关联,反之亦然
  • 严格的映射:两张表的数据关系是一一对应的
  • 逻辑层面:通常用于将一个实体的不同属性分离存储

常见的应用场景

  • 数据拆分:将经常访问的字段和不经常访问的字段分离,以优化性能
  • 权限控制:存储用户及其角色权限配置
  • 扩展功能:将主表的扩展数据存储到另一张表

优点分析

  • 模块化设计:将数据分成不同表,便于维护和管理
  • 安全性提升:敏感信息可以单独存储
  • 性能优化:分表存储减少单表数据量

缺点分析

  • 查询复杂性增加:需要进行表的连接查询(JOIN)
  • 维护难度加大:需要严格设计和维护表之间的关系
  • 事务管理成本:跨表操作需要在事务中处理

查询模型

用户表和订单表的关系为:一个用户有多个订单,一个订单只从属于一个用户。查询一个订单,同时查询出该订单的所属用户。


创建表

CREATE TABLE `wzk_orders` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `ordertime` varchar(255) DEFAULT NULL,
  `total` double DEFAULT NULL,
  `uid` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;

CREATE TABLE `wzk_user` (
  `id` int(11) NOT NULL,
  `username` varchar(255) DEFAULT NULL,
  `password` varchar(255) DEFAULT NULL,
  `birthday` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;

查询语句

select * from wzk_orders o, wzk_user u where o.uid=u.id

Java 类定义

WzkOrder.java

@Data
@AllArgsConstructor
@NoArgsConstructor
public class WzkOrder {
    private int id;
    private Date ordertime;
    private double total;
    private WzkUser user;
}

WzkUser.java

@Data
@AllArgsConstructor
@NoArgsConstructor
public class WzkUser {
    private int id;
    private String username;
    private String password;
    private Date birthday;
}

Mapper 接口与 XML

OrderMapper.java

public interface OrderMapper {
    List<WzkOrder> findAll();
}

OrderMapper.xml

写法一:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="icu.wzk.mapper.OrderMapper">
    <!-- 写法一 -->
    <resultMap id="orderMap" type="icu.wzk.model.WzkOrder">
        <result column="uid" property="user.id"></result>
        <result column="username" property="user.username"></result>
        <result column="password" property="user.password"></result>
        <result column="birthday" property="user.birthday"></result>
    </resultMap>

    <select id="findAll" resultMap="orderMap">
        select * from wzk_orders o, wzk_user u where o.uid=u.id
    </select>
</mapper>

写法二(使用 association):

<!-- 写法二 -->
<resultMap id="orderMap" type="icu.wzk.model.WzkOrder">
    <result property="id" column="id"></result>
    <result property="ordertime" column="ordertime"></result>
    <result property="total" column="total"></result>
    <association property="user" javaType="icu.wzk.model.WzkUser">
        <result column="uid" property="id"></result>
        <result column="username" property="username"></result>
        <result column="password" property="password"></result>
        <result column="birthday" property="birthday"></result>
    </association>
</resultMap>

SqlMapConfig.xml 配置

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <properties>
        <property name="driverClass" value="com.mysql.cj.jdbc.Driver"/>
        <property name="jdbcUrl" value="jdbc:mysql://172.16.1.130:3306/wzk-mybatis?characterEncoding=utf-8"/>
        <property name="user" value="hive"/>
        <property name="password" value="hive@wzk.icu"/>
    </properties>

    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driverClass}"/>
                <property name="url" value="${jdbcUrl}"/>
                <property name="username" value="${user}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper resource="mapper.xml"/>
        <!-- 新增的 OrderMapper -->
        <mapper resource="OrderMapper.xml"/>
    </mappers>
</configuration>

测试代码

public class WzkIcu08 {
    public static void main(String[] args) throws IOException {
        InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
                .build(resourceAsStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        OrderMapper orderMapper = sqlSession.getMapper(OrderMapper.class);
        List<WzkOrder> dataList = orderMapper.findAll();
        dataList.forEach(System.out::println);
        sqlSession.close();
    }
}

运行结果

WzkOrder(id=1, ordertime=Mon Nov 11 00:00:00 CST 2024, total=100.0, user=WzkUser(id=1, username=wzk, password=icu, birthday=Mon Nov 11 00:00:00 CST 2024))
WzkOrder(id=2, ordertime=Mon Nov 11 00:00:00 CST 2024, total=200.0, user=WzkUser(id=1, username=wzk, password=icu, birthday=Mon Nov 11 00:00:00 CST 2024))
WzkOrder(id=3, ordertime=Sun Nov 10 00:00:00 CST 2024, total=150.0, user=WzkUser(id=2, username=wzk2, password=icu2, birthday=Mon Nov 11 00:00:00 CST 2024))

注意事项

  • 数据一致性:必须确保表A和表B之间的引用完整性,避免孤立记录
  • 索引设计:为外键列创建索引,以提升连接查询性能
  • 场景适配:如果没有明显的1对1关系需求,建议尽量避免使用,以简化设计