MyBatis普通模式开发

普通模式,也称为传统DAO模式,就是在传统DAO模式下,定义接口和实现类,如 interface EmpDao  class EmpDaoImpl implements EmpDao.  在实现类中,SQLSession对象调用 select insert delete update 等方法实现.目前极为少见.在传统模式下,我们需要知道SqlSession对象 实现CURD和 参数传递的处理,后续所需表SQL如下:

#创建dept表
CREATE table dept(
DEPTON int(2) not NULL,
DNAME  varchar(14),
LOC    varchar(13) 
)
INSERT into dept VALUES(10,'ACCOUNTING','NEW YORK');
INSERT into dept VALUES(20,'RESEARCH','DALLAS');
INSERT into dept VALUES(30,'SALES','CHICAGO');
INSERT into dept VALUES(40,'OPERATIONS','BOSTON');
#创建emp表
CREATE TABLE emp(
empno int(4) not null,
ename varchar(10),
job varchar(9),
mgr int(4),
hiredate date,
sal DECIMAL(7,2),
comm DECIMAL(7,2),
deptno int(2)
)
INSERT into emp values(7369,'SMITH','CLERK',7902,'1980-12-17',800,NULL,20);
INSERT into emp values(7499,'ALLEN','SALESMAN',7698,'1981-02-20',1600,300,30);
INSERT into emp values(7521,'WARD','SALESMAN',7698,'1981-02-22',1250,500,30);
INSERT into emp values(7566,'JONES','MANNAGER',7839,'1981-04-02',2975,NULL,20);
INSERT into emp values(7654,'MARTIN','SALESMAN',7698,'1981-09-28',1250,1400,30);
INSERT into emp values(7698,'BLAKE','MANNAGER',7839,'1981-05-01',2850,NULL,30);
INSERT into emp values(7782,'CLARK','MANNAGER',7839,'1981-06-09',2450,NULL,10);
INSERT into emp values(7788,'SCOTT','ANALYST',7566,'1987-07-13',3000,NULL,20);
INSERT into emp values(7839,'KING','PRESIDENT',NULL,'1981-11-17',5000,NULL,10);
INSERT into emp values(7844,'TURNER','SALESMAN',7698,'1981-09-08',1500,0,30);
INSERT into emp values(7876,'ADAMS','CLERK',7788,'1987-07-13',1100,NULL,20);
INSERT into emp values(7900,'JAMES','CLERK',7698,'1981-12-03',950,NULL,30);
INSERT into emp values(7902,'FORD','ANALYST',7566,'1981-12-03',3000,NULL,20);
INSERT into emp values(7934,'MILLER','CLERK',7782,'1982-01-13',1300,NULL,10);
#创建salgrade表
CREATE TABLE salgrade(
GRADE int(11) not NULL,
LOSAL VARCHAR(14),
HISAL VARCHAR(13)
)
INSERT into salgrade values(1,'700','1200');
INSERT into salgrade values(2,'1201','1400');
INSERT into salgrade values(3,'1401','2000');
INSERT into salgrade values(4,'2001','3000');
INSERT into salgrade values(5,'3001','9999');

一、mybatis查询的三种方式

SqlSessionFactory

  • SqlSessionFactory是MyBatis的关键对象,它是个单个数据库映射关系经过编译后的内存镜像。
  • SqlSessionFactory对象的实例可以通过SqlSessionFactoryBuilder对象类获得,而SqlSessionFactoryBuilder则可以从XML配置文件或一个预先定制的Configuration的实例构建出SqlSessionFactory的实例。
  • 每一个MyBatis的应用程序都以一个SqlSessionFactory对象的实例为核心。
  • SqlSessionFactory是线程安全的,SqlSessionFactory一旦被创建,应该在应用执行期间都存在。在应用运行期间不要重复创建多次,建议使用单例模式。
  • SqlSessionFactory是创建SqlSession的工厂。

SqlSession

  • SqlSession是MyBatis的关键对象,是执行持久化操作的独享,类似于JDBC中的Connection。
  • 它是应用程序与持久层之间执行交互操作的一个单线程对象,也是MyBatis执行持久化操作的关键对象。
  • SqlSession对象完全包含以数据库为背景的所有执行SQL操作的方法,它的底层封装了JDBC连接,可以用SqlSession实例来直接执行被映射的SQL语句。
  • 每个线程都应该有它自己的SqlSession实例。
  • SqlSession的实例不能被共享,同时SqlSession也是线程不安全的,绝对不能讲SqlSeesion实例的引用放在一个类的静态字段甚至是实例字段中。也绝不能将SqlSession实例的引用放在任何类型的管理范围中,比如Servlet当中的HttpSession对象中。
  • 使用完SqlSeesion之后关闭Session很重要,应该确保使用finally块来关闭它。

