🐳 Mybatis 中的 对一、对多关联

1. 数据库中实体之间的对应关系

  1. 一对一

例如:人和身份证 、一个人只能拥有一张身份证

  1. 一对多

例如: 学员拥有多本图书

  1. 多对多

例如:学员和老师 , 多对多会产生中间关系表、

2. 在mybatis中,上述三种关系分成了两大类

  1. 对一关联
  2. 对多关联

代码实现

2.1 环境搭建

1.新建数据库、四张表 (relation)

2.添加依赖 (mysql , mybatis , junit , lombok)

xml 复制代码
<dependencies>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.11</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.32</version>
    </dependency>
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-api</artifactId>
        <version>5.10.1</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.24</version>
    </dependency>
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
         <version>1.2.3</version>
    </dependency>
</dependencies>

3.新建实体类、BookBean、Card、Person、Student

java 复制代码
@Data
@NoArgsConstructor
@AllArgsConstructor
public class BookBean {
    private Integer bid ;
    private String bname ;
}

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Card {
    private Integer cid;
    private String cno;
}

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Person {
    private Integer pid ;
    private String pname ;
    private String address ;
    //对一关联:一个人拥有一张身份证
    private Card card ; 
}

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student {
    private Integer sid ;
    private String sname ;
    //一个学员拥有多本图书 : 一对多
    private List<BookBean> bookBeanList;
}

4.新建mapper接口 PersonMapper、StudentMapper

java 复制代码
public interface PersonMapper {
    //查询所有的Person信息,每一个Person仅仅是自己的简单属性信息
    List<Person> getPersonList();
    //查询所有的Person信息,每一个Person不仅包含自己的简单属性信息也包含他拥有的身份证信息
    List<Person> getPersonListWithCardInfo();
    //查询所有的Person信息,每一个Person不仅包含自己的简单属性信息也包含他拥有的身份证信息
    List<Person> getPersonListWithCardInfo2();
}

public interface StudentMapper {
    List<Student> getStudentListWithBookBeanList();
}

5.resources 目录下新建com.bottom.mybatis.mapper 目录,并新建两个mapper.xml文件

PersonMapper.xml

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="com.bottom.mybatis.mapper.PersonMapper">
    <select id="getPersonList" resultType="Person">
        select * from t_person
    </select>

    <!-- 这种方式发现person中的三个字段能成功映射,但是card仍然是null -->
    <!--
    <select id="getPersonListWithCardInfo" resultType="Person">
        select * from t_person t1 left join t_card t2 on t1.pid = t2.cid
    </select>
    -->
    <select id="getPersonListWithCardInfo" resultMap="PersonResultMap">
        select t1.* , t2.* from t_person t1 left join t_card t2 on t1.pid = t2.cid
    </select>

    <resultMap id="PersonResultMap" type="Person" autoMapping="true">
        <id property="pid" column="pid"/>
        <!-- 对一关联 -->
        <association property="card" javaType="Card" autoMapping="true">
            <id property="cid" column="cid"/>
        </association>
    </resultMap>


    <select id="getPersonListWithCardInfo2" resultType="Person">
        select t1.* , t2.cid as 'card.cid' , t2.cno as 'card.cno'
        from t_person t1 left join t_card t2 on t1.pid = t2.cid
    </select>


</mapper>

StudentMapper.xml

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="com.bottom.mybatis.mapper.StudentMapper">
    <select id="getStudentListWithBookBeanList" resultMap="StudentWithBookBeanListResultMap">
        select * from t_student t1 left join t_bookbean t2 on t1.sid = t2.stuid
    </select>

    <resultMap id="StudentWithBookBeanListResultMap" type="Student" autoMapping="true">
        <id property="sid" column="sid"/>
        <!-- 对多关联 collection -->
        <collection property="bookBeanList" ofType="BookBean" autoMapping="true">
            <id property="bid" column="bid"/>
        </collection>
    </resultMap>

</mapper>

5.在 resources 目录下新建 mybatis-config.xml、logback.xml

