MyBatis(2)

第一节 复习

初识mybatis
使用步骤 :
(1)导入jar包(11个 1个核心,9个依赖,1个数据库)
(2)准备文件(数据库的属性文件,log4j的属性文件) 【位置位于src下】
(3)编写xml文件
(4)编写实体类 (对应的是数据库中的表)
(5)编写mapper.xml文件
(6)关联
(7)测试
在这里插入图片描述
出现问题的原因:字段名称与属性名称不一致,导致mybatis的自动映射失败
解决方案:使用手动映射, 修 改mapper.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="abc.a">
    <select id="query" resultMap="rm">
        select * from dept
    </select>
    <resultMap id="rm" type="dept">
        <!--开始字段与属性的手动映射-->
        <!---主键列使用id-->
        <id column="deptno" property="deptNo"></id>
        <!--普通列使用result-->
        <result column="dname" property="deptName"></result>
        <result column="loc" property="deptLoc"></result>
    </resultMap>
</mapper>

需要在mybatis中再添加上这个mapper标签,这里省略。

package com.bjsxt.test;
import com.bjsxt.entity.Dept;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;

/**
 *测试类
 */
public class Test {
    public static void main(String[] args) throws IOException {
        InputStream inputStream = Resources.getResourceAsStream("mybatis.xml");
        SqlSessionFactory build = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession sqlSession = build.openSession();
        List<Dept> list = sqlSession.selectList("abc.a.query");
        System.out.println(list);
        sqlSession.close();
    }
}

第二节 Mybatis中的代理

为什么需要使用mybatis的动态代理
因为有利于程序的扩展和维护
在这里插入图片描述
mybatis使用动态代理的步骤
(1)编写实体类
(2)编写接口

package com.bjsxt.mapper;
import com.bjsxt.entity.Dept2;
import java.util.List;
public interface Dept2Mapper {
    public List<Dept2> queryAll();
    public Dept2 selectByNo(int deptNo);
    public int insertDept2(Dept2 dept2);
}

(3)编写mapper.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.bjsxt.mapper.Dept2Mapper"> <!---接口如何与xml关联,就是xml的命名空间为接口的全路径-->
    <select id="queryAll" resultType="dept2">  <!--id的值为接口中方法的名称-->
        select * from dept
    </select>
    <select id="selectByNo" resultType="dept2">
        select * from dept where deptNo=#{0}  <!--这里面的0可以换成a、para 亲测>
    </select>
    <insert id="insertDept2">
        insert into dept values (#{deptNo},#{dname},#{loc})
    </insert>
</mapper>

(4)关联

(5)测试类

package com.bjsxt.test;
import com.bjsxt.entity.Dept;
import com.bjsxt.entity.Dept2;
import com.bjsxt.mapper.Dept2Mapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class Test2 {
    public static void main(String[] args) throws IOException {
        //(1)解析
        InputStream resourceAsStream = Resources.getResourceAsStream("mybatis.xml");
        //(2)
        SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resourceAsStream);
        //(3)
        SqlSession sqlSession = build.openSession();
       //(4) 多态,接口   "new 实现类() "  使用反射
           //  = 的左侧为接口类型 ,   =右侧, 实际为接口的实现类,
        Dept2Mapper mapper = sqlSession.getMapper(Dept2Mapper.class);
         //对象名.方法名
        List<Dept2> dept2s = mapper.queryAll();
        System.out.println(dept2s);
        System.out.println("------------------------------------");
        Dept2 dept2 = mapper.selectByNo(20);
        System.out.println(dept2);
        System.out.println("-----------------------------");
        int i = mapper.insertDept2(new Dept2(50, "fda", "fdsa"));
        System.out.println(i);
        sqlSession.commit();
        //(5)
        sqlSession.close();
    }
}

第三节 多表查询

一、业务方式

(1)一对一关系 一个员工只能在一个部门
需求: 查询员工及员工所在部门的信息
SQL语句
a)select * from emp ; -->查询出所有员工信息
b)select * from dept where deptno=?

 业务代码实现
       a)查询出所有的员工存放到集合中      public List<Emp> queryAll(){}
       b)遍历集合,可以得到每个员工的部门编号
       c)根据部门编号查询对应的部门信息    public Dept queryByNo(int deptNo)
       d)Emp的实体中增加Dept类型的属性,用于存储对应的员工的部门信息   

在这里插入图片描述
(1)查询所有的员工信息

package com.bjsxt.mapper;
import com.bjsxt.entity.Emp;
import java.util.List;
public interface EmpMapper {
    public List<Emp> queryAll();
}
<?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.bjsxt.mapper.EmpMapper">
    <select id="queryAll" resultType="emp">
        select * from emp
    </select>
</mapper>

(2)根据部门编号查询部门信息

package com.bjsxt.mapper;
import com.bjsxt.entity.Dept;
public interface DeptMapper {
    public Dept selectByNo(int deptNo);
}

<?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.bjsxt.mapper.DeptMapper">
    <select id="selectByNo" resultType="dept">
         select  * from dept where deptno=#{0}
    </select>
</mapper>

(3)测试,使用java代码进行“组合”

package com.bjsxt.test;
import com.bjsxt.entity.Dept;
import com.bjsxt.entity.Emp;
import com.bjsxt.mapper.DeptMapper;
import com.bjsxt.mapper.EmpMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class TestOne {
    public static void main(String[] args) throws IOException {
        //(1)解析xml
        InputStream inputStream = Resources.getResourceAsStream("mybatis.xml");
        //(2)获取工厂对象
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
        //(3)获取session对象
        SqlSession sqlSession = factory.openSession();
        //(4)业务的方法实现一对一的查询,使用java代码去组织,实现表连查的效果
        EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);

        DeptMapper deptMapper = sqlSession.getMapper(DeptMapper.class);

        List<Emp> list = mapper.queryAll(); // 查询出所有的员工信息

        for(Emp emp:list){
             //获取每个员工的部门编号
            int deptNo = emp.getDeptNo();
            //调用根据编号查询部门信息的方法
            Dept dept = deptMapper.selectByNo(deptNo);
            //将查询到的部门信息使用set方法为Emp中的dept属性赋值
            emp.setDept(dept);
        }
        System.out.println("---------------遍历每一个员工及部门信息---------------------");
        System.out.println(list.size());
        for(Emp emp:list){
            System.out.println(emp);
        }
        //(5)关闭
        sqlSession.close();
    }
}

(2)一对多的关系 一个部门(有)对应多个员工

SQL语句  : select * from dept   查询所有部门           public List<Dept> selectAll()
         select * from emp where deptno=?      public List<Emp> selectByNo(int deptNo);

业务代码 :
a) 查询出所有的部门信息,放到集合里
b)遍历集合得到每个部门编号
c)在员工表中根据部门编号查询
d)在Dept类中增加List类型的属性,用于存储部门所对应的员工信息
在这里插入图片描述

public interface DeptMapper {
    public List<Dept> selectAll();
}

<select id="selectAll" resultType="dept">
        select * from dept
    </select>
public interface EmpMapper {
    public List<Emp> selectByNo(int deptNo);
}
<select id="selectByNo" resultType="emp">
        select * from emp where deptno=#{0}
    </select>

测试

package com.bjsxt.test;
import com.bjsxt.entity.Dept;
import com.bjsxt.entity.Emp;
import com.bjsxt.mapper.DeptMapper;
import com.bjsxt.mapper.EmpMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class TestOneMore {
    public static void main(String[] args) throws IOException {
        //(1)解析xml
        InputStream inputStream = Resources.getResourceAsStream("mybatis.xml");
        //(2)获取工厂对象
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
        //(3)获取session对象
        SqlSession sqlSession = factory.openSession();
        //(4)业务的方法实现一对一的查询,使用java代码去组织,实现表连查的效果
        EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
        DeptMapper deptMapper = sqlSession.getMapper(DeptMapper.class);
        List<Dept> list = deptMapper.selectAll();//查询所有的部门信息
        //遍历部门
        for(Dept dept:list){
            int deptNo = dept.getDeptNo();
            //根据部门编号查询员工信息
            List<Emp> list1 = mapper.selectByNo(deptNo);
            //将员工信息添加到Dept类中的List<Emp>类型的属性
            dept.setEmpList(list1);
        }
        System.out.println("------------遍历list集合----------------");
        for(Dept dept:list){
            System.out.println(dept);
        }
        //(5)关闭
        sqlSession.close();
    }
}