SqlSession对象本身API中就已经提供了三个查询方法,分别能够实现如下查询方式

  • selectOne:返回单个对象 
  • selectList:返回对象List集合 
  • selectMap:返回对象Map集合 

1.1.准备emp表对应实体类

在com.augus.pojo包下创建实体类如下:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Emp implements Serializable {
    private Integer empno;
    private String ename;
    private String job;
    private String mgr;
    private Date hiredate;
    private Double sal;
    private Double comm;
    private Integer deptno;
}

1.2.创建EmpMapper.xml映射文件

这里注意传统模式下是不会开发接口,只会在创建映射文件如下:在com.augus.mapper下创建内容如下:

<?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">

<!--
namespace这里需要设置和接口类的路径
可以理解成要实现的SQL定义在那个接口文件中
-->
<mapper namespace="EmpMapper">

    <!--
    要实现查询empno为7654的员工信息
    -->
    <select id="findEmpNo" resultType="emp">
        select * from emp where empno=7566
    </select>


    <!--
    查询所有的员工信息,放在集合中
    List<Emp> findAllEmp();
    -->
    <select id="findAllEmp" resultType="emp">
        select * from emp
    </select>

    <!--
    查询所有的员工信息,结果放在集合中
    List<Map> findAllMap();
    resultType="map" 指定结果以集合的形式存放
    -->
    <select id="findAllMap" resultType="map">
       select * from emp
    </select>

</mapper>

1.3.在sqlMapConfig.xml中配置映射文件

特别注意的是需要在sqlMapConfig.xml中配置引入mapper文件,必须使用resource标签实现

<?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 resource="jdbc.properties"></properties>

    <settings>
        <setting name="logImpl" value="LOG4J2"/>
    </settings>

    <typeAliases>
        <!--
        如下每一个实体类都起别名,那么实体类特别的就很麻烦,所以通过,
        包扫描的方式即可解决。会自动扫描某个包下面的所有实体类,默认
        用类名的小写作为应用时的类名
        -->
        <!--<typeAlias type="com.augus01.pojo.Dept" alias="dept"></typeAlias>-->
        <package name="com.augus.pojo"/>
    </typeAliases>

    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <!--指定连接数据库的信息,数据库服务器ip、端口、用户名、密码-->
                <property name="driver" value="${jdbc_driver}"/>
                <property name="url" value="${jdbc_url}"/>
                <property name="username" value="${jdbc_username}"/>
                <property name="password" value="${jdbc_password}"/>
            </dataSource>
        </environment>
    </environments>
    <!--加载mapper映射文件-->
    <mappers>
       <mapper resource="com/augus/mapper/EmpMapper.xml"/>
    </mappers>
</configuration>

截图如下:

1.4.编写测试代码如下

这里编写的是代码基于Junit5进行测试

public class Test1 {
    private static SqlSession sqlSession;

    @BeforeAll
    public static void init() throws IOException {

        //指定加载的xml配置文件
        InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");

        /**
         * SqlSessionFactoryBuilder主要是提供了根据字节流、字符流以及配置参数这三个参数组成的各种build方法,最终会调用上的build方法。
         * SqlSessionFactoryBuilder的 build()方法用于创建 SqlSessionFactory 的实例。SqlSessionFactory 用于创建 SqlSession 实例。
         */
        SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resourceAsStream);

        /**
         * SqlSession是MyBatis的关键对象,是执行持久化操作的对象,类似于JDBC中的Connection。
         * 它是应用程序与持久存储层之间执行交互操作的一个单线程对象,也是MyBatis执行持久化操作的关键对象。
         * SqlSession对象完全包含以数据库为背景的所有执行SQL操作的方法,它的底层封装了JDBC连接,可以用SqlSession实例来直接执行已映射的SQL语句。
         * 每个线程都应该有它自己的SqlSession实例。SqlSession的实例不能被共享,也是线程不安全的,绝对不能将SqlSession 实例的引用放在一个类的静态字段甚至是实例字段中。也绝不能将SqlSession实例的引用放在任何类型的管理范围中,比如Serlvet当中的HttpSession 对象中。使用完SqlSession之后关闭Session很重要,应该确保使用finally块来关闭它。
         */
        sqlSession = build.openSession();
    }

    @Test
    public void testFindEmpOne(){
        Emp emp = sqlSession.selectOne("findEmpNo");
        System.out.println(emp);
    }

    @Test
    public void testFindEmpAll(){
        List<Emp> findAllEmp = sqlSession.selectList("findAllEmp");

        for (Emp emp : findAllEmp) {
            System.out.println(emp);
        }
    }

    @Test
    public void testFindEmpMapAll(){
        //以empno字段作为键,每一条结果作为值,键的名字必须和表字段大小写保持一致
        Map<Integer,Emp> findAllMap = sqlSession.selectMap("findAllMap","empno");

        //获取键
        Set<Integer> integers = findAllMap.keySet();

        //根据键取值
        for (Integer integer : integers) {
            //根据键取值
            Object emp = findAllMap.get(integer);
            System.out.println("键为:"+integer+",值为:"+emp);
        }

    }
}

