返回介绍

2.4 实例

发布于 2025-04-26 13:08:32 字数 9296 浏览 0 评论 0 收藏

这里做一个实例,它可以使我们熟悉 MyBatis 主要组件的用法。我们需要满足 MyBatis 各个组件的生命周期。首先需要生成 SqlSessionFacotry 单例,然后让它生成 SqlSession,进而拿到映射器中来完成我们的业务逻辑。

确定文件所需要放置的路径,以便在上下文中读取配置文件,如图 2-7 所示。

039_0001

图 2-7 实例文件路径

各个实例文件的作用,如表 2-1 所示。

表 2-1 实例文件的作用

039-1

首先,提供 log4j 的配置文件,如代码清单 2-11 所示。它为我们打出 MyBatis 的运行轨迹,给我们调试 MyBatis 应用带来了极大的帮助。

代码清单 2-11:log4j.properties

    log4j.rootLogger=DEBUG , stdout  
    log4j.logger.org.mybatis=DEBUG   
    log4j.appender.stdout=org.apache.log4j.ConsoleAppender   
    log4j.appender.stdout.layout=org.apache.log4j.PatternLayout   
log4j.appender.stdout.layout.ConversionPattern=%5p %d %C: %m%n  

其次,构建 SessionFactory,我们需要配置文件,如代码清单 2-12 所示。

代码清单 2-12:mybatis-config.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>
    <typeAliases>
        <typeAlias alias="role" type="com.learn.chapter2.po.Role"/>
    </typeAliases>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC">
                <property name="autoCommit" value="false"/>
            </transactionManager>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
                <property name="username" value="root"/>
                <property name="password" value="learn"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="com\learn\chapter2\mapper\roleMapper.xml"/>
    </mappers>
</configuration>

最后,构建 SqlSessionFactory,并且给出创建 SqlSession 的方法,这里我们利用配置文件 mybatis-config.xml 完成 SqlSessionFactory 的构建。这里和上面有些变化,我们不妨先看看代码如何现实,如代码清单 2-13 所示。

代码清单 2-13:SqlSessionFactoryUtil.java

package com.learn.chapter2.util;

import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
public class SqlSessionFactoryUtil {
    //SqlSessionFactory 对象
    private static SqlSessionFactory sqlSessionFactory = null;
    //类线程锁
    private static final Class CLASS_LOCK = SqlSessionFactoryUtil.class;
    /**
     * 私有化构造参数
     */
    private SqlSessionFactoryUtil() {}
    /**
     * 构建 SqlSessionFactory
     */
    public static SqlSessionFactory initSqlSessionFactory() {
        String resource = "mybatis-config.xml";
        InputStream inputStream = null;
        try {
            inputStream = Resources.getResourceAsStream(resource);
        } catch (IOException ex) {
            Logger.getLogger(SqlSessionFactoryUtil.class.getName()).log(Level.SEVERE, null, ex);
        }
        synchronized(CLASS_LOCK) {
            if (sqlSessionFactory == null) {
                sqlSessionFactory=new SqlSessionFactoryBuilder().build (input Stream);
            }
        }
        return sqlSessionFactory;
    }
    /**
     *  打开 SqlSession
     */
    public static SqlSession openSqlSession() {
        if (sqlSessionFactory == null) {
            initSqlSessionFactory();
        }
        return sqlSessionFactory.openSession();
    }
}

解释一下代码的含义,正如生命周期描述的一样,我们希望 SqlSessionFactory 对于一个数据库而言只有一个实例,于是我们希望它是单例。现在我们学习一下代码如何实现单例模式。

构建 SessionFactory 单例是通过方法 initSqlSessionFactory 实现的。首先,将构造方法设置为私有(private),其目的是避免使用者使用 new 的方式去创建多个对象。然后,我们使用 synchronized 对 SqlSessionFactoryUtil 类加锁,其目的是避免在多线程环境(MyBatis 多用于多线程环境,比如 Web 服务器,Socket 请求等)中,多次初始化造成对象的不唯一。

某一个对象在应用中承担唯一责任的时候使用单例模式,而本例中 SqlSessionFactory 的唯一责任就是为我们创建 SqlSession,所以采用单例模式。单例模式的好处在于可以重复使用这个唯一对象,而对象在内存中读取和运行速度都比较快,同时节约内存。我们的办法往往是把构造方法私有化,并给一个静态(static)方法,让其返回唯一单例,而在多线程环境初始化单例,往往需要加线程锁以避免类对象被多次初始化,正如本例一样。

我们还实现了 openSqlSession 方法,利用构建好的 SqlSessionFactory 创建 SqlSession,为将来所用奠定基础。

这里我们要给一个 POJO 类 - Role.java,如代码清单 2-14 所示,它就是一个很普通的 JavaBean。

代码清单 2-14:Role.java