业务方式实现多表查询的效果,实际上底层是两 个单表的查询,使用java代码,"组织"成多表查询的效果

二、N+1方式

业务方式:实际上是两个单表的查询,使用java进行“组合”成两表连查的效果
优点:简单,容易理解
缺点:书写的代码比较麻烦

业务方式的缺点可以使用N+1解决

N +1 :N +1是指执行的sql语句的条数是N+1条,底层也是两个单表的查询,是使用"xml"文件进行配置来实现的
(1)一对一 :一个员工对应一个部门
需求:查询所有员工及员工所对应的部门信息
sql: select * from emp ;
select * from dept where deptno=?
配置XML文件,mapper.xml文件
使用一个名称为标签来实现

EmpMapper接口

public List<Emp>queryAllN();

DeptMapper接口

 public Dept selectByNoN(int deptNo);

xml文件
DeptMapper.xml

<select id="selectByNoN" resultType="dept">
        select  * from dept where deptno=#{0}
    </select>

EmpMapper.xml

<select id="queryAllN" resultMap="rm">
        select  * from emp
    </select>
    <resultMap id="rm" type="emp">
        <!---emp表中的id,和result-->
        <id column="empno" property="empNo"></id>
        <result column="ename" property="ename"></result>
        <result column="job" property="job"></result>
        <!--需要执行哪个sql语句了 一对一-->
        <association property="dept" select="com.bjsxt.mapper.DeptMapper.selectByNoN"
        javaType="dept" column="deptno"></association>
    </resultMap>
package com.bjsxt.test;
import com.bjsxt.entity.Dept;
import com.bjsxt.entity.Emp;
import com.bjsxt.mapper.DeptMapper;
import com.bjsxt.mapper.EmpMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class TestOneN {
    public static void main(String[] args) throws IOException {
        //(1)解析xml
        InputStream inputStream = Resources.getResourceAsStream("mybatis.xml");
        //(2)获取工厂对象
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
        //(3)获取session对象
        SqlSession sqlSession = factory.openSession();
        //(4)业务的方法实现一对一的查询,使用java代码去组织,实现表连查的效果
        EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
        List<Emp> list = mapper.queryAllN();
        for(Emp emp:list){
            System.out.println(emp);
        }
        //(5)关闭
        sqlSession.close();
    }
}

需要使用标签
association标签的常用的4个属性
a)select : 指明要”调用“sql语句
举例select=“com.bjsxt.mapper.DeptMapper.selectByNoN”
属性值 ;要执行的sql语句所在xml文件的命名空间+select标签的id值
b)javaType: select 查询语句的返回值的类型 selectByNoN查询的返回值类型
c)property: select 查询结果存储在Emp这个类的哪个属性里
d)column: 根据表中的哪个列查询

(1)一对多 :一个部门对应多个员工
SQL : select * from dept
select * from emp where deptno=?
N+1方法:配置mapper.xml文件

EmpMapper接口

 public List<Emp> selectByNoN(int deptNo);

DeptMapper接口

public List<Dept> selectAllN();

EmpMapper.xml

<select id="selectByNoN" resultType="emp">
        select * from emp where deptno=#{0}
    </select>

DeptMapper.xml

 <select id="selectAllN" resultMap="rm">
        select * from dept
    </select>
    <resultMap id="rm" type="dept">
        <!---dept表的主键列和其它列-->
        <id column="deptno" property="deptNo"></id>
        <result column="dname" property="dname"></result>
        <result column="loc" property="loc"></result>
        <!--多,由于查询的一个部门的员工有很多,所以使用的标签为collection-->
        <collection  select="com.bjsxt.mapper.EmpMapper.selectByNoN" property="empList"
        ofType="emp" column="deptno"></collection>
    </resultMap>

