MyBatis(二)Mybatis对象分析及使用

一、重要类对象

1.1、Resources

资源,读取资源文件。有很多方法通过加载并解析资源文件,返回不同类型的IO流对象。

1.2、sqlSessionFactoryBuilder

SqlSessionFactory的创建需要使用sqlSessionFactoryBuilder对象的build()方法。事实上使用SqlSessionFactoryBuilder的原因是将SqlSessionFactory这个复杂对象的创建交给Builder来执行,也就是建造者模式。

建造者模式:又称生成器模式,是一种对象的创建模式。可以将一个产品的内部表象与生成过程分割开,从而可以使一个建造过程生成具有不同内部表象的产品(将一个复杂对象的构建与它的表示分离,使得同样的构建可以创建不同的表示) 这样用户只需要指定需要建造的类型就可以得到具体的产品,不需要了解具体的建造过程和细节

在建造者模式中,角色分为指导者(Director)和建造者(builder):用户联系指导者,指导者指挥建造者最终得到产品。建造者模式可以强制执行分步骤建造过程。

1.3、SqlSessionFactory

SqlSessionFactory是一种重量级对象(系统开销大的对象),线程安全,所以一个应用只需要一个该对象即可。创建SqlSession对象使用SqlSessionFactory接口的openSession()方法。

默认的openSession()方法没有参数,它创建有如下特性的SqlSession对象:

  1. 开启一个事务(不自动提交)
  2. 将从由当前环境配置的DataSource实例中获取connection对象,事务隔离级别将会使用驱动或者数据源的默认设置。
  3. 预处理语句不会被复用,也不会处理批量更新。
  • openSession(true) 创建一个有自动提交的SqlSession
  • openSession(false) 创建一个非自动提交的SqlSession,即需要手动提交
  • openSession() 同openSession(false)

1.4、SqlSession

SqlSession对象用于执行持久化操作,一个SqlSession对应着一次数据库会话。一次会话以SqlSession的创建开始,以SqlSession的关闭结束。

SqlSession对象是线程不安全的,所以每次数据库会话结束前,需要马上调用其close()方法将其关闭。再次需要会话,再次开启。

SqlSession内部超过20个方法,我们常用的都是执行语法相关的方法。这些方法被用来执行定义在Sql映射的XML文件中SELECT、UPDATE、INSERT、DELETE语句,他们都会自行解释,每一句都使用语句的ID属性和参数对象,参数可以是原生类型(自动装箱或包装类)、JavaBean、PoJo或者Map。

<T> T selectOne(String statement, Object parameter)

<E> List<E> selectList(String statement, Object parameter)

<K,V> Map<K,V> selectMap(String statement, Object parameter, String mapKey) 

int insert(String statement, Object parameter) 

int update(String statement, Object parameter) 

int delete(String statement, Object parameter)

/*
    selectOne和selectList不同仅仅是因为selectOne必须返回一个对象或者null,如果返回值超过一个就会抛出异常。
    selectMap会将返回对象中的属性作为key值,将对象作为value值,从而将多结果集转换为Map类型。
    因为不是所有的语句都需要参数,所以这些方法都重载成为不需要参数的形式。
*/

二、Mybatis框架

在这里插入图片描述

  1. mybatis.xml是Mybatis框架的全局配置文件,配置了Mybatis运行的框架信息。Mapper1.xml…是Sql映射文件,配置了所有操作数据库的语句。这些文件需要在全局配置中加载。
  2. 通过Mybatis.xml等配置信息构建SqlSessionFactory,相当于产生连接池。
  3. 由SqlSessionFactory会话工厂创建SqlSession会话,进行数据库操作。
  4. Mybatis底层定义了Excutor执行器的接口操作数据库,Excutor接口有两个实现,基本执行器和缓存执行器。
  5. MappedStatement也是Mybatis的底层封装对象, 它包装了Mybatis配置信息以及sql映射信息,Mapper.xml中一个Sql语句对应一个Mapped Statement,sql的ID就是Mapped Statement的id。
  6. Mapped Statement对sql执行输入参数定义,输入参数包括HashMap、基本类型、pojo,Excutor在Mapped Statement执行Sql语句前将输入java对象映射到sql语句中,执行sql完毕后,输出映射就是JDBC中编码中对prepareStatement执行结果的定义。

三、配置日志

3.1、添加pom依赖

     <!--日志-->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.12</version>
        </dependency>

3.2、添加log4j.properties配置文件

#Global logging configuration   info warning error
log4j.rootLogger=DEBUG,stdout
#console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

3.3、添加mybatis.xml配置

<configuration>
    <!-- 配置日志   -->
    <settings>
        <setting name="logImpl" value="LOG4J"/>
    </settings>
    ...
</configuration>

3.4、测试结果

在这里插入图片描述

四、使用dao方式开发Mybatis项目

4.1、ThreadLocal

ThreadLocal并非一个线程的本地实现版本,它并不是一个Thread,而是一个threadlocalvariable(线程局部变量)。它的功能十分简单,为每一个使用该变量的线程都提供一个变量值副本,是java中较为特殊的一种线程绑定机制,其中每一个线程都可以独立的改变自己的副本,而不会与其他线程副本冲突。

4.2、SqlSession工具类

public class MybatisUtil {

    private static ThreadLocal<SqlSession> threadLocal=new ThreadLocal<>();

    private static SqlSessionFactory sqlSessionFactory;

    /**
     * 加载配置文件
     */
    static {
        try {
            Reader reader = Resources.getResourceAsReader("mybatis.xml");
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取sqlSession
     * @return
     */
    public static SqlSession getSqlSession(){
        SqlSession sqlSession=threadLocal.get();
        if(sqlSession==null){
            sqlSession = sqlSessionFactory.openSession();
            threadLocal.set(sqlSession);
        }
        return sqlSession;
    }

    /**
     * 关闭sqlSession
     */
    public static void closeSqlSession(){
        SqlSession sqlSession=threadLocal.get();
        if(sqlSession==null){
             sqlSession.close();
             threadLocal.remove();
        }
    } 
} 

4.3、dao接口和实现类

public interface TeamDao {
    /**
     * 查询全部队伍
     * @return
     */
    List<Team> queryAll();

    /**
     * 根据队伍ID查询
     * @param teamId
     * @return
     */
    Team queryById(Integer teamId);

    /**
     * 新增队伍
     * @param team
     * @return
     */
    Integer add(Team team);

    /**
     * 更新队伍
     * @param team
     * @return
     */
    Integer update(Team team);

    /**
     * 删除队伍
     * @param teamId
     * @return
     */
    Integer delete(Integer teamId); 
}



public class TeamDaoImpl implements TeamDao { 
    @Override
    public List<Team> queryAll() {
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        List<Team> list = sqlSession.selectList("com.jsonliu.test.entity.Team.queryAll");
        MybatisUtil.closeSqlSession();
        return list;
    }

    @Override
    public Team queryById(Integer teamId) {
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        Team team=sqlSession.selectOne("com.jsonliu.test.entity.Team.queryById",teamId);
        MybatisUtil.closeSqlSession();
        return team;
    }

    @Override
    public Integer add(Team team) {
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        int num = sqlSession.insert("com.jsonliu.test.entity.Team.insert", team);
        sqlSession.commit();
        MybatisUtil.closeSqlSession();
        return num;
    }

    @Override
    public Integer update(Team team) {
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        int num =sqlSession.update("com.jsonliu.test.entity.Team.update",team);
        sqlSession.commit();
        MybatisUtil.closeSqlSession();
        return num;
    }

    @Override
    public Integer delete(Integer teamId) {
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        int num =sqlSession.delete("com.jsonliu.test.entity.Team.delete",teamId);
        sqlSession.commit();
        MybatisUtil.closeSqlSession();
        return num;
    }
}

4.4、测试类

public class TestB {

    private TeamDao teamDao=new TeamDaoImpl();

    @Test
    public void test1(){
        System.out.println("------------------queryAll----------------------");
        List<Team> teams = teamDao.queryAll();
        teams.forEach(team -> {
            System.out.println(team);
        });

        System.out.println("------------------add----------------------");
        Integer insert = teamDao.add(new Team("探险者", "新泽西", new Date()));
        System.out.println("新增结果:"+insert);

        System.out.println("------------------query----------------------");
        Team team = teamDao.queryById(1115);
        System.out.println(team);

        System.out.println("------------------update----------------------");
        team.setTeamName("JK的队伍");
        team.setLocation("hangzhou");
        Integer update = teamDao.update(team);
        System.out.println("修改结果:"+insert);

        System.out.println("------------------delete----------------------");
        Integer delete = teamDao.delete(1115);
        System.out.println("删除结果:"+delete); 
    } 
}

五、使用mapper方式开发Mybatis项目

5.1、什么是mapper接口

前面的例子中,dao实现类并没做什么实质性的事情,仅仅通过sqlSession的相关API定位到mapper中相应id的sql语句。真正对DB进行操作是Mapper中的SQL完成的。

所以,Mybatis抛开了dao的实现类,直接定位到映射文件mapper中相应的sql语句,对DB进行操作。这种Dao的实现方式被称为Mapper接口的动态代理实现。

Mapper动态代理无需程序员实现dao接口,接口是Mybatis结合映射文件生成的动态代理实现的。

5.2、TeamMapper

public interface TeamMapper {

    /**
     * 查询全部队伍
     * @return
     */
    List<Team> queryAll();

    /**
     * 根据队伍ID查询
     * @param teamId
     * @return
     */
    Team queryById(Integer teamId);

    /**
     * 新增队伍
     * @param team
     * @return
     */
    Integer insert(Team team);

    /**
     * 更新队伍
     * @param team
     * @return
     */
    Integer update(Team team);

    /**
     * 删除队伍
     * @param teamId
     * @return
     */
    Integer delete(Integer teamId);  
} 

5.3、TeamMapper.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">
<!--namespace必须与映射类的名称一致,是完全限定名-->
<mapper namespace="com.jsonliu.test.mapper.TeamMapper">
    <!--id自定义名称,不能重复。相当于dao中方法名称,resultType使用要求:实体中属性名称必须与数据库表中列名称一致-->
    <select id="queryAll" resultType="com.jsonliu.test.entity.Team">
        select * from team
    </select>

    <!--parameterType="参数类型" #{id}表示参数,id-自定义,符合命名规范即可,没有实际对应意义-->
    <select id="queryById" parameterType="int" resultType="com.jsonliu.test.entity.Team">
        select * from team where teamId=#{id}
    </select>

    <!--parameterType="com.jsonliu.test.entity.Team" 将对象作为参数,
        #{}必须是实体类中的属性名称,即占位符?-->
    <insert id="insert" parameterType="com.jsonliu.test.entity.Team">
        insert into team(teamName,location,createTime)
        values(#{teamName},#{location},#{createTime})
    </insert>

    <update id="update" parameterType="com.jsonliu.test.entity.Team">
        update team set teamName=#{teamName},location=#{location} where teamId=#{teamId}
    </update>

    <delete id="delete" parameterType="int">
        delete from team where  teamId=#{teamId}
    </delete> 
</mapper>

5.4、mybatis配置文件中添加mapper

<configuration>
...
 <!-- 注册映射文件  -->
    <mappers>
        <mapper resource="com/jsonliu/test/entity/Team.xml"/>
        <mapper resource="com/jsonliu/test/mapper/TeamMapper.xml"/>
    </mappers>
</configuration>

5.5、getMapper()获取代理对象

只需调用 SqlSession 的 getMapper()方法,即可获取指定接口的实现类对象。

public class TeamMapperTest { 
    @Test
    public void test1(){
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        TeamMapper teamDao = sqlSession.getMapper(TeamMapper.class);
        System.out.println("------------------queryAll----------------------");
        List<Team> teams = teamDao.queryAll();
        teams.forEach(team -> {
            System.out.println(team);
        }); 
        System.out.println("------------------add----------------------");
        Integer insert = teamDao.insert(new Team("探险者23", "新泽西23", new Date()));
        System.out.println("新增结果:"+insert);

        System.out.println("------------------query----------------------");
        Team team = teamDao.queryById(1116);
        System.out.println(team);

        System.out.println("------------------update----------------------");
        team.setTeamName("wangwu的队伍");
        team.setLocation("tianjin");
        Integer update = teamDao.update(team);
        System.out.println("修改结果:"+insert);

        System.out.println("------------------delete----------------------");
        Integer delete = teamDao.delete(1116);
        System.out.println("删除结果:"+delete);
    } 
}

5.6、实现原理

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

笑谈子云亭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值