二、mybatis参数传递的三种方式

对应SQL中进行参数化时设置参数而言,mybatis提供了三种方式:

  • 单个基础数据类型作为参数
  • 多个基础数据类型的map 集合作为参数
  • 引用类型作为参数

1.创建EmpMapper2.xml映射文件

在里面编写对应sql:

<?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="EmpMapper2">

    <!--
    根据编号查询员工信息
    id="findEmpByEmpNo" 名称:
    resultType="emp" 返回的类型
    parameterType="integer":参数的类型
    在SQL语句上可以使用${}  #{} 代表参数的占位,如果参数是单个基本数据类型,{}中名字可以随便写,见名知意
        ${} 代表mybatis底层使用Statment语句对象,参数是以字符串拼接的形式设置
        #{} 代表mybatis底层使用的preparedStatment语句对象,参数使用?作为占位符处理 常用方式(推荐)
    -->
    <select id="findEmpByEmpNo" resultType="emp" parameterType="integer">
        select * from emp where empno=#{empno}
    </select>

    <!--
    多个基础数据类型的map 集合作为参数,根据部门号和最低薪资的进行查询
    参数为map集合,所以parameterType="map"
    -->
    <select id="findEmpByDeptNoAndSal1" resultType="emp" parameterType="map">
        select * from emp where deptno=#{deptno} and sal=#{sal}
    </select>

    <!--
    引用类型作为参数:参数以Emp对象属性的值传入
    -->
    <select id="findEmpByDeptNoAndSal2" resultType="emp" parameterType="emp">
        select * from emp where deptno=#{deptno} and sal=#{sal}
    </select>

</mapper>

2.在sqlMapConfig.xml中设置加载EmpMapper2.xml文件

<mapper resource="com/augus/mapper/EmpMapper2.xml"/>

如下图所示:

3.测试代码

创建测试代码Test2,如下:

public class Test2 {
    private static SqlSession sqlSession;

    @BeforeAll
    public static void init() throws IOException {

        //指定加载的xml配置文件
        InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");

        /**
         * SqlSessionFactoryBuilder主要是提供了根据字节流、字符流以及配置参数这三个参数组成的各种build方法,最终会调用上的build方法。
         * SqlSessionFactoryBuilder的 build()方法用于创建 SqlSessionFactory 的实例。SqlSessionFactory 用于创建 SqlSession 实例。
         */
        SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resourceAsStream);

        /**
         * SqlSession是MyBatis的关键对象,是执行持久化操作的对象,类似于JDBC中的Connection。
         * 它是应用程序与持久存储层之间执行交互操作的一个单线程对象,也是MyBatis执行持久化操作的关键对象。
         * SqlSession对象完全包含以数据库为背景的所有执行SQL操作的方法,它的底层封装了JDBC连接,可以用SqlSession实例来直接执行已映射的SQL语句。
         * 每个线程都应该有它自己的SqlSession实例。SqlSession的实例不能被共享,也是线程不安全的,绝对不能将SqlSession 实例的引用放在一个类的静态字段甚至是实例字段中。也绝不能将SqlSession实例的引用放在任何类型的管理范围中,比如Serlvet当中的HttpSession 对象中。使用完SqlSession之后关闭Session很重要,应该确保使用finally块来关闭它。
         */
        sqlSession = build.openSession();
    }

    @Test
    public void findEmpByEmpNo(){
        Emp emp = sqlSession.selectOne("findEmpByEmpNo",7782);
        System.out.println(emp);
    }

    /**
     * 多个基础数据类型的map 集合作为参数
     */
    @Test
    public void testFindEmpByDeptNoAndSal1(){
        //参数作为map集合传入
        HashMap<String, Object> stringObjectHashMap = new HashMap<>();
        //设置键值对象
        stringObjectHashMap.put("deptno",30);
        stringObjectHashMap.put("sal",2850.00);

        //执行sql,传入map集合组合的参数
        List<Emp> emps = sqlSession.selectList("findEmpByDeptNoAndSal1", stringObjectHashMap);

        for (Emp emp : emps) {
            System.out.println(emp);
        }
    }

    /**
     * 引用类型作为参数
     */
    @Test
    public void testFindEmpByDeptNoAndSal2(){
        //创建Emp对象,组合参数
        Emp emp = new Emp();
        //设置属性
        emp.setDeptno(30);
        emp.setSal(2850.00);

        //执行sql
        List<Emp> emps = sqlSession.selectList("findEmpByDeptNoAndSal2", emp);

        //输出
        for (Emp emp1 : emps) {
            System.out.println(emp1);
        }
    }
}

执行如下:

三、mybatis完成DML全部操作

1.创建EmpMapper3.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="EmpMapper3">
    <!--
    注意增加、删除、修改操作返回的都是int类型,表示操作的数据量
    所以resltType则无序指定
    insert、update、delete标签中没有resultType属性,但是可以设置paramaterType
    -->
    
    <!--增加-->
    <insert id="addEmp" parameterType="emp">
        insert into emp values (#{empno},#{ename},#{job},#{mgr},#{hiredate},#{sal},#{comm},#{deptno})
    </insert>

    <!--修改
    根据员工编号,修改员工姓名
    -->
    <update id="updateEmpNameByEmpNo" parameterType="emp">
        update emp set ename=#{ename} where empno=#{empno}
    </update>

    <!--
    删除
    根据员工编号删除员工信息
    -->
    <delete id="deleteEmpByEmpNO" parameterType="integer">
        delete from emp where empno>#{empno}
    </delete>
    
</mapper>

2.在sqlMapConfig.xml中设置加载EmpMapper2.xml文件

在配置文件中添加映射文件:

<mapper resource="com/augus/mapper/EmpMapper3.xml"/>

如下图:

3.测试代码

创建测试类,进行测试如下:

public class Test3 {
    private static SqlSession sqlSession;

    @BeforeAll
    public static void init() throws IOException {

        //指定加载的xml配置文件
        InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");

        /**
         * SqlSessionFactoryBuilder主要是提供了根据字节流、字符流以及配置参数这三个参数组成的各种build方法,最终会调用上的build方法。
         * SqlSessionFactoryBuilder的 build()方法用于创建 SqlSessionFactory 的实例。SqlSessionFactory 用于创建 SqlSession 实例。
         */
        SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resourceAsStream);

        /**
         * SqlSession是MyBatis的关键对象,是执行持久化操作的对象,类似于JDBC中的Connection。
         * 它是应用程序与持久存储层之间执行交互操作的一个单线程对象,也是MyBatis执行持久化操作的关键对象。
         * SqlSession对象完全包含以数据库为背景的所有执行SQL操作的方法,它的底层封装了JDBC连接,可以用SqlSession实例来直接执行已映射的SQL语句。
         * 每个线程都应该有它自己的SqlSession实例。SqlSession的实例不能被共享,也是线程不安全的,绝对不能将SqlSession 实例的引用放在一个类的静态字段甚至是实例字段中。也绝不能将SqlSession实例的引用放在任何类型的管理范围中,比如Serlvet当中的HttpSession 对象中。使用完SqlSession之后关闭Session很重要,应该确保使用finally块来关闭它。
         */
        sqlSession = build.openSession();
    }



    /**
     * 新增
     */
    @Test
    public void testAddEmp(){
        //创建Emp对象,作为参数传入
        Emp emp = new Emp(7910, null, "张飞", 7965, new Date(), 8800.0, 200.0, 20);
        //执行sql
        int result = sqlSession.insert("addEmp", emp);

        //注意在增删改对数据作出影响的情况,必须提交事务
        sqlSession.commit();

        System.out.println(result);
    }

    /**
     * 修改
     */
    @Test
    public void testUpdateEmpNameByEmpNo(){
        //创建Emp对象,组合参数
        Emp emp = new Emp();
        //设置属性
        emp.setEmpno(7910);
        emp.setEname("李敏");

        //执行sql
        int result = sqlSession.update("updateEmpNameByEmpNo", emp);

        //注意在增删改对数据作出影响的情况,必须提交事务
        sqlSession.commit();
        System.out.println(result);

    }

    /**
     * 删除编号大于7905的员工信息
     */
    @Test
    public void testDeleteEmpByEmpNO(){
        int result = sqlSession.delete("deleteEmpByEmpNO", 7905);
        //注意在增删改对数据作出影响的情况,必须提交事务
        sqlSession.commit();
        System.out.println(result);
    }
}
posted @ 2022-08-02 14:20  酒剑仙*  阅读(49)  评论(0)    收藏  举报