测试类

package com.bjsxt.test;
import com.bjsxt.entity.Dept;
import com.bjsxt.entity.Emp;
import com.bjsxt.mapper.DeptMapper;
import com.bjsxt.mapper.EmpMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class TestOneMoreN {
    public static void main(String[] args) throws IOException {
        //(1)解析xml
        InputStream inputStream = Resources.getResourceAsStream("mybatis.xml");
        //(2)获取工厂对象
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
        //(3)获取session对象
        SqlSession sqlSession = factory.openSession();
        //(4)业务的方法实现一对一的查询,使用java代码去组织,实现表连查的效果
        DeptMapper deptMapper = sqlSession.getMapper(DeptMapper.class);
        List<Dept> list = deptMapper.selectAllN();
        for(Dept dept:list){
            System.out.println(dept);
        }
        //(5)关闭
        sqlSession.close();
    }
}

一对多查询,使用到<collection标签>该标签有4个常用属性
a) select : 指要执行的sql语句
b)property:查询结果放到实体中的哪个属性存储
c)ofType :select 查询的返回值的类型
d)column: 根据哪个列进行查询

三、表连接查询

N+1的优点:不需要写业务代码
缺点:执行的sql语句的数量比较多,效率比较低

为什么表连接方式?
(1)不用写业务代码(java代码不用写太多)
(2) 只需要执行一个表连接查询即可 (sql只有一句)

一对一 :一个员工对应一个部门
SQL: select * from emp e ,dept d where e.deptno=d.deptno
通过mapper.xml文件的配置来实现
依然使用的是resultMap标签

接口中的方法

 public List<Emp> queryAllTable();

配置xml文件

<!--表连接查询-->
    <select id="queryAllTable" resultMap="rm1">
        select * from emp e ,dept d where e.deptno=d.deptno
    </select>
    <resultMap id="rm1" type="emp">
        <!--查询结果中只有这三个列有值-->
        <id column="empno" property="empNo"></id>
        <result column="ename" property="ename"></result>
        <result column="job" property="job"></result>
        
        <!--连接的dept表的中列-->
        <association property="dept" javaType="dept">
            <id column="deptno" property="deptNo"></id>
            <result column="dname" property="dname"></result>
            <result column="loc" property="loc"></result>
        </association>
    </resultMap>

一对一,使用

一对多 一个部门对应N多个员工
SQL :select * from emp e ,dept d where e.deptno=d.deptno
配置mapper.xml文件来实现

接口中的方法

 public List<Dept> selectAllTable();

配置xml文件

 <!--表连接查询-->
    <select id="queryAllTable" resultMap="rm1">
        select * from emp e ,dept d where e.deptno=d.deptno
    </select>
    <resultMap id="rm1" type="emp">
        <!--查询结果中只有这三个列有值-->
        <id column="empno" property="empNo"></id>
        <result column="ename" property="ename"></result>
        <result column="job" property="job"></result>
        
        <!--连接的dept表的中列-->
        <association property="dept" javaType="dept">
            <id column="deptno" property="deptNo"></id>
            <result column="dname" property="dname"></result>
            <result column="loc" property="loc"></result>
        </association>
    </resultMap>

一对一,使用

一对多 一个部门对应N多个员工
SQL :select * from emp e ,dept d where e.deptno=d.deptno
配置mapper.xml文件来实现

 public List<Dept> selectAllTable();
 <select id="selectAllTable" resultMap="rm1">
        select * from emp e right join dept d on  e.deptno=d.deptno
    </select>
    <resultMap id="rm1" type="dept">
        <id column="deptno" property="deptNo"></id>
        <result column="dname" property="dname"></result>
        <result column="loc" property="loc"></result>
        <!--连接emp表-->
        <collection property="empList" ofType="emp">
            <id column="empno" property="empNo"></id>
            <result column="ename" property="ename"></result>
        </collection>
    </resultMap>

一对多,使用标签

resultMap标签的作用
(1)手动映射
(2)n+1方式的果询
(3)表连接查询

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值