在前面的博文中,小编介绍了springmvc的相关知识点,在今天这篇博文中,小编将介绍一下mybatis的框架原理,以及mybatis的入门程序,实现用户的增删改查,她有什么优缺点以及mybatis和hibernate之间存在着怎么样的关系,接下来小编一一进行讲解,希望对小伙伴们有帮助,不足之处,还请多多指教。
什么是mybatis?
MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。
MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架。MyBatis 避免了几乎所有的 JDBC 代码和手工设置参数以及抽取结果集。MyBatis 使用简单的 XML 或注解来配置和映射基本体,将接口和 Java 的 POJO(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。简单来说,mybatis就是一个持久层的框架,mybatis让程序将主要精力放在sql上,通过mybatis提供的映射方式,自由灵活生成满足需要的sql语句,mybatis可以将向preparedStatement中的输入参数自动进行输入映射,将查询结果集灵活映射成java对象。

接着,我们通过一张图,来了解一下mybatis的框架原理:

框架架构讲解:

a、加载配置文件:配置来源于两个地方,一个是配置文件,一个是java代码的注解,将sql的配置信息加载成为一个个MappedStatement对象(包括了传入参数映射配置、执行的SQL语句、结果映射配置),存储在内存中。

b、SQL解析:当api接口层接收到调用请求时,会接收到传入slq的id和传入对象(可以是map或者基本数据类型),mybatis会根据sql的id找到对应的MappedStatement,然后根据传入参数对象对MappedStatement进行解析,解析后可以得到最终要执行的sql语句和参数。

c、 SQL执行:将最终得到的SQL和参数拿到数据库进行执行,得到操作数据库的结果。

d、结果映射:将操作数据库的结果按照映射的配置进行转换,可以转换成HashMap、JavaBean或者基本数据类型,并将最终结果返回。

mybatis入门程序解析

接着,小编结合demo来具体介绍一下,需求如下:
根据用户id查询用户信息;
根据用户名称模糊查询用户信息;
添加、删除、更新用户。
第一步、建立各种包和类,工程目录如下所示:

第二步、编写SqlMapConfig.xml中的内容,配置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>
	<!-- 将spring整合后environments配置将废除 -->
	<environments default="developent">
	<!-- 使用jdbc事务管理,事务控制由mybatis -->
		<transactionManager type="JDBC"/>
	<!-- 数据库连接池,由mybatis管理 -->
		<dataSource type="POLLED">
			<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>
	</environments>
	<!-- 加载 映射文件 -->
	<mappers>
		<mapper resource="sqlmap/User.xml"/>
	</mappers>
</configuration>

第三步、编写User.java中的内容,如下所示:

package cn.itcast.mybatis.po;

import java.util.Date;

/**
 *
 * <p>Title: User</p>
 * <p>Description:用户po </p>
 * @author	丁国华
 * @date	2016年7月31日 15:39:04
 * @version 1.0
 */
public class User {

	//属性名和数据库表的字段对应
	private int id;
	private String username;// 用户姓名
	private String sex;// 性别
	private Date birthday;// 生日
	private String address;// 地址
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
	public Date getBirthday() {
		return birthday;
	}
	public void setBirthday(Date birthday) {
		this.birthday = birthday;
	}
	public String getAddress() {
		return address;
	}
	public void setAddress(String address) {
		this.address = address;
	}
	@Override
	public String toString() {
		return "User [id=" + id + ", username=" + username + ", sex=" + sex
				+ ", birthday=" + birthday + ", address=" + address + "]";
	}

}

第四步、实现增删改查的功能,首先编写User.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命名空间,作用就是对sql进行分类化管理,理解sql隔离
注意:使用mapper代理方法开发,namespace有特殊重要的作用-->
<mapper namespace="test">

	<!-- 在 映射文件中配置很多sql语句 -->
	<!-- 需求:通过id查询用户表的记录 -->
	<!-- 通过 select执行数据库查询
	id:标识 映射文件中的 sql
	将sql语句封装到mappedStatement对象中,所以将id称为statement的id
	parameterType:指定输入 参数的类型,这里指定int型
	#{}表示一个占位符号
	#{id}:其中的id表示接收输入 的参数,参数名称就是id,如果输入 参数是简单类型,#{}中的参数名可以任意,可以value或其它名称

	resultType:指定sql输出结果 的所映射的java对象类型,select指定resultType表示将单条记录映射成的java对象。
	 -->
	 	<select id="findUserById" parameterType="int" resultType="cn.itcast.mybatis.po.User">
		SELECT * FROM USER WHERE id=#{value}
	</select>

	<!-- 根据用户名称模糊查询用户信息,可能返回多条
	resultType:指定就是单挑记录所映射的java对象类型
	${}:表示拼接sql串,将接收到参数的内容不加任何修饰拼接到sql中。
	使用${}拼接sql,引起sql注入
	${value}:接收输入参数的内容,如果传入类型是简单类型,${}中只能使用value -->
	<select id="findUserByName" parameterType="java.lang.String" resultType="cn.itcast.mybatis.po.User">
		SELECT * FROM USER WHERE username LIKE '%${value}%'
	</select>	

	<!-- 添加用户
	parameterType:指定输入参数类型是pojo(包括用户信息)
	#{}中指定pojo的属性名,接收到pojo对象的属性值,mybatis通过OGNL获取对象的属性值 -->
	<insert id="insertUser" parameterType="cn.itcast.mybatis.po.User">
	<!-- 将插入数据的主键返回,返回到user对象中
	SELECT LAST_INSERT_ID():得到刚刚insert进去记录的主键值,只适用于自增主键
	keyProperty:将查询得到主键值设置到parameterType指定的对象的那个属性
	order:SELECT LAST_INSERT_ID()执行顺序,相对于insert语句来说她的执行顺序
	resultType:指定SELECT LAST_INSERT_ID()的结果类型
	 -->
	 <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
	 	SELECT LAST_INSER_ID()
	 </selectKey>
		insert into user(username,birthday,sex,address) value(#{username},#{birthday},#{sex},#{address})
		<!-- 使用mysql的uuid()函数生成主键
		执行过程,首先通过uuid得到主键,将主键设置到user对象的id属性中
		其次,在insert执行的时候,从user对象中,取出id属性值 -->
		<selectKey keyProperty="id" order="BEFORE" resultType="java.lang.String">
			SELECT uuid()
		</selectKey>
		insert into user(username,birthday,sex,address) value(#{username},#{birthday},#{sex},#{address});
	</insert>
	<!-- 删除用户
	根据id删除用户,需要输入id值 -->
	<delete id="deleteUser" parameterType="java.lang.Integer">
		delete from user where id=#{id}
	</delete>

	<!-- 根据id更新用户
	分析:
	需要传入用户的id
	需要传入用户的更新信息
	parameterType指定user对象,包括 id和更新信息,注意:id必须存在
	#{id}:从输入 user对象中获取id属性值
	 -->
	<update id="updateUser" parameterType="cn.itcast.mybatis.po.User">
		update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address}
		 where id=#{id}
	</update>

</mapper>

第五步、编写具体的方法,如下所示:

package cn.itcast.mybatis.first;

import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;

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 org.junit.Test;

import cn.itcast.mybatis.po.User;

public class MybatisFirst {

	// 根据id查询用户信息,得到一条记录结果
	@Test
	public void findUserByIdTest() throws IOException {

		// mybatis配置文件
		String resource = "SqlMapConfig.xml";
		// 得到配置文件流
		InputStream inputStream = Resources.getResourceAsStream(resource);

		// 创建会话工厂,传入mybatis的配置文件信息
		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
				.build(inputStream);

		// 通过工厂得到SqlSession
		SqlSession sqlSession = sqlSessionFactory.openSession();

		// 通过SqlSession操作数据库
		// 第一个参数:映射文件中statement的id,等于=namespace+"."+statement的id
		// 第二个参数:指定和映射文件中所匹配的parameterType类型的参数
		// sqlSession.selectOne结果 是与映射文件中所匹配的resultType类型的对象
		// selectOne查询出一条记录
		User user = sqlSession.selectOne("test.findUserById", 1);

		System.out.println(user);

		// 释放资源
		sqlSession.close();

	}

	//根据用户名称模糊查询用户列表
	@Test
	public void findUserByNameTest() throws IOException{
		//mybatis配置文件
		String resource ="SqlMapConfig.xml";
		//得到配置文件
		InputStream inputStream = Resources.getResourceAsStream(resource);

		//创建会话工厂,传入mybatis的配置文件信息
		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

		//通过工厂得到SqlSession
		SqlSession sqlSession = sqlSessionFactory.openSession();

		//List中的user和映射文件中德resultType所指定的类型一致
		List<User> list = sqlSession.selectList("test.findUserByName","小明");
		System.out.println(list);
		sqlSession.close();
	}

	public void insertUserTest() throws IOException{
		//mybatis配置文件
		String resource ="SqlMapConfig";
		//得到配置文件流
		InputStream inputStream = Resources.getResourceAsStream(resource);

		//创建会话工厂,传入mybatis的配置文件信息
		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

		//通过工厂得到sqlsession
		SqlSession sqlSession = sqlSessionFactory.openSession();
		//插入用户对象
		User user = new User();
		user.setUsername("丁国华");
		user.setBirthday(new Date());
		user.setSex("1");
		user.setAddress("安徽合肥");

		//list中的user和映射文件中的resultType所指定的类型一直
		sqlSession.insert("test.insertUser",user);

		//提交事物
		sqlSession.commit();

		//关闭会话
		sqlSession.close();

	}

	//根据id删除用户信息
	@Test
	public void deleteUserTest() throws IOException{
		//mybatis配置文件
		String resource = "SqlMapConfig.xml";
		//得到配置文件流
		InputStream inputStream = Resources.getResourceAsStream(resource);
		//创建工厂,传入mybatis的配置文件信息
		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
		//通过工厂得到SqlSession
		SqlSession sqlSession = sqlSessionFactory.openSession();
		//传入id删除用户
		sqlSession.delete("test.deleteUser",39);

		//提交事物
		sqlSession.commit();
		//关闭会话
		sqlSession.close();

	}

	// 更新用户信息
		@Test
		public void updateUserTest() throws IOException {
			// mybatis配置文件
			String resource = "SqlMapConfig.xml";
			// 得到配置文件流
			InputStream inputStream = Resources.getResourceAsStream(resource);

			// 创建会话工厂,传入mybatis的配置文件信息
			SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
					.build(inputStream);

			// 通过工厂得到SqlSession
			SqlSession sqlSession = sqlSessionFactory.openSession();
			// 更新用户信息

			User user = new User();
			//必须设置id
			user.setId(41);
			user.setUsername("丁国华");
			user.setBirthday(new Date());
			user.setSex("2");
			user.setAddress("安徽合肥");

			sqlSession.update("test.updateUser", user);

			// 提交事务
			sqlSession.commit();

			// 关闭会话
			sqlSession.close();

		}

}

mybatis的优缺点
优点:
a、易于上手和掌握。
b、sql写在xml里,便于统一管理和优化。
c、 解除sql与程序代码的耦合。
d、提供映射标签,支持对象与数据库的orm字段关系映射
e、提供对象关系映射标签,支持对象关系组建维护
f、提供xml标签,支持编写动态sql。
缺点:
a、 sql工作量很大,尤其是字段多、关联表多时,更是如此。
b、sql依赖于数据库,导致数据库移植性差。
c、 由于xml里标签id必须唯一,导致DAO中方法不支持方法重载。
d、DAO层过于简单,对象组装的工作量较大。
e、 缓存使用不当,容易产生脏数据。

mybatis和hibernate的对比
相同点:Hibernate和mybatis都可以是通过SessionFactoryBuilder由xml配置文件生成SessionFactory,然后由

SessionFactroy生成Session,最后由Session来开启执行事物和SQL语句,其中SessionFactoryBuider、

SessionFactory、Session的生命周期都是差不多的。

不同点:

mybatis:小巧、方便、高效、简单、直接、半自动;

hibernate:强大、方便、高效、复杂、绕弯子、全自动;

mybatis:

a、入门简单,即学即用,提供了数据库查询的自动对象绑定功能,而且延续了很多的SQL使用经验,对于没有

那么高的对象模型要求的项目来说,堪称perfect。

b、 可以进行更为细致的SQL优化,可以减少查询字段。

c、 缺点就是框架还是比较简陋,功能尚有缺失,虽然简化了数据绑定代码,但是整个底层数据库查询实际还是

要自己写的,工作量也比较大,而且不太容易适应快速数据库修改。
d、 二级缓存机制不佳。
       hibernate:
       a、功能强大,数据库无关性好,O/R映射能力强,如果你对Hibernate相当精通,而且对Hibernate进行了适当的

封装,那么你的项目整个持久层代码会相当简单,需要写的代码很少,开发速度很快,非常爽。
       b、有更好的二级缓存机制,可以使用第三方缓存。
       c、缺点就是学习门槛不低,要精通门槛更高,而且怎么设计O/R映射,在性能和对象模型之间如何权衡取得平衡

,以及怎样用好Hibernate方面需要你的经验和能力都很强才行。

举个形象的比喻:
        mybatis:机械工具,使用方便,拿来就用,但工作还是要自己来作,不过工具是活的,怎么使由我决定。
        hibernate:智能机器人,但研发它(学习、熟练度)的成本很高,工作都可以摆脱他了,但仅限于它能做的事。

小编寄语:该博文,小编主要简单的介绍了mybatis的基本知识,包括一个简单的增删改查的demo,mybatis的

优缺点,以及hibernate和mybatis的对比,她们之间的相同点和不同点,mybatis简单来说,就是一个持久层的框架,

mybatis让程序将主要精力放在sql上,通过mybatis提供的映射方式,自由灵活生成满足需要的sql语句,mybatis可以

将向preparedStatement中的输入参数自动进行输入映射,将查询结果集灵活映射成java对象。

【mybatis深度历险系列】mybatis的框架原理+入门程序解析的更多相关文章

  1. 【mybatis深度历险系列】mybatis中的输入映射和输出映射

    在前面的博文中,小编介绍了mybatis的框架原理以及入门程序,还有mybatis中开发到的两种方法,原始开发dao的方法和mapper代理方法,今天博文,我们来继续学习mybatis中的相关知识,随 ...

  2. 【mybatis深度历险系列】深入浅出mybatis中原始dao的开发和mapper代理开发

    使用Mybatis开发Dao,通常有两个方法,即原始Dao开发方法和Mapper接口开发方法.mybatis在进行dao开发的时候,涉及到三姐妹,分别是SqlSessionFactoryBuilder ...

  3. 【mybatis深度历险系列】延迟加载

    在前面的博文中,小编主要简单的介绍了mybatis中的高级映射,小伙伴们可以把mybatis和hibernate的因素进行对比,更加有利于理解.今天这篇博文,小编主要来简单介绍一下mybatis中的延 ...

  4. 【mybatis深度历险系列】mybatis中的高级映射一对一、一对多、多对多

    学习hibernate的时候,小编已经接触多各种映射,mybatis中映射有到底是如何运转的,今天这篇博文,小编主要来简单的介绍一下mybatis中的高级映射,包括一对一.一对多.多对多,希望多有需要 ...

  5. 【mybatis深度历险系列】mybatis中的动态sql

    最近一直做项目,博文很长时间没有更新了,今天抽空,学习了一下mybatis,并且总结一下.在前面的博文中,小编主要简单的介绍了mybatis中的输入和输出映射,并且通过demo简单的介绍了输入映射和输 ...

  6. Spring+SpringMVC+MyBatis深入学习及搭建(十三)——SpringMVC入门程序(二)

    1.非注解的处理器映射器和适配器 1.1非注解的处理器映射器 前面我们配置的org.springframework.web.servlet.handler.BeanNameUrlHandlerMapp ...

  7. 分布式Redis深度历险-Cluster

    本文为分布式Redis深度历险系列的第三篇,主要内容为Redis的Cluster,也就是Redis集群功能. Redis集群是Redis官方提供的分布式方案,整个集群通过将所有数据分成16384个槽来 ...

  8. 分布式Redis深度历险-复制

    Redis深度历险分为两个部分,单机Redis和分布式Redis. 本文为分布式Redis深度历险系列的第一篇,主要内容为Redis的复制功能. Redis的复制功能的作用和大多数分布式存储系统一样, ...

  9. Mybatis系列(一)入门

    Mybatis系列(一)入门 mybatis简介 MyBatis 是支持普通 SQL 查询,存储过程和高级映射的优秀持久层框架.MyBatis 消除 了几乎所有的 JDBC 代码和参数的手工设置以及结 ...

随机推荐

  1. C# 打开文件夹和保存文件夹

    OpenFileDialog sfd = new OpenFileDialog(); sfd.ShowDialog(); this.textBox1.Text = sfd.FileName; Save ...

  2. 关于div包裹img,底下多出3px间隙的问题

    背景:昨天写过一个div包裹图片的html,已经reset了所有的div,但还是发现img与div底部会有3px的间距,我检查了所有的css,发现并未发现什么问题,结果度娘了一下,发现好多朋友都遇到了 ...

  3. leetcode 717. 1-bit and 2-bit Characters -easy

    https://leetcode.com/problems/1-bit-and-2-bit-characters/description/ We have two special characters ...

  4. [LeetCode] Fraction Addition and Subtraction 分数加减法

    Given a string representing an expression of fraction addition and subtraction, you need to return t ...

  5. [LeetCode] Longest Harmonious Subsequence 最长和谐子序列

    We define a harmonious array is an array where the difference between its maximum value and its mini ...

  6. MySQL 并行复制从库发生自动重启分析

    并行复制从库发生自动重启分析 背景 半同步复制从库在晚上凌晨2点半发生自动重启,另一个异步复制从库在第二天凌晨3点也发生了自动重启. 分析 版本mysql 5.7.16 mysql> show ...

  7. Centos6.9连接工具设置

    由于vm下面的centos6.9这种操作环境非常的不友好,用起来非常的不方便, 所以我们需要用一个远程连接工具来连接,我们的虚拟机.我们使用的是teraterm. 下载地址:https://osdn. ...

  8. python3爬取女神图片,破解盗链问题

    title: python3爬取女神图片,破解盗链问题 date: 2018-04-22 08:26:00 tags: [python3,美女,图片抓取,爬虫, 盗链] comments: true ...

  9. 洛谷4月月赛R1

    T1.题目大意:n个人站成一排,有m个团队,每个人有且属于一个团队,可以让若干个人出队,任意交换这些人的位置后再站回去,问要让所有同一团队的人连续地站在一起,至少要出队几个.(n<=10^5,m ...

  10. hdu 3473 划分树

    Minimum Sum Time Limit: 16000/8000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Tot ...