- 为什么要学习Mybatis?
- Mybatis简化了哪些流程?
1、为什么要学习Mybatis?
下面的是一段JDBC的代码,我们写原生的JDBC代码时,会有一些模板代码,比如加载驱动,创建连接,预处理,封装sql,封装结果集。这种模板代码太多了,导致我们要发大量的时间在这些事情上。Mybatis就是帮助我们解决这样的模板代码。这就是ORM框架流行的原因,虽然Mybatis称不上是一个ORM框架,因为它没有把表的关系完全映射成对象的关系,我们还要写sql,只是Mybatis把“输入”与“输出”映射成了对象,这样的话,就不需要我们封装sql与结果集了。
那为什么不使用Hibernate这种真正的ORM框架了,Hibernate封装的太彻底了,一旦涉及的SQL的优化,它就比较难了。而且Hibernate由于是完全操作的是对象,也就是在ORM映射配置的时候,是比较难的,很难了解是外键关联还是怎样,因为它完全屏蔽了SQL,这样的话,不太好看出关系。
2、Mybatis简化了哪些流程?
2.1、例子
下面的例子我们先采用ibatis的方式实现,也就是DAO的接口与实现都是我们实现,不采用cglib创建DAO的实现类。
2.1.1、pom依赖
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.2.7</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.17</version>
</dependency>
<!-- Mybatis会采用cglib创建DAO的实现类(*MapperImpl) -->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.17.1-GA</version>
</dependency>
2.1.2、user表
2.1.3、定义PO
2.1.4、DAO接口
2.1.5、DAO的实现
public class UserDaoImpl implements UserDao {
/**
* SqlSessionFactory是一个工厂,那就是线程安全的,也就是它最好用单例的方式实现
* SqlSession不是线程安全的,可以采用在线程栈的方式或者ThreadLocal的方式。
*/
private SqlSessionFactory sqlSessionFactory;
public UserDaoImpl(SqlSessionFactory sqlSessionFactory){
this.sqlSessionFactory = sqlSessionFactory;
}
public User findUserById(int userid) throws Exception{
SqlSession sqlSession = sqlSessionFactory.openSession();
User user = sqlSession.selectOne("test.findUserById",userid);
return user;
}
public List<User> findAll() throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
List<User> userList = sqlSession.selectList("test.findAll");
return userList;
}
public List<User> findUsersByName(String username) throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
List<User> userList = sqlSession.selectList("test.findAll","王五");
return userList;
}
public void addUser(User user) throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
sqlSession.insert("test.addUser", user);
sqlSession.commit();
}
public void updateUser(User user) throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
sqlSession.update("test.updateUser", user);
sqlSession.commit();
}
public void deleteUserById(int userid) throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
sqlSession.delete("test.deleteUserById", userid);
//mybatis默认是不自动提交的,所以一定要调用下面的commit()方法,
//提交在控制台打印[Committing JDBC Connection]
sqlSession.commit();
}
}
注意:sqlSession要关闭,我上面省略了sqlSession.close()。另外除了查询的话,要调用下面的这个方法,sqlSession.commit()。要不然不会提交,因为Mybatis的默认设置不是自动提交。在日志中看到[Committing JDBC Connection]的话,代表提交了,是Debug级别的日志。
2.1.6、配置映射文件
这个映射文件其实可以看做跟Hibernate差不多,只是Mybatis里面配置了“输入”与“输出”的映射,其它的还是配置的SQL。这个映射文件的名字最好采用与类名一致,方便它人阅读。
<?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中,最好一个PO类对应一个DAO,对应一个Mapper,在通过配置namespace,
使得Mapper之间隔离。也就是要访问Mapper里面的东西的时候,必须加上namespace。
在Mapper配置中,里面有<select>、<insert>、<update>、<delete>等标签,代表你要做的事情
配置如下:
id:id就是我们的SQLSession中要传入的id,但是要加上namespace方式,语法:namespace.id,
如下面的代码:
User user = sqlSession.selectOne("test.findUserById",userid);
parameterType:参数类型,这个代表你传入参数的类型,如果是基本类型的话,下面的#{value}
的名字随便,#{name}代表取传入的参数的值。如实是PO的话,就要采用OGNL的方式
获取参数。比如下面传入的是User对象的话,#{id},#{username},这个id与username
就是对象的属性。
resultType:输出参数的类型,也就是在查询某些表的数据的时候,只要表的字段与User类的属性名
一致的话,就会封装要User对象中。如果不一致的话,要采用resultMap的方式。也可以是基本类型。
-->
2.1.7、Mybatis的配置
注意:useUnicode=true&characterEncoding=utf8
http://blog.163.com/cn_dreamgo/blog/static/52679452201272745826905/
2.2、测试
2.3、总结
编写Mybatis代码,我们可以看得出,那些模板代码都全没有了,我们只通过Mybatis的配置得到的SqlSessionFactory,然后得到SqlSession,然后用它操作数据库。它里面封装了select/insert等等操作数据库的api。大大的简化了我们的开发,我们只要把对应的sql配置到我们的映射配置中即可,另外输入与输出参数都可以在里面配置。
有没有那种方式可以把DAO的实现也不用实现了呢?可以采用Mapper的方式,我们只要写DAO接口,也叫Mapper接口。因为在映射文件中配置id、输入、输出,我们的DAO实现也就要用到这几个,完全可以实现。下面的一篇博客将讲解必须要遵循哪些约定。
#{value}与%{value}的区别,#{value}取值,而%{value}是用来字符串拼接的,比如我们要做模糊匹配的话,不想子传入参数就把模糊匹配的字符串传入的话,就可以采用这种方式。
关于Mybatis的流程,可以如以下流程,下面是网上找的图: