在前面的博文中,小编介绍了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. 在Unity3D中利用 RenderTexture 实现游戏内截图

    using System.Collections; using System.Collections.Generic; using System.IO; using UnityEngine; publ ...

  2. 原生JS面向对象方法实现万年历

    ###面向对象的方法实现万年历 实现思路:    1.创建构造函数constructor    ```    function Calender(main){         this.current ...

  3. Chtholly Nota Seniorious

    题目背景 大样例下发链接: https://pan.baidu.com/s/1nuVpRS1 密码: sfxg こんなにも.たくさんの幸せをあの人に分けてもらった だから.きっと 今の.私は 谁が何と ...

  4. bzoj5055 膜法师

    Description 在经历过1e9次大型战争后的宇宙中现在还剩下n个完美维度, 现在来自多元宇宙的膜法师,想偷取其中的三个维度为伟大的长者续秒, 显然,他能为长者所续的时间,为这三个维度上能量的乘 ...

  5. Codeforces Round #460 D. Karen and Cards

    Description Karen just got home from the supermarket, and is getting ready to go to sleep. After tak ...

  6. 51nod 1770 数数字

    1770 数数字 基准时间限制:1 秒 空间限制:262144 KB 分值: 20 难度:3级算法题  收藏  关注 统计一下 aaa ⋯ aaan个a × b 的结果里面 ...

  7. 【UOJ UNR #1】争夺圣杯

    来自FallDream的博客,未经允许,请勿转载,谢谢. 传送门 考虑直接对每个数字,统计它会产生的贡献. 单调栈求出每个数字左边第一个大等于他的数,右边第一个大于他的 (注意只能有一边取等) 假设左 ...

  8. hdu 1166 线段树(sum+单点修改)

    敌兵布阵 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submi ...

  9. spring cloud 入门系列二:使用Eureka 进行服务治理

    服务治理可以说是微服务架构中最为核心和基础的模块,它主要用来实现各个微服务实例的自动化注册和发现. Spring Cloud Eureka是Spring Cloud Netflix 微服务套件的一部分 ...

  10. Ubuntu16.04下安装jdk1.8过程

    笔者环境:腾讯云服务器 Ubuntu16.04 x64 一 . 去oracle官网下载对应的jdk 下载地址:http://www.oracle.com/technetwork/java/javase ...