Mybatis学习记录(2)级联操作

Mybatis学习(2)级联操作

级联操作 一对多

例,查询学生类时带出班级类

1. 创建数据表

首先,数据表结构

学生表,主键为id,外键为grand,与班级表t_classes 的id绑定。
在这里插入图片描述
班级表,主键为id
在这里插入图片描述

2. 确定查询SQL代码

查询 t_student s、t_classes 两个表,条件为 t_student 表的 id=2的数据

select * from t_student s ,t_classes c  where s.id= 2;

查询结果
在这里插入图片描述
会出现这样的查询结果是因为:
因为只指定了 s.id = 2在执行上述语句时,Mysql会查询表 t_student 中符合条件: id = 2的数据,并与 t_classes 所有数据组合在一起,返回给用户。

若要查询 t_student 中 id=2 的数据,和他 t_classes 表中的班级应当使用:

select * from t_student s ,t_classes c  where s.id= 2 and s.grand =c.id;

查询结果如下,其查询原则为:查询 t_student 中符合条件: id = 2的数据,并与 t_classes 符合 s.grand =c.id 所有数据组合在一起,返回给用户。
在这里插入图片描述
进一步的,由于 grand 和c.id的数据是我们所不需要的,所以我们可以使用下述代码:

select  s.id , s.studentname , c. classname  from t_student s ,t_classes c  where s.id= 2  and s.grand =c.id;

其查询结果如下
在这里插入图片描述

3. 在MyBatis中使用
1 创建与数据表对应的实体类

班级类

@Data
public class Classes {
    private  int id;
    private String classname;
    private List< Student> students;
}

学生类

@Data
public class Student {
    private  int id;
    private String studentname;
    private Classes classes;
}
2 创建方法接口

定义findById(int id) 方法,名称要和配置文件中一致

public interface StudentRepository {
    public Student findById( int id);
}
3 配置xml文件 重点

< id> <> 设置主键
column 列名 跟结果集里的列名映射
property 属性 要把id映射给 实体类的哪个属性

<?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.zi.repository.StudentRepository">

    <resultMap id="studentMap" type="com.zi.entity.Student">
    <id column="id" property="id"></id>  <!-- <id> <>  设置主键    column 列名 跟结果集里的列名映射  property 属性 要把id映射给 实体类的哪个属性-->
    <result column="name" property="name"></result>  <!--其他字段用  <result><>    -->
        <association property="classes" javaType="com.zi.entity.Classes">
            <id column="cid" property="id" ></id>
            <result column="cname" property="classname"></result>
        </association>
    </resultMap>

    <select id="findById" parameterType="int" resultMap="studentMap">
            select s.id , s.studentname  , c.id as cid , c.classname as cname from t_student s,t_classes c
            where s.id = #{id} /*and s.studentname = c.id*/
    </select>

</mapper>
4 在全局配置文件中注册xml文件

在全局配置文件中,注册

  <mapper resource="com/zi/repository/StudentRepository.xml"></mapper>
5 Java语句调用
InputStream inputStream = test2.class.getClassLoader().getResourceAsStream("MyBatisConfig");
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new  SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory =  sqlSessionFactoryBuilder.build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
//获取实现接⼝的代理对象

StudentRepository accountRepository = sqlSession.getMapper(StudentRepository.class);
Student student =  accountRepository.findById(2);
System.out.println(student);
通过班级带出学生

和通过学生带出班级相比,在配置xml文件上有区别,因为学生通常不止一个,所以在类中,是通过Student类型的集合来定义班级的学生属性的

  private List< Student> students; 

因此,将上面的 < association>标签换为< collection>标签ofType 中填集合中数据类型,即在此处为Student类型的全类名

 <collection property="students" ofType="com.zi.entity.Student">
        <id column="sid" property="id" ></id>
        <result column="sname" property="studentname"></result>
    </collection>

下面是完整的配置XML文件内容
<?xml version="1.0" encoding="UTF-8" ?>

<mapper namespace="com.zi.repository.ClassesRepository">