logback.xml

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="true">
    <appender name="STDOUT"
              class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>[%d{HH:mm:ss.SSS}] [%-5level] [%thread] [%logger] [%msg]%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <root level="DEBUG">
        <appender-ref ref="STDOUT" />
    </root>

    <logger name="com.bottom.mybatis" level="DEBUG" />

</configuration>

mybatis-config.xml

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>
    <settings>
        <setting name="logImpl" value="SLF4J"/>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
    <typeAliases>
        <package name="com.bottom.mybatis.pojo"/>
    </typeAliases>
    <environments default="dev">
        <environment id="dev">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/relation"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <package name="com.bottom.mybatis.mapper"/>
    </mappers>
</configuration>

6.测试类测试

java 复制代码
public class PersonMapperTest {
    private SqlSession sqlSession;
    private PersonMapper personMapper;
    private StudentMapper studentMapper ;

    @BeforeEach
    public void setup() throws IOException {
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
        sqlSession = sqlSessionFactory.openSession();
        personMapper = sqlSession.getMapper(PersonMapper.class);
        studentMapper = sqlSession.getMapper(StudentMapper.class);
    }

    @AfterEach
    public void teardown() throws SQLException {
        if(sqlSession!=null && !sqlSession.getConnection().isClosed()){
            sqlSession.commit();
            sqlSession.close();
        }
    }

    @Test
    public void test01(){
        personMapper.getPersonList().forEach(System.out::println);
    }

    //1.演示对一关联
    @Test
    public void test02(){
        personMapper.getPersonListWithCardInfo().forEach(System.out::println);
    }

    //2.演示对一关联的另一种解决方案
    @Test
    public void test03(){
        personMapper.getPersonListWithCardInfo2().forEach(System.out::println);
    }

    //3.演示对多关联
    @Test
    public void test04(){
        studentMapper.getStudentListWithBookBeanList().forEach(System.out::println);
    }
}

2.2 具体关系分析

2.2.1 一对一

--------------------------------------------场景模拟----------------------------------------------

一个人只能拥有一张身份证

---------------------------------------------代码实现---------------------------------------------

2.2.2 一对

--------------------------------------------场景模拟----------------------------------------------

一个学生可以拥有多本书

---------------------------------------------代码实现---------------------------------------------

2.3 总结

MyBatis 的一对一关联和一对多关联是指在数据库表之间建立的关系。下面是对它们的简单总结:

一对一关联:

  • 表示两个表之间的一对一关系,即一个表中的每行对应另一个表中的唯一一行。

  • 通常通过外键来建立关联,一个表的主键作为另一个表的外键。

  • 在 MyBatis 中,可以通过映射文件中的associationcollection元素来配置一对一关联。

一对多关联:

  • 表示一个表中的每行可以对应另一个表中的多行。

  • 常见的例子是一个主表和一个明细表之间的关系,如学生表和课程表。

  • 在 MyBatis 中,可以使用collection元素来配置一对多关联,指定关联的列和映射的对象。

通过正确配置 MyBatis 的映射文件,可以在查询和操作数据时利用这些关联关系,方便地获取相关联的数据。这样可以提高数据操作的效率和准确性。

相关推荐
guoruijun_2012_43 分钟前
fastadmin多个表crud连表操作步骤
android·java·开发语言
Hello-Brand13 分钟前
Java核心知识体系10-线程管理
java·高并发·多线程·并发·多线程模型·线程管理
乐悠小码19 分钟前
数据结构------队列(Java语言描述)
java·开发语言·数据结构·链表·队列
史努比.21 分钟前
Pod控制器
java·开发语言
2的n次方_23 分钟前
二维费用背包问题
java·算法·动态规划
皮皮林55124 分钟前
警惕!List.of() vs Arrays.asList():这些隐藏差异可能让你的代码崩溃!
java
莳光.24 分钟前
122、java的LambdaQueryWapper的条件拼接实现数据sql中and (column1 =1 or column1 is null)
java·mybatis
程序猿麦小七29 分钟前
基于springboot的景区网页设计与实现
java·spring boot·后端·旅游·景区
weisian15135 分钟前
认证鉴权框架SpringSecurity-2--重点组件和过滤器链篇
java·安全
蓝田~37 分钟前
SpringBoot-自定义注解,拦截器
java·spring boot·后端