MyBatis实战之初步
关于MyBatis与Hibernate及其JDBC的比较,大家可以参考我的这篇文章:MyBatis+Hibernate+JDBC对比分析
如果觉得这个还不够系统全面,可以自行Google或者百度。
用了MyBatis有两年了,后来觉得不好用有一定的局限性换成了MyBatis-Plus,关于MyBatis-Plus实战系列,可以参考这个链接:https://www.cnblogs.com/youcong/category/1213059.html
另外话说回来了,为什么我又要回到MyBatis?
原因有这么几个方面?
第一、MyBatis-Plus是MyBatis的升级版,MyBatis有的,MyBatis-Plus都有,MyBatis没有的,MyBatis-Plus也有,从这个角度来看,MyBatis-Plus是从MyBatis中衍生出来的,那么它们的源码可以说有一大半是一致的,只是有少部分不同,所以如果以后MyBatis-Plus不能满足我的需求,我可以自行改造,虽说码云或者Github上有不少现成的轮子可以用,但是我个人觉得,如果进入一家比较大的公司,不仅仅要知道如何投机取巧(善用现有的轮子,同时也要具备制造轮子的能力,你可以理解为深入了解源码,并熟悉其中的设计模式);
第二、如第一条所说的那样,我看过很多开源项目,有的理解透彻MyBatis,知道MyBatis生成的代码有很多局限性,就例如它的逆向工程可以避免重复编写CRUD之类的代码,但是生成的XML太繁琐,于是就有了MyBatis-Plus,但是MyBatis-Plus也并不是没有缺点的,比如它只能针对单表,而不能多表连接,也正是因为这个局限性,Jeesite的创造者才决定自行改造MyBatis,让其符合自身的需要,关于Jeesite简化MyBatis的博文,大家可以参考这个链接:https://my.oschina.net/thinkgem/blog/1503611;
第三、目前主流还是MyBatis,互联网项目大多都是MyBatis,有的公司也有自己封装的ORM框架,但是本质上基本要么是对Hibernate进行改造,要么就是对MyBatis改造,下面我贴一下关于MyBatis的图给大家看看:
从这张图,大家可以知道MyBatis和MyBatis-Plus在开源项目都彼此占用;
有人说,现在博客上有很多关于MyBatis的,你写这个是不是有点多余的,我对此的回答是,不多余。就好比读书,每个人读一本书一遍或者两遍及其以上,感触肯定是不一样的。很多东西当初的时候不知道是什么意思,回过头来,你会发现,你可以发现一些不一样的东西,这个东西,你可以理解为举一反三或是融会贯通。
下面进入正题,关于MyBatis的学习,我当初是参考孤傲苍狼的博客。今天在写这篇文章时,我查了官网,也搜索相关的中文教程,在w3cschool发现了关于MyBatis,但是我觉得写的不好,对于初学者和进阶者而言,简直就是乱七八糟,我知道也许这样评价会引起一些人讽刺,但是这是事实,大家可以自己看,我觉得初学者或者进阶者,特别是进阶者可以回过头再看看官网。
准备环境:Window10/8/7+JDK8/7/6或以上+MySQL
项目结构如下:
SQL脚本:
REATE TABLE `user` (
`user_id` int(8) NOT NULL AUTO_INCREMENT COMMENT '用户主键',
`login_code` varchar(20) NOT NULL COMMENT '用户编码(登录账户) 手机号 邮箱号',
`user_name` varchar(20) NOT NULL COMMENT '用户名',
`password` varchar(40) NOT NULL COMMENT '密码',
`sex` int(2) NOT NULL COMMENT '性别',
`identity_card` varchar(20) DEFAULT NULL COMMENT '身份证',
`create_time` datetime NOT NULL COMMENT '创建时间',
`create_by` varchar(10) NOT NULL COMMENT '创建人',
`update_time` datetime NOT NULL COMMENT '更新时间',
`update_by` varchar(10) NOT NULL COMMENT '更新人',
`status` int(2) NOT NULL DEFAULT '0' COMMENT '状态:0注册新用户 1邮件认证用户 2管理员 3黑名单',
PRIMARY KEY (`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
一、导入依赖
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.youcong.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>0.0.1-SNAPSHOT</version> <dependencies>
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency> <!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency> </dependencies>
</project>
二、编写实体类
package com.blog.entity; import java.io.Serializable; import java.util.Date;
import java.io.Serializable; public class User{ private static final long serialVersionUID = 1L; /**
* 用户主键
*/
private Integer userId;
/**
* 用户编码(登录账户) 手机号 邮箱号
*/
private String loginCode;
/**
* 用户名
*/
private String userName;
/**
* 密码
*/
private String password;
/**
* 性别
*/
private Integer sex;
/**
* 身份证
*/
private String identityCard;
/**
* 创建时间
*/
private Date createTime;
/**
* 创建人
*/ private String createBy;
/**
* 更新时间
*/
private Date updateTime;
/**
* 更新人
*/
private String updateBy;
/**
* 状态:0注册新用户 1邮件认证用户 2管理员 3黑名单
*/
private Integer status; public Date getUpdateTime() {
return updateTime;
} public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
} public static long getSerialversionuid() {
return serialVersionUID;
} public Integer getUserId() {
return userId;
} public void setUserId(Integer userId) {
this.userId = userId;
} public String getLoginCode() {
return loginCode;
} public void setLoginCode(String loginCode) {
this.loginCode = loginCode;
} public String getUserName() {
return userName;
} public void setUserName(String userName) {
this.userName = userName;
} public String getPassword() {
return password;
} public void setPassword(String password) {
this.password = password;
} public Integer getSex() {
return sex;
} public void setSex(Integer sex) {
this.sex = sex;
} public String getIdentityCard() {
return identityCard;
} public void setIdentityCard(String identityCard) {
this.identityCard = identityCard;
} public Date getCreateTime() {
return createTime;
} public void setCreateTime(Date createTime) {
this.createTime = createTime;
} public String getCreateBy() {
return createBy;
} public void setCreateBy(String createBy) {
this.createBy = createBy;
} public String getUpdateBy() {
return updateBy;
} public void setUpdateBy(String updateBy) {
this.updateBy = updateBy;
} public Integer getStatus() {
return status;
} public void setStatus(Integer status) {
this.status = status;
} }
三、编写数据访问层及其对应的XML文件
package com.blog.dao; import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select; import com.blog.entity.User; public interface UserDao {
@Select("select * from `user` where user_id=#{userId}")
@Results(@Result(property="userName",column="user_name"))
User selectOne(int userId); }
@Select是MyBatis的注解写法,当字段名和属性名一致时,可以直接@Select不需要@Results,@Results的作用就是因为实体属性与字段不一致,为了获取查询结果,必须要这样。
当然了你也可以不写注解,直接在对应的UserDao.xml写,如果是UserDao.xml里面写的话,就会变成这样
package com.blog.dao; import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select; import com.blog.entity.User; public interface UserDao { User selectOne(int userId); }
需要在UserDao.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.blog.dao.UserDao"> <!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="com.blog.entity.User">
<id column="user_id" property="userId" />
<result column="login_code" property="loginCode" />
<result column="user_name" property="userName" />
<result column="password" property="password" />
<result column="sex" property="sex" />
<result column="identity_card" property="identityCard" />
<result column="create_time" property="createTime" />
<result column="create_by" property="createBy" />
<result column="update_time" property="updateTime" />
<result column="update_by" property="updateBy" />
<result column="status" property="status" />
</resultMap> <!-- 通用查询结果列 -->
<sql id="Base_Column_List">
user_id, login_code, user_name, password, sex, identity_card, create_time, create_by, update_time, update_by, status
</sql>
<select id="selectOne" resultMap="BaseResultMap"> select * from `user` where user_id=#{userId} </select> </mapper>
除了<select>标签之外,还有<insert>、<update>、<delete>,它们的作用分别是查、增、更、删。当然了,还有这里面可以<sql>,这个<sql>的作用就是为了复用重复列,省的重复编写代码冗余。如果要引用,写成这样既可
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
user_id, login_code, user_name, password, sex, identity_card, create_time, create_by, update_time, update_by, status
</sql> <select id="selectOne" resultMap="BaseResultMap">
select <include refid="Base_Column_List"/>
from `user` where user_id=#{userId}
</select>
MyBatis常用的两种写法,XML方式和注解方式,但是无论你采用哪种,对应的XML文件必须要存在。
其实<resultMap id="BaseResultMap" type="com.blog.entity.User"> 可以变成 <resultMap id="BaseResultMap" type="User">
前提必须要在mybatis-config.xml配置
<typeAliases>
<typeAlias type="com.blog.entity.User" alias="User"/>
</typeAliases>
但是有人觉得,如果我的类有很多,岂不是要配置很多,太麻烦了,别怕,MyBatis已经为你想到了
<typeAliases>
<package name="com.blog.entity"/>
</typeAliases>
这样配置就解决了重复配置的麻烦
其实除了这样,如果你想标新立异点,还可以再实体最上面加上@Alias注解
这就是MyBatis的别名三种方式/策略。
四、编写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>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/blog_test"/>
<property name="username" value="root"/>
<property name="password" value="1234"/>
</dataSource>
</environment>
</environments> <mappers>
<mapper resource="mybatis/mapping/UserDao.xml"/>
</mappers>
</configuration>
mybatis-config.xml这个配置没多大用,坦白说。
因为后期与Spring整合由Spring来管理数据库连接池对象。
不过还是要稍微讲讲,以让读者达到开卷有益的目的或者是让没有学过的或者已经学过但是不知道的涨涨见识。
<environment id="development">表示我们默认使用development配置环境
<transactionManager type="JDBC"/> 采用JDBC的事务管理模式
<dataSource type="POOLED"> 数据库连接信息
<mappers> 映射器 通常一般映射XML文件
五、编写工具类
package com.blog.config; import java.io.IOException;
import java.io.InputStream; import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder; public class SqlSessionFactoryUtils { private static SqlSessionFactory sqlSessionFactory = null; public static SqlSessionFactory getSqlSessionFactory() {
InputStream is = null;
if(sqlSessionFactory==null) { String resource = "mybatis/mybatis-config.xml";
try {
sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream(resource));
return sqlSessionFactory;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} } return sqlSessionFactory;
} }
说到上述代码,顺便谈谈MyBatis的核心组件。它的核心组件主要有这么几个,如下所示:
SqlSessionFactoryBuilder:它会根据配置信息或者代码来生成SqlSessionFactory;
SqlSessionFactory:依赖工厂生成SqlSession;
SqlSession:是一个即可发送SQL执行返回结果,也可以获取Mapper接口;
Sql Mapper:它是MyBatis的新设计组件,它是由一个Java接口和XML文件(或注解)构建,需要给出对应的SQL和映射规则。它负责发送SQL去执行并返回结果。
用一张图来表示它们之间的关系,如图:
它们的生命周期在此稍微说一下:
(1)SqlSessionFacotoryBuilder
SqlSessionFacotoryBuilder是利用XML和Java代码获得资源来构建SqlSessionFactory的,通过它可以构建多个SqlSessionFactory,它的作用就是一个构建器,一旦我们构建了SqlSessionFactory,它的作用就完结,它就失去存在的意义。这时我们应该毫不犹豫的废弃它,将它回收。所以它的生命周期只存在方法局部,它的作用就是生成SqlSessionFactory。
(2)SqlSessionFactory的作用是创建SqlSession,而SqlSession就是一个会话,相当于JDBC中的Connection对象。每次应用程序需要访问数据库,我们就要通过SqlSessionFactory创建SqlSession,所以SqlSessionFactory应该在MyBatis应用的整个生命周期中。而如果我们多次创建同一个数据库的SqlSessionFactory,则每次创建SqlSessionFactory会打开更多的数据库连接资源,那么连接资源就很快会被耗尽。因此SqlSessionFactory的责任是唯一的,它的责任就是创建SqlSession,所以我们果断采用单例模式。如果采用多例,那么它对数据库连接的消耗是很大的,不利于我们统一管理。所以正确的做法是使得每个数据库只对应一个SqlSessionFactory,管理好数据库资源分配,避免过多的Connection被消耗。
(3)SqlSession
SqlSession是一个会话,相当于JDBC的一个Connection对象,它的生命周期应该是在请求数据库处理事务的过程中。它是一个线程不安全的对象,在涉及多线程的时候我们需要特别当心,操作数据库需要注意其隔离级别,数据库锁等高级特性。此外,每次创建的SqlSession都必须及时关闭它,它长期存在就会使数据库连接池的活动资源减少,对系统性能的影响很大。
(4)Mapper
Mapper是一个接口,而没有任何实现类,它的作用是发送SQL,然后返回我们需要的结果,或者执行SQL从而修改数据库的数据,因此它应该在一个SqlSession事务方法之内,是一个方法级别的东西。它就如同JDBC中的一条SQL语句的执行,它的最大范围和SqlSession是相同的。尽管我们想一直保存着Mapper,但是你会发现它很难控制,所以尽量在一个SqlSession事务的方法中使用它们,然后废弃掉。
MyBatis组件生命周期,如图:
六、测试
package mybatis; import org.apache.ibatis.session.SqlSession;
import org.junit.Test; import com.blog.config.SqlSessionFactoryUtils;
import com.blog.dao.UserDao;
import com.blog.entity.User; public class MyBatisTest { @Test
public void testName() throws Exception {
SqlSession sqlSession = null;
sqlSession = SqlSessionFactoryUtils.getSqlSessionFactory().openSession(); UserDao userDao = sqlSession.getMapper(UserDao.class); User user = userDao.selectOne(1);
System.out.println(user.getUserName());
}
}
小结:
通过这篇文章,你可以达到能够知道怎么使用MyBatis和了解熟悉它的相关执行原理和对应的生命周期,希望能给大家带来有益的启发和收获。
本文参考:
《深入浅出MyBatis技术原理和实战》
MyBatis官网:http://www.mybatis.org/mybatis-3/
MyBatis实战之初步的更多相关文章
- MyBatis实战之解析与运行
本次所谈的原理仅仅只涉及基本的框架和核心代码,并不会全部都说到,比如关于MyBatis是如何解析XML文件和其他配置文件从而的到内容,还有就是JDBC如何使用,关于JDBC如何使用,可以参考我的这篇博 ...
- MyBatis实战之动态SQL
如果使用JDBC或者其他框架,很多时候你得根据需要去拼接SQL,这是一个麻烦的事情,而MyBatis提供对SQL语句动态的组装能力,而且它只有几个基本的元素,非常简单明了,大量的判断都可以在MyBat ...
- MyBatis实战之配置
MyBatis最重要的配置也就两个,一个是mybatis-config.xml,又称MyBatis的全局配置,另一个就是XXXDao.xml或XXXMapper.xml映射配置. mybatis-co ...
- mybatis实战教程(mybatis in action),mybatis入门到精通
转自:http://www.yihaomen.com/article/java/302.htm (读者注:其实这个应该叫做很基础的入门一下下,如果你看过hibernate了那这个就非常的简单) (再加 ...
- mybatis实战教程(mybatis in action),mybatis入门到精通(转)
转自:http://www.yihaomen.com/article/java/302.htm (读者注:其实这个应该叫做很基础的入门一下下,如果你看过Hibernate了那这个就非常的简单) (再加 ...
- 【转】mybatis实战教程(mybatis in action),mybatis入门到精通
MyBatis 目录(?)[-] mybatis实战教程mybatis in action之一开发环境搭建 mybatis实战教程mybatis in action之二以接口的方式编程 mybatis ...
- 转)mybatis实战教程(mybatis in action),mybatis入门到精通
mybatis实战教程(mybatis in action),mybatis入门到精通 http://limingnihao.iteye.com/blog/781671 http://blog.csd ...
- 1.mybatis实战教程mybatis in action之一开发环境搭建
转自:https://www.cnblogs.com/shanheyongmu/p/5652471.html 什么是mybatis MyBatis是支持普通SQL查询,存储过程和高级映射的优秀持久层框 ...
- mybatis实战教程(mybatis in action)之九:mybatis 代码生成工具的使用
mybatis 应用程序,需要大量的配置文件,对于一个成百上千的数据库表来说,完全手工配置,这是一个很恐怖的工作量. 所以mybatis 官方也推出了一个mybatis代码生成工具的jar包. 今天花 ...
随机推荐
- Java基本——数据类型
一.创建一个简单的Java应用程序 public class Code { public static void main(String[]args) { System.out.println(&qu ...
- CentOs 7.3下ELK日志分析系统搭建
系统环境 为了安装时不出错,建议选择这两者选择一样的版本,本文全部选择5.3版本. System: Centos release 7.3 Java: openjdk version "1.8 ...
- python-装饰器模式
源码地址:https://github.com/weilanhanf/PythonDesignPatterns 说明: 有时为了给某个对象而不是给整个类添加一个功能,使用继承机制是添加功能的一个有效途 ...
- Spring AOP 中@Pointcut的用法
Spring Aop中@pointCut的用法,格式:execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? nam ...
- Android系统执行Java jar程序 -- dalvik运行dex Java工程
本文仅针对纯java工程执行进行诠释,一般在PC平台作为jar包形式存在,在Android平台则以dex包形式存在. Java属于高级程序语言,Java程序需要运行在特定的虚拟机中,虚拟机将Java字 ...
- chromium os系统编译与环境搭建
官方网址:http://www.chromium.org/chromium-os chromium os是google自2009年开启的项目,是一款开源的电脑操作系统,用于开发chromium/chr ...
- Python Django框架笔记(五):模型
#前言部分来自Django Book (一) 前言 大多数web应用本质上: 1. 每个页面都是将数据库的数据以HTML格式进行展现. 2. 向用户提供修改数据库数据的方法.(例如:注册.发表评 ...
- 【转】Linux---centos安装配置并挂载NFS
转自:http://blog.csdn.net/loyachen/article/details/51010688 [系统环境] CentOS release 6.7 (Final) 服务端配置 1. ...
- 七牛云A账号数据迁移到B账号下
1,七牛云A账号下开启空间授权,可以让B账号可以访问A账号下的空间,,授予权限只读即可. 2,下载七牛云命令行工具.(通过命令完成数据迁移) https://dn-devtools.qbox.me/2 ...
- 关于 Azure Windows VM 的磁盘和 VHD
就像其他任何计算机一样,Azure 中的虚拟机将磁盘用作存储操作系统.应用程序和数据的位置. 所有 Azure 虚拟机都至少有两个磁盘,即 Windows 操作系统磁盘和临时磁盘. 操作系统磁盘基于映 ...