<resultMap id="classMap" type="com.zi.entity.Classes">
<id column="id" property="id"></id>  <!-- <id> <>  设置主键    column 列名 跟结果集里的列名映射  property 属性 要把id映射给 实体类的哪个属性-->
<result column="classname" property="classname"></result>  <!--其他字段用  <result><>    -->
    <collection property="students" ofType="com.zi.entity.Student">
        <id column="sid" property="id" ></id>
        <result column="sname" property="studentname"></result>
    </collection>
</resultMap>

<select id="findById" parameterType="int" resultMap="classMap">
        select c.id , c.classname , s.id as sid , s.studentname as sname from t_student s,t_classes c
        where c.id = #{id} and c.id = s.grand
</select>

级联操作 多对多 客户和商品

一些说明

结果集和类映射
根据Mysql查找到的结果集,按照从左往右的顺序,依次查找对应实体类中的字段,若有则赋值,没有则不赋值。

as的使用,将结果集的列名返回为as 后的字段

select s.id , s.studentname  , c.id as cid,  c.classname as cname from t_student s,t_classes c
where s.id = 2;

Student(id=2, studentname=null, classes=Classes(id=4, classname=9班, students=null))

1. 在数据库创建对应数据表,并设置外键约束

##创建 Goods Customers 用户-商品对照 数据表

CREATE TABLE t_customers(
                          `id` INT  PRIMARY KEY,
                          `customername` VARCHAR(100) NOT NULL
)ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE t_goods(
                            `id` INT  PRIMARY KEY,
                            `goodname` VARCHAR(100) NOT NULL
)ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE t_cg(
                            `id` INT  PRIMARY KEY,
                            `cid` int  NOT NULL,
                            `gid` int  NOT NULL
)ENGINE=InnoDB DEFAULT CHARSET=utf8;

##添加外键

ALTER TABLE t_cg
    ADD CONSTRAINT fk_tb_dept2
        FOREIGN KEY(cid)
            REFERENCES t_customers(id);

ALTER TABLE t_cg
    ADD CONSTRAINT fk_tb_dept3
        FOREIGN KEY(gid)
            REFERENCES t_goods(id);
2. 创建对应实体类

商品类

public class Good {
    private  int id ;
    private String goodname;
    private List<Customer> customers;
}

用户类

public class Customer {
    private  int id ;
    private String customername;
    private List<Good> goods;
}
3. 创建方法接口
public interface CustomerRepository {
    public Customer findById(int id);
}
4. 配置xml文件

在写配置文件前,需要理清楚SQL语句的关系
在数据库中,我要执行以下语句:

select  c.id ,c.customername,g.goodname  from t_customers c ,t_goods g,t_cg cg where c.id =2 and  c.id = cg.cid and g.id =cg.gid  ;

返回以下结果集:
在这里插入图片描述
开始写配置文件

	<?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.zi.repository.CustomerRepository">

    <resultMap id="customerMap" type="com.zi.entity.Customer">
    <id column="id" property="id"></id>  <!-- <id> <>  设置主键    column 列名 跟结果集里的列名映射  property 属性 要把id映射给 实体类的哪个属性-->
    <result column="customername" property="customername"></result>  <!--其他字段用  <result><>    -->
        <collection property="goods" ofType="com.zi.entity.Good">
            <id column="gid" property="id" ></id>
            <result column="goodname" property="goodname"></result>
        </collection>
    </resultMap>

    <select id="findById" parameterType="int" resultMap="customerMap">
        select  c.id ,c.customername,g.goodname ,g.id as gid from t_customers c ,t_goods g,t_cg cg
         where  c.id =2 and  c.id = cg.cid and g.id =cg.gid;
    </select>

</mapper>
5. 在全局配置文件中注入关联
    <mapper resource="com/zi/repository/CustomerRepository.xml"></mapper>
6. 在JAVA语句中使用
InputStream inputStream = test2.class.getClassLoader().getResourceAsStream("MyBatisConfig");
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new  SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory =  sqlSessionFactoryBuilder.build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
CustomerRepository accountRepository3 = sqlSession.getMapper(CustomerRepository.class);
System.out.println(accountRepository3.findById(2));
出现读取不到对象数据的现象

原因是,我在创建实体类时,没有添加@Data,即没有构造函数,导致只声明了类,而没有构造它。

在这里插入图片描述

文件结构

下面是我的文件夹结构

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值