MyBatis学习笔记——初识MyBatis核心组件

一、MyBatis核心组件

MyBatis官方API

组件作用
SqlSessionFactoryBuilder构造器,用于构造SqlSessionFactory ,采用分布构建的Builder模式。(建造者模式
SqlSessionFactory(工厂接口)使用工厂模式,生成SqlSession
SqlSession可以 发送 SQL执行返回结果,也可以 获取 Mapper的接口。在使用中, SQL语句不再出现在业务逻辑代码中 ,而使用MyBatis提供的SQLMapper接口编程技术 ,从而提高代码的可读性可维护性
SQL Mapper映射器,由JAVA接口XML(可用注解替代)构成,需给出对应的SQL语句映射规则。负责发送SQL执行并返回结果

二、SqlSessionFactory(工厂接口)

使用MyBatis首先是:使用配置或者代码生产SqlSessionFactory,在MyBatis提供了SqlSessionFactoryBuilder方法来构造SqlSessionFactory。采用的建造者模式(Builder)来构建。

每个基于MyBatis的应用都是以一个SqlSessionFactory的实例为中心的,而SqlSessionFactory的唯一作用是:生产SqlSession,作用是唯一的。因此,通常采用单例模式处理SqlSessionFactory

MyBatis中,生成SqlSessionFactory有如下两种方法:

  • 通过读取配置的XML构建SqlSessionFactory
  • 通过Java代码生成SqlSessionFactory

1. 通过读取配置的XML构建SqlSessionFactory

基础配置文件属性配置有一定的规则,否则DTD会报错,规则如下:

(properties?,settings?,typeAliases?,typeHandlers?,objectFactory?,objectWrapperFactory?,reflectorFactory?,plugins?,environments?,databaseIdProvider?,mappers?)"

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


	<!-- 设置别名 -->
	<typeAliases>
		<typeAlias type="edu.mju.bean.Role" alias="role" />
	</typeAliases>

  	<!-- 数据库环境 -->
	<environments default="development">
		<environment id="development">
			<!--这里使用的是 JDBC 的事务管理器-->
			<transactionManager type="JDBC" />
			<!--MyBatis内置的数据源:UNPOOLED、POOLED、JNDI-->
			<dataSource type="POOLED">
				<property name="driver" value="${database.driver}" />
				<property name="url" value="${database.url}" />
				<property name="username" value="${database.username}" />
				<property name="password" value="${database.password}" />
			</dataSource>
		</environment>
	</environments>
	
	<!-- 映射文件 -->
	<mappers>
	    <mapper resource="edu/mju/mapper/RoleMapper.xml"/>
	</mappers>
  	
  </configuration>
标签说明
properties读取resource指定的配置文件
typeAliases设置别名,通过添加typeAlias标签,type为某一个类的全限定名,alias为自定义别名
environments环境配置。default参数指定使用的环境配置。
environment创建一个环境配置。
transactionManager配置事务管理器
dataSource配置数据源。MyBatis内置数据源:UNPOOLED、POOLED、JNDI。
UNPOOLED,mybaties会为每一个数据库操作创建一个新的连接,并关闭它。该方式适用于只有小规模数量并发用户的简单应用程序上。
POOLED,mybaties会创建一个数据库连接池,连接池的一个连接将会被用作数据库操作。一旦数据库操作完成,mybaties会将此连接返回给连接池。在开发或测试环境中经常用到此方式。
JNDI。mybaties会从在应用服务器向配置好的JNDI数据源DataSource获取数据库连接。在生产环境中优先考虑这种方式。
mappers引入映射文件。

通过以下代码,生成SqlSessionFactory

	public static SqlSessionFactory getSqlSessionFactory()  {
		   //读取配置文件
		   String resource = "mybatis-config.xml";
		   InputStream inputStream = null;
			try {
				//通过MyBatis的Resources对象getResourceAsStream方法返回在classpath作为Stream对象的资源
				inputStream = Resources.getResourceAsStream(resource);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		   SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
		   return sqlSessionFactory;
		}

2. 通过Java代码生成SqlSessionFactory

    public static SqlSessionFactory getSqlSessionFactory()  {
        //数据库连接池信息
        PooledDataSource dataSource = new PooledDataSource();
        dataSource.setDriver("com.mysql.jdbc.Driver");
        dataSource.setUrl("root");
        dataSource.setPassword("123456");
        dataSource.setUrl("jdbc:mysql://192.168.0.248:3306/chapter3?useUnicode=true&characterEncoding=UTF-8");
        //设置是否自动提交
        dataSource.setDefaultAutoCommit(false);

        //配置事务管理器
        TransactionFactory transactionFactory = new JdbcTransactionFactory();
        Environment environment = new Environment("development",transactionFactory,dataSource);

        //创建Configuration
        Configuration configuration = new Configuration(environment);
        //注册MyBatis别名
        configuration.getTypeAliasRegistry().registerAlias("role", Role.class);
        //注册映射器
        configuration.addMapper(RoleMapper.class);

        //构建SqlSessionFactory
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);

        return sqlSessionFactory;
    }

三、SqlSession

MyBatis中,SqlSession是核心接口。在MyBatis有两个实现类:DefaultSqlSessionSqlSessionManager

DefaultSqlSession:在单线程使用。
SqlSessionManager:在多线程使用。

SqlSession作用:

  • 获取Mapper接口
  • 发送SQL给数据库
  • 控制数据库事务

创建SqlSession代码如下:

	   public static SqlSession getSession()  {
	       SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
	       return sqlSessionFactory.openSession();
	   }
		
		//等同于
		SqlSession SqlSession = SqlSessionFactory.openSession();

除此之外,SqlSession还有控制数据库事务的方法,如

  • sqlSession.commit():提交事务
  • sqlSession.rollback():回滚事务

四、映射器

官方API

映射器是MyBatis中最重要的组件,由一个接口和对应XML文件(或者注解)组成。

接口是不能直接运行!但MyBatis运用了动态代理技术使得接口能够运行,MyBatis为该接口生成一个代理对象,代理对象处理相关的逻辑。

1. XML文件形式实现映射器

这里我们先定义一个实体类:Role.java

package edu.mju.bean;

public class Role {
	private Integer id;
	private String roleName;
	private String note;
	//省略get/set方法
}

  1. 定义映射器接口

RoleMapper.java

package edu.mju.mapper;

import edu.mju.bean.Role;

public interface RoleMapper {
	int insertRole(Role role);
	Role selectRole(Integer id);
}
  1. XML创建映射器

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="edu.mju.mapper.RoleMapper">
	 <!-- <select id="selectRole" resultType="edu.mju.bean.Role" > -->
	 <select id="selectRole" resultMap="roleViewMap">
	   select * from t_role where id = #{id}
	 </select>
	
	 <insert id="insertRole" parameterType="edu.mju.bean.Role" useGeneratedKeys="true">
	   insert into t_role(role_name,note) values(#{roleName},#{note})
	 </insert>


	 <!-- 自定义结果集映射 -->
     <resultMap id="roleViewMap" type="edu.mju.bean.Role">
        <result column="id" property="id"/>
        <result column="role_name" property="roleName"/>
        <result column="note" property="note"/>
    </resultMap>
</mapper>
属性说明
<mapper namaspace=" ">namespace对应的是一个接口的全限定名,上下文通过namespace找到对应接口。
<resultMap id=“roleViewMap” type=“edu.mju.bean.Role”>自定义结果集映射。
type:指明类型为edu.mju.bean.Role类的类型。
id:唯一表标识id。
<result column=“role_name” property=“roleName”/>column:数据库查询的结果列名。
property:映射的属性名。
insert映射插入语句
update映射更新语句
delete映射删除语句
select映射查询语句
resultMap对外部 resultMap 的命名引用。结果映射是 MyBatis 最强大的特性,如果你对其理解透彻,许多复杂的映射问题都能迎刃而解。 resultType 和 resultMap 之间只能同时使用一个。
parameterType将会传入这条语句的参数的类全限定名或别名。这个属性是可选的,因为 MyBatis 可以通过类型处理器(TypeHandler)推断出具体传入语句的参数,默认值为未设置(unset)。
更多属性官方API
  1. 配置映射器

基础配置文件(mybatis-config.xml)中,引入映射文件

	<!-- 映射文件 -->
	<mappers>
	    <mapper resource="edu/mju/mapper/RoleMapper.xml"/>
	</mappers>

2. 注解实现映射器

  1. RoleMapper2.java
package edu.mju.mapper;

import edu.mju.bean.Role;
import org.apache.ibatis.annotations.Insert;

public interface RoleMapper2 {

	@Insert("insert into t_role(role_name,note) values(#{roleName},#{note})")
	int insertRole2(Role role);

}

  1. 配置映射
	<!-- 映射文件 -->
	<mappers>
	    <mapper resource="edu/mju/mapper/RoleMapper.xml"/>
		<mapper class="edu.mju.mapper.RoleMapper2"/>
	</mappers>

3. 发送SQL

通过以上两种方法实现了映射器,可以通过SqlSession发送SQL或用Mapper接口发送SQL

  • SqlSession发送SQL
    /**
     * 通过SqlSession发送SQL
     * @param id id
     * @return Role对象
     * @throws IOException 异常处理
     */
   public Role getByIdSqlSession(int id) throws IOException {
       SqlSession session = MyBatisUtil.getSession();
       //selectOne(String statement, Object parameter):
       // statement:匹配要使用的语句的唯一标识符
       // parameter:传递给语句的参数对象。
       Role role = session.selectOne("edu.mju.mapper.RoleMapper.selectRole",id);
       session.close();
       return  role;
   }
  • Mapper接口发送SQL
   /**
     * 通过Mapper接口发送SQL
     * @param id id
     * @return Role对象
     * @throws IOException 异常处理
     */
    public Role getByIdMapper(int id) throws IOException {
        SqlSession session = MyBatisUtil.getSession();
        //selectOne(String statement, Object parameter):
        // statement:匹配要使用的语句的唯一标识符
        // parameter:传递给语句的参数对象。
        RoleMapper roleMapper = session.getMapper(RoleMapper.class);
        Role role = roleMapper.selectRole(id);
        session.close();
        return  role;
    }

对比以上两种发送SQL方式,推荐使用第二种Mapper接口发送SQL的方式,优点如下:

  • 使用Mapper接口编程可以消除SqlSession带来的功能性代码,提高可读性.
  • 错误能够及早发现.使用第一种的方式,只能在运行中才能知道是否产生错误;而第二种方式IDE会提示错误和校验.

五、生命周期

在多线程的环境中,错误使用会造成严重的多线程并发问题,为了正确编写MyBatis的应用程序,我们需要掌握MyBatis组件的生命周期.

1. SqlSessionFactoryBuilder

SqlSessionFactoryBuilder的作用是创建SqlSessionFactory,创建成功后,SqlSessionFactoryBuilder就失去了作用,所以它只存在于创建SqlSessionFactory的方法中,不长期存在.

2. SqlSession

SqlSessionFactory相当于数据库连接池,SqlSession相当于一个数据库连接(Connection对象).它存在于业务请求中,当业务处理完成请求后,应关闭该连接,以释放SqlSessionFactory空间,使数据库资源能够供给下一个连接对象,避免系统瘫痪.

3.Mapper

Mapper是一个接口,由SqlSession所创建,它的生命周期小于等于SqlSession的生命周期.

六、实例

1. 实体类

package edu.mju.bean;

public class Role {
	private Integer id;
	private String roleName;
	private String note;
	
	
	public Role(String roleName, String note) {
		this.roleName = roleName;
		this.note = note;
	}
	
	public Integer getId() {
		return id;
	}
	public void setId(Integer 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;
	}
}

2. Mapper接口

package edu.mju.mapper;

import edu.mju.bean.Role;

public interface RoleMapper {
	/**
	 * 添加Role对象
	 * @param role 要添加的对象
	 * @return 更新的值
	 */
	int insertRole(Role role);

	/**
	 * 根据id查找Role
	 * @param id id
	 * @return Role对象
	 */
	Role selectRole(Integer id);

	/**
	 * 根据id删除Role
	 * @param id id
	 * @return 更新的值
	 */
	int deleteRole(Integer id);

	/**
	 * 更新Role
	 * @param role 传入更新的Role对象
	 * @return 更新的值
	 */
	int updateRole(Role role);
}

3. 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="edu.mju.mapper.RoleMapper">
	 <!-- <select id="selectRole" resultType="edu.mju.bean.Role" > -->
	 <select id="selectRole" resultMap="roleViewMap">
	   select * from t_role where id = #{id}
	 </select>
	
	 <insert id="insertRole" parameterType="edu.mju.bean.Role" useGeneratedKeys="true">
	   insert into t_role(role_name,note) values(#{roleName},#{note})
	 </insert>

	<delete id="deleteRole" parameterType="int">
		delete from t_role where id = #{id}
	</delete>

	<update id="updateRole" parameterType="edu.mju.bean.Role">
		update t_role set role_name = #{roleName},note = #{note} where id = #{id}
	</update>


	 <!-- 自定义结果集映射 -->
     <resultMap id="roleViewMap" type="edu.mju.bean.Role">
        <result column="id" property="id"/>
        <result column="role_name" property="roleName"/>
        <result column="note" property="note"/>
    </resultMap>
</mapper>

4. mybatis配置文件

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


	<!-- 设置别名 -->
	<typeAliases>
		<typeAlias type="edu.mju.bean.Role" alias="role" />
	</typeAliases>

  	<!-- 数据库环境 -->
	<environments default="development">
		<environment id="development">
			<!--这里使用的是 JDBC 的事务管理器-->
			<transactionManager type="JDBC" />
			<!--MyBatis内置的数据源:UNPOOLED、POOLED、JNDI-->
			<dataSource type="POOLED">
				<property name="driver" value="${database.driver}" />
				<property name="url" value="${database.url}" />
				<property name="username" value="${database.username}" />
				<property name="password" value="${database.password}" />
			</dataSource>
		</environment>
	</environments>
	
	<!-- 映射文件 -->
	<mappers>
	    <mapper resource="edu/mju/mapper/RoleMapper.xml"/>
		<mapper class="edu.mju.mapper.RoleMapper2"/>
	</mappers>
  	
  </configuration>

5. 工具类

用来构建SqlSessionFactory.
这里在构造方法中加入private关键字,使得其他代码不能通过new的方式来创建它.加入synchronized关键字加锁,防止多线程中多次实例化SqlSessionFactory对象,从而保证SqlSessionFactory的唯一性.

package edu.mju.utils;

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

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 MyBatisUtil {

    private final static Class<MyBatisUtil> MY_BATIS_UTIL_CLASS = MyBatisUtil.class;

    private static SqlSessionFactory sqlSessionFactory = null;

    /**
     * private修饰构造方法,不能通过new创建MyBatisUtil()。
     */
    private MyBatisUtil() {
    }

    /**
     * 创建SqlSessionFactory(工厂接口)
     *
     * @return SqlSessionFactory
     * @throws IOException
     */
    public static SqlSessionFactory getSqlSessionFactory() {
        //加锁,防止多线程多次实例化SqlSessionFactory对象
        synchronized (MY_BATIS_UTIL_CLASS) {
            if (sqlSessionFactory != null) {
                return sqlSessionFactory;
            }
            //读取配置文件
            String resource = "mybatis-config.xml";
            InputStream inputStream = null;
            try {
                //通过MyBatis的Resources对象getResourceAsStream方法返回在classpath作为Stream对象的资源
                inputStream = Resources.getResourceAsStream(resource);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            return sqlSessionFactory;
        }
    }

    /**
     * 获取SqlSession
     *
     * @return SqlSession
     * @throws IOException
     */
    public static SqlSession getSession() {
		if(sqlSessionFactory == null){
			getSqlSessionFactory();
		}
        return sqlSessionFactory.openSession();
    }
}

6. Dao处理

package edu.mju.dao;

import java.io.IOException;

import edu.mju.mapper.RoleMapper;
import org.apache.ibatis.session.SqlSession;

import edu.mju.bean.Role;
import edu.mju.utils.MyBatisUtil;

public class RoleDao {

    /**
     * 通过SqlSession发送SQL
     * @param id id
     * @return Role对象
     * @throws IOException 异常处理
     */
   public Role getByIdSqlSession(int id) throws IOException {
       SqlSession session = MyBatisUtil.getSession();
       //selectOne(String statement, Object parameter):
       // statement:匹配要使用的语句的唯一标识符
       // parameter:传递给语句的参数对象。
       Role role = session.selectOne("edu.mju.mapper.RoleMapper.selectRole",id);
       session.close();
       return  role;
   }

    /**
     * 通过Mapper接口发送SQL
     * @param id id
     * @return Role对象
     * @throws IOException 异常处理
     */
    public Role getByIdMapper(int id) throws IOException {
        SqlSession session = MyBatisUtil.getSession();
        //selectOne(String statement, Object parameter):
        // statement:匹配要使用的语句的唯一标识符
        // parameter:传递给语句的参数对象。
        RoleMapper roleMapper = session.getMapper(RoleMapper.class);
        Role role = roleMapper.selectRole(id);
        session.close();
        return  role;
    }

    /**
     * 根据id删除Role
     * @param id id
     * @return 更新的值
     */
    public int deleteRole(Integer id){
        SqlSession session = MyBatisUtil.getSession();
        RoleMapper roleMapper = session.getMapper(RoleMapper.class);
        int result = roleMapper.deleteRole(id);
        session.close();
        return result;
    }

    /**
     * 更新Role
     * @param role 更新的Role对象
     * @return 更新的值
     */
    public int updateRole(Role role){
        SqlSession session = MyBatisUtil.getSession();
        RoleMapper roleMapper = session.getMapper(RoleMapper.class);
        int result = roleMapper.updateRole(role);
        session.close();
        return result;
    }
   
   public int insertRole(Role role) throws IOException {
       SqlSession session = MyBatisUtil.getSession();
       //selectOne(String statement, Object parameter):
       // statement:匹配要使用的语句的唯一标识符
       // parameter:传递给语句的参数对象。
       int i = session.insert("edu.mju.mapper.RoleMapper.insertRole",role);
       session.close();
       return  i;
   }

    public int insertRole2(Role role) throws IOException {
        SqlSession session = MyBatisUtil.getSession();
        //selectOne(String statement, Object parameter):
        // statement:匹配要使用的语句的唯一标识符
        // parameter:传递给语句的参数对象。
        int i = session.insert("edu.mju.mapper.RoleMapper2.insertRole2",role);
        session.close();
        return  i;
    }


   
}

7. 测试类

package edu.mju.test;

import java.io.IOException;

import edu.mju.bean.Role;
import edu.mju.dao.RoleDao;

public class TestDao {

	public static void main(String[] args) {
		Role role = getById(5);
		System.out.println("------------更新role后-----------");
		role.setNote("更新后");
		role.setRoleName("更新后的RoleName");
		updateRole(role);
		getById(5);
//		System.out.println(insertRole(new Role("中文测试1","中文note_1")));
//
//		System.out.println(insertRole(new Role("中文测试2","中文2")));

		//deleteRole(8);

	}


	public static Role getById(Integer id) {
		RoleDao roleDao = new RoleDao();
		Role role = null;
		try {
			//通过SqlSession发送SQL
			//role = roleDao.getByIdSqlSession(id);
			//通过Mapper接口发送SQL
			role = roleDao.getByIdMapper(id);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		System.out.println(role.getId());
		System.out.println(role.getRoleName());
		System.out.println(role.getNote());

		return role;
	}
	
	public static int insertRole(Role role) {
		RoleDao roleDao = new RoleDao();
		int result = 0;
		try {
			result = roleDao.insertRole(role);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return result;
	}

	public static int insertRole2(Role role){
		RoleDao roleDao = new RoleDao();
		int result = 0;
		try {
			result = roleDao.insertRole2(role);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return result;
	}

	public static void deleteRole(Integer id){
		RoleDao roleDao = new RoleDao();
		int i = roleDao.deleteRole(id);
		System.out.println("删除Role:"+i);
	}

	public static void updateRole(Role role){
		RoleDao roleDao = new RoleDao();
		int i = roleDao.updateRole(role);
		System.out.println("更新Role:"+i);
	}

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值