package com.learn.chapter2.po;
public class Role {    
    private Long id;
    private String roleName;
    private String note;
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getRoleName() {
        return roleName;
    }
    public void setRoleName(String roleName) {
        this.roleName = roleName;
    }
    public String getNote() {
        return note;
    }
    public void setNote(String note) {
        this.note = note;
    }
}

我们还需要一个映射器的描述,让我们编写 XML 映射文件,如代码清单 2-15 所示。

代码清单 2-15:RoleMapper.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.learn.chapter2.mapper.RoleMapper">
    <select id="getRole" parameterType="long" resultType="role">
        select id, role_name as roleName, note from t_role where id = #{id}
    </select>
    <insert id="insertRole" parameterType="role">
        insert into t_role(role_name, note) values (#{roleName}, #{note})
    </insert>
    <delete id="deleteRole" parameterType="long">
        delete from t_role where id = #{id}
    </delete>
</mapper>

这里我们定义了 3 条 SQL,它们的作用有 3 个。

  • 查询一个角色对象。

  • 插入角色。

  • 删除角色表的数据。

这时候需要定义一个接口,注意接口的方法要和 XML 映射文件的 id 保持一致,于是得出下面的接口,如代码清单 2-16 所示。

代码清单 2-16:RoleMapper.java

package com.learn.chapter2.mapper;
import com.learn.chapter2.po.Role;
public interface RoleMapper {
        public Role getRole(Long id);
        public int deleteRole(Long id);
        public int insertRole(Role role);
}

为此我们已经构建好 SqlSessionFactory,同时也提供了创建 SqlSession 的方法和映射器,完成了对应的 3 个方法。现在我们可以利用这些东西完成下面两个任务了。

(1)插入一个角色(Role)对象。

(2)删除一个编号为 1L 的角色对象。

这里我们使用 Chapter2Main.java 类完成我们需要完成的任务,如代码清单 2-17 所示。

代码清单 2-17:Chapter2Main.java

package com.learn.chapter2.main;

import java.io.IOException;
import java.io.InputStream;

import org.apache.ibatis.datasource.pooled.PooledDataSource;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.mapping.Environment;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.ibatis.transaction.TransactionFactory;
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;

import com.learn.chapter2.mapper.RoleMapper;
import com.learn.chapter2.po.Role;
import com.learn.chapter2.util.SqlSessionFactoryUtil;

public class Chapter2Main {    

    public static void main(String[] args) throws IOException {
        SqlSession sqlSession = null;
        try {
            sqlSession = SqlSessionFactoryUtil.openSqlSession();
            RoleMapper roleMapper = sqlSession.getMapper(RoleMapper.class);
            Role role = new Role();
            role.setRoleName("testName");
            role.setNote("testNote");
            roleMapper.insertRole(role);
            roleMapper.deleteRole(1L);
            sqlSession.commit();
        } catch(Exception ex) {
            System.err.println(ex.getMessage());
            sqlSession.rollback();
        } finally {
            if (sqlSession != null) {
                sqlSession.close();
            }
        }
    }

}

至此我们的代码完成了,让我们用 Java Application 的形式运行一下 Chapter2Main.java。我们可以看到如下结果。

......
DEBUG 2016-02-01 14:48:10,528 org.apache.ibatis.transaction.jdbc. JdbcTransaction:Setting autocommit to false on JDBC Connection[com. mysql.jdbc.JDBC4Connection@7e0b0338]
DEBUG 2016-02-01 14:48:10,531 org.apache.ibatis.logging.jdbc. BaseJdbcLogger: ==>  Preparing: insert into t_role(role_name, note) values (?, ?) 
DEBUG 2016-02-01 14:48:10,563 org.apache.ibatis.logging.jdbc.Base JdbcLogger: ==> Parameters: testName(String), testNote(String)
DEBUG 2016-02-01 14:48:10,564 org.apache.ibatis.logging.jdbc.Base JdbcLogger:<==Updates:1
DEBUG 2016-02-01 14:48:10,564 org.apache.ibatis.logging.jdbc. Base JdbcLogger: ==>  Preparing: delete from t_role where id = ? 
DEBUG 2016-02-01 14:48:10,565 org.apache.ibatis.logging.jdbc. Base JdbcLogger:==> Parameters: 1(Long)
DEBUG 2016-02-01 14:48:10,566 org.apache.ibatis.logging.jdbc.BaseJdbc Logger:<==Updates:1
DEBUG 2016-02-01 14:48:10,566 org.apache.ibatis.transaction.jdbc. JdbcTransaction: Committing JDBC Connection [com.mysql.jdbc.JDBC4Connec tion@7e0b0338]
......

这样 Log4j 为我们打印出了 MyBatis 的运行轨迹,最为重要的是它为我们打印出了运行的 SQL 和参数。在调试中这些信息是十分重要的,如果发生异常我们将可以找到问题的所在,也能找到插入和删除角色的过程,运行完全成功。

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。