SSM————Mybatis(1)
一、基本概念:
Mybatis是apache的一个开源项目iBtis,2010年这个项目由apache software foundation迁移到google code,并且改名MyBatis,2013年11月迁移到GitHub。
Mybatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注SQL本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。
Mybatis通过xml或注解的方式将要执行的各种statement(statement、prepareStatement、CallableStatement)配置起来,并通过java对象和statement中的sql进行映射生成最终执行的sql语句,最后Mybatis框架执行sql并将结果映射成java对象返回。
与jdbc相比较:
jdbc出现以下缺点:
1、 数据库连接创建、释放频繁造成系统资源浪费,从而影响系统性能。如果使用数据库连接池可解决此问题。
2、 Sql语句在代码中硬编码,造成代码不易维护,实际应用中sql变化的可能较大,sql变动需要改变java代码。
3、 使用preparedStatement向占有位符号传参数存在硬编码,因为sql语句的where条件不一定,可能多也可能少,修改sql还要修改代码,系统不易维护。
对结果集解析存在硬编码(查询列名),sql变化导致解析代码变化,系统不易维护,如果能将数据库记录封装成pojo对象解析比较方便。
二、Mybatis架构:

注:sqlSession中包含Executor,Executor中包含MappedStatement
1、 mybatis配置
SqlMapConfig.xml,此文件作为mybatis的全局配置文件,配置了mybatis的运行环境等信息。
mapper.xml文件即sql映射文件,文件中配置了操作数据库的sql语句。此文件需要在SqlMapConfig.xml中加载。
2、 通过mybatis环境等配置信息构造SqlSessionFactory即会话工厂
3、 由会话工厂创建sqlSession即会话,操作数据库需要通过sqlSession进行。
4、 mybatis底层自定义了Executor执行器接口操作数据库,Executor接口有两个实现,一个是基本执行器、一个是缓存执行器。
5、 Mapped Statement也是mybatis一个底层封装对象,它包装了mybatis配置信息及sql映射信息等。mapper.xml文件中一个sql对应一个Mapped Statement对象,sql的id即是Mapped statement的id。
6、 Mapped Statement对sql执行输入参数进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql前将输入的java对象映射至sql中,输入参数映射就是jdbc编程中对preparedStatement设置参数。
7、 Mapped Statement对sql执行输出结果进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql后将输出结果映射至java对象中,输出结果映射过程相当于jdbc编程中对结果的解析处理过程。
三、Mybatis入门程序:
1、mybatis的下载:
mybaits的代码由github.com管理
下载地址:https://github.com/mybatis/mybatis-3/releases
课前资料提供的mybatis如下:

其中:mybatis-3.2.7.jar mybatis的核心包
lib文件夹 mybatis的依赖包所在
mybatis-3.2.7.pdf mybatis使用手册
2、业务需求:
使用MyBatis实现以下功能:
根据用户id查询一个用户
根据用户名称模糊查询用户列表
添加用户
更新用户
删除用户
3、环境搭建:
(1)创建java工程
如下图使用之前创建的mybatis-first工程

(2)加入jar包
加入mybatis核心包、依赖包、数据驱动包。
mybatis核心包

mybatis依赖包

数据库驱动包

(3)加入配置文件
如下图创建资源文件夹config,加入log4j.properties和SqlMapConfig.xml配置文件


【1】在config下创建log4j.properties如下:(保存运行日志)
# Global logging configuration log4j.rootLogger=DEBUG, stdout # Console output... log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%
mybatis默认使用log4j作为输出日志信息。
【2】在config下创建SqlMapConfig.xml如下:(连接各个文件主要是工厂和sql的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> <!-- 和spring整合后 environments配置将废除 --> <environments default="development"> <environment id="development"> <!-- 使用jdbc事务管理 --> <transactionManager type="JDBC" /> <!-- 数据库连接池 --> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8" /> <property name="username" value="root" /> <property name="password" value="123" /> </dataSource> </environment> </environments> </configuration>
SqlMapConfig.xml是mybatis核心配置文件,配置文件内容为数据源、事务管理。
【3】效果如下:

4、创建pojo(数据封装和JavaBean类似)
pojo类作为mybatis进行sql映射使用,po类通常与数据库表对应,
数据库user表如下图:

User.java如下:
Public class User {
private int id;
private String username;// 用户姓名
private String sex;// 性别
private Date birthday;// 生日
private String address;// 地址
get/set……
5、sql映射文件(主要是书写sql语句)
在config下的sqlmap目录下创建sql映射文件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,还有一个很重要的作用,后面会讲 -->
<mapper namespace="test">
<!-- 通过id查询一个用户 -->
<select id="findUserById" parameterType="Integer" resultType="com.itheima.mybatis.pojo.User">
select * from user where id = #{v}
</select>
</mapper>
占位符:#{任意取名} select * from user where id = ? 占位符 例如:? == ‘王五’
${只能用value} select * from user where username like 字符串拼接
例子:
常用(防注入):
6、加载映射文件(让它找到sql语句)
mybatis框架需要加载Mapper.xml映射文件
将users.xml添加在SqlMapConfig.xml,如下:

前面这几步是通用的步骤,其他根据需求编写代码。
四、增删改查
五、DAO开发
使用MyBatis开发Dao,通常有两个方法,即原始Dao开发方法和Mapper动态代理开发方法。
1、需求
使用MyBatis开发DAO实现以下的功能:
根据用户id查询一个用户信息
根据用户名称模糊查询用户信息列表
添加用户信息
2、SqlSession的使用范围
SqlSession中封装了对数据库的操作,如:查询、插入、更新、删除等。
SqlSession通过SqlSessionFactory创建。
SqlSessionFactory是通过SqlSessionFactoryBuilder进行创建。
(1)SqlSessionFactoryBuilder
SqlSessionFactoryBuilder用于创建SqlSessionFacoty,SqlSessionFacoty一旦创建完成就不需要 SqlSessionFactoryBuilder了,因为SqlSession是通过SqlSessionFactory创建的。所以可以将 SqlSessionFactoryBuilder当成一个工具类使用,最佳使用范围是方法范围即方法体内局部变量。
(2)SqlSessionFactory
SqlSessionFactory是一个接口,接口中定义了openSession的不同重载方法,SqlSessionFactory的 最佳使用范围是整个应用运行期间,一旦创建后可以重复使用,通常以单例模式管理SqlSessionFactory。
(3)SqlSession
SqlSession是一个面向用户的接口,sqlSession中定义了数据库操作方法。每个线程都应该有它自己 的SqlSession实例。SqlSession的实例不能共享使用,它也是线程不安全的。因此最佳的范围是请求或方 法范围。绝对不能将SqlSession实例的引用放在一个类的静态字段或实例字段中。
打开一个 SqlSession;使用完毕就要关闭它。通常把这个关闭操作放到 finally 块中以确保每次都能执行 关闭。如下:
SqlSession session = sqlSessionFactory.openSession(); try { // do work } finally { session.close(); }
3、原始DAO开发方式
原始Dao开发方法需要程序员编写Dao接口和Dao实现类。
(1)映射文件
编写映射文件如下:(也可以使用入门程序完成映射文件)
<?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,还有一个很重要的作用,后面会讲 --> <mapper namespace="test"> <!-- 根据id查询用户 --> <select id="queryUserById" parameterType="int" resultType="cn.itcast.mybatis.pojo.User"> select * from user where id = #{id} </select> <!-- 根据username模糊查询用户 --> <select id="queryUserByUsername" parameterType="string" resultType="cn.itcast.mybatis.pojo.User"> select * from user where username like '%${value}%' </select> <!-- 保存用户 --> <insert id="saveUser" parameterType="cn.itcast.mybatis.pojo.User"> <selectKey keyProperty="id" keyColumn="id" order="AFTER" resultType="int"> SELECT LAST_INSERT_ID() </selectKey> insert into user(username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address}) </insert> </mapper>
(2)DAO接口
先进行DAO的接口开发,编码如下:
public interface UserDao { /** * 根据id查询用户 * * @param id * @return */ User queryUserById(int id); /** * 根据用户名模糊查询用户 * * @param username * @return */ List<User> queryUserByUsername(String username); /** * 保存用户 * * @param user */ void saveUser(User user); }
(3)DAO实现类
编写的Dao实现类如下
public class UserDaoImpl implements UserDao { private SqlSessionFactory sqlSessionFactory; public UserDaoImpl(SqlSessionFactory sqlSessionFactory) { super(); this.sqlSessionFactory = sqlSessionFactory; } @Override public User queryUserById(int id) { // 创建SqlSession SqlSession sqlSession = this.sqlSessionFactory.openSession(); // 执行查询逻辑 User user = sqlSession.selectOne("queryUserById", id); // 释放资源 sqlSession.close(); return user; } @Override public List<User> queryUserByUsername(String username) { // 创建SqlSession SqlSession sqlSession = this.sqlSessionFactory.openSession(); // 执行查询逻辑 List<User> list = sqlSession.selectList("queryUserByUsername", username); // 释放资源 sqlSession.close(); return list; } @Override public void saveUser(User user) { // 创建SqlSession SqlSession sqlSession = this.sqlSessionFactory.openSession(); // 执行保存逻辑 sqlSession.insert("saveUser", user); // 提交事务 sqlSession.commit(); // 释放资源 sqlSession.close(); } }
(4)DAO测试
创建一个JUnit的测试类,对UserDao进行测试,测试代码如下:
public class UserDaoTest { private SqlSessionFactory sqlSessionFactory; @Before public void init() throws Exception { // 创建SqlSessionFactoryBuilder SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder(); // 加载SqlMapConfig.xml配置文件 InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml"); // 创建SqlsessionFactory this.sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream); } @Test public void testQueryUserById() { // 创建DAO UserDao userDao = new UserDaoImpl(this.sqlSessionFactory); // 执行查询 User user = userDao.queryUserById(1); System.out.println(user); } @Test public void testQueryUserByUsername() { // 创建DAO UserDao userDao = new UserDaoImpl(this.sqlSessionFactory); // 执行查询 List<User> list = userDao.queryUserByUsername("张"); for (User user : list) { System.out.println(user); } } @Test public void testSaveUser() { // 创建DAO UserDao userDao = new UserDaoImpl(this.sqlSessionFactory); // 创建保存对象 User user = new User(); user.setUsername("刘备"); user.setBirthday(new Date()); user.setSex("1"); user.setAddress("蜀国"); // 执行保存 userDao.saveUser(user); System.out.println(user); } }
4、Mapper动态代理开发
(1)开发规范
Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口 定义创建接口的动态代理对象,代理对象的方法体同上边Dao接口实现类方法。
Mapper接口开发需要遵循以下规范:
1、 接口方法名 == User.xml中的id名
2、返回值类型与Mapper.xml文件中返回值类型要一致
3、 方法入参类型与Mapper.xml中入参的类型要一致
4、 命名空间绑定此接口
(2)Mapper.xml(映射文件)
定义mapper映射文件UserMapper.xml
将UserMapper.xml放在config下mapper目录下,效果如下:

UserMapper.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 --> <!-- 还有一个很重要的作用,使用动态代理开发DAO,1. namespace必须和Mapper接口类路径一致 --> <mapper namespace="cn.itcast.mybatis.mapper.UserMapper"> <!-- 根据用户id查询用户 --> <!-- 2. id必须和Mapper接口方法名一致 --> <!-- 3. parameterType必须和接口方法参数类型一致 --> <!-- 4. resultType必须和接口方法返回值类型一致 --> <select id="queryUserById" parameterType="int" resultType="cn.itcast.mybatis.pojo.User"> select * from user where id = #{id} </select> <!-- 根据用户名查询用户 --> <select id="queryUserByUsername" parameterType="string" resultType="cn.itcast.mybatis.pojo.User"> select * from user where username like '%${value}%' </select> <!-- 保存用户 --> <insert id="saveUser" parameterType="cn.itcast.mybatis.pojo.User"> <selectKey keyProperty="id" keyColumn="id" order="AFTER" resultType="int"> select last_insert_id() </selectKey> insert into user(username,birthday,sex,address) values (#{username},#{birthday},#{sex},#{address}); </insert> </mapper>
(3)UserMapper(接口文件)
创建UserMapper接口代码如下:
public interface UserMapper { /** * 根据id查询 * * @param id * @return */ User queryUserById(int id); /** * 根据用户名查询用户 * * @param username * @return */ List<User> queryUserByUsername(String username); /** * 保存用户 * * @param user */ void saveUser(User user); }
(4)加载UserMapper.xml文件
修改SqlMapConfig.xml文件,添加以下所示的内容:
<!-- 加载映射文件 -->
<mappers>
<mapper resource="sqlmap/User.xml" />
<mapper resource="mapper/UserMapper.xml" />
</mappers>
(5)测试
编写的测试方法如下:
public class UserMapperTest { private SqlSessionFactory sqlSessionFactory; @Before public void init() throws Exception { // 创建SqlSessionFactoryBuilder SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder(); // 加载SqlMapConfig.xml配置文件 InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml"); // 创建SqlsessionFactory this.sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream); } @Test public void testQueryUserById() { // 获取sqlSession,和spring整合后由spring管理 SqlSession sqlSession = this.sqlSessionFactory.openSession(); // 从sqlSession帮我生成一个实现类(给接口) UserMapper userMapper = sqlSession.getMapper(UserMapper.class); // 执行查询方法 User user = userMapper.queryUserById(1); System.out.println(user); // 和spring整合后由spring管理 sqlSession.close(); } @Test public void testQueryUserByUsername() { // 获取sqlSession,和spring整合后由spring管理 SqlSession sqlSession = this.sqlSessionFactory.openSession(); // 从sqlSession中获取Mapper接口的代理对象 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); // 执行查询方法 List<User> list = userMapper.queryUserByUsername("张"); for (User user : list) { System.out.println(user); } // 和spring整合后由spring管理 sqlSession.close(); } @Test public void testSaveUser() { // 获取sqlSession,和spring整合后由spring管理 SqlSession sqlSession = this.sqlSessionFactory.openSession(); // 从sqlSession中获取Mapper接口的代理对象 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); // 创建保存对象 User user = new User(); user.setUsername("刘备"); user.setBirthday(new Date()); user.setSex("1"); user.setAddress("蜀国"); // 执行查询方法 userMapper.saveUser(user); System.out.println(user); // 和spring整合后由spring管理 sqlSession.commit(); sqlSession.close(); } }
5、小结
selectOne和selectList
动态代理对象调用sqlSession.selectOne()和sqlSession.selectList()是根据mapper接口方法的 返回值决定,如果返回list则调用selectList方法,如果返回单个对象则调用selectOne方法。
namespace
mybatis官方推荐使用mapper代理方法开发mapper接口,程序员不用编写mapper接口实现 类,使用mapper代理方法时,输入参数可以使用pojo包装对象或map对象,保证dao的通用性。
六、关于SqlMapConfig的一些知识点
1、配置内容
SqlMapConfigl.xml中配置的内容和顺序如下:
properties(属性)
settings(全局配置参数)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境集合属性对象)
environment(环境子属性对象)
transactionManager(事务管理)
dataSource(数据源)
mappers(映射器)
2、properties(属性)
SqlMapConfig.xml可以引用java属性文件中的配置信息如下:
在config下定义db.properties文件,如下所示:

db.properties配置文件内容如下:
1 jdbc.driver=com.mysql.jdbc.Driver 2 jdbc.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8 3 jdbc.username=root 4 jdbc.password=root
SqlMapConfig.xml引用如下:
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <!DOCTYPE configuration 3 PUBLIC "-//mybatis.org//DTD Config 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-config.dtd"> 5 <configuration> 6 <!-- 是用resource属性加载外部配置文件 --> 7 <properties resource="db.properties"> 8 <!-- 在properties内部用property定义属性 --> 9 <!-- 如果外部配置文件有该属性,则内部定义属性被外部属性覆盖 --> 10 <property name="jdbc.username" value="root123" /> 11 <property name="jdbc.password" value="root123" /> 12 </properties> 13 14 <!-- 和spring整合后 environments配置将废除 --> 15 <environments default="development"> 16 <environment id="development"> 17 <!-- 使用jdbc事务管理 --> 18 <transactionManager type="JDBC" /> 19 <!-- 数据库连接池 --> 20 <dataSource type="POOLED"> 21 <property name="driver" value="${jdbc.driver}" /> 22 <property name="url" value="${jdbc.url}" /> 23 <property name="username" value="${jdbc.username}" /> 24 <property name="password" value="${jdbc.password}" /> 25 </dataSource> 26 </environment> 27 </environments> 28 29 <!-- 加载映射文件 --> 30 <mappers> 31 <mapper resource="sqlmap/User.xml" /> 32 <mapper resource="mapper/UserMapper.xml" /> 33 </mappers> 34 </configuration>
注意: MyBatis 将按照下面的顺序来加载属性:
在 properties 元素体内定义的属性首先被读取。
然后会读取properties 元素中resource或 url 加载的属性,它会覆盖已读取的同名属性。
3、typeAliases(类型别名)
(1)mybatis支持别名:


(2)自定义别名
在SqlMapConfig.xml中配置如下:
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <!DOCTYPE configuration 3 PUBLIC "-//mybatis.org//DTD Config 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-config.dtd"> 5 <configuration> 6 <!-- 是用resource属性加载外部配置文件 --> 7 <properties resource="db.properties"> 8 <!-- 在properties内部用property定义属性 --> 9 <property name="jdbc.username" value="root123" /> 10 <property name="jdbc.password" value="root123" /> 11 </properties> 12 13 <typeAliases> 14 <!-- 单个别名定义 --> 15 <typeAlias alias="user" type="cn.itcast.mybatis.pojo.User" /> 16 <!-- 批量别名定义,扫描整个包下的类,别名为类名(大小写不敏感) --> 17 <package name="cn.itcast.mybatis.pojo" /> 18 <package name="其它包" /> 19 </typeAliases> 20 21 <!-- 和spring整合后 environments配置将废除 --> 22 <environments default="development"> 23 <environment id="development"> 24 <!-- 使用jdbc事务管理 --> 25 <transactionManager type="JDBC" /> 26 <!-- 数据库连接池 --> 27 <dataSource type="POOLED"> 28 <property name="driver" value="${jdbc.driver}" /> 29 <property name="url" value="${jdbc.url}" /> 30 <property name="username" value="${jdbc.username}" /> 31 <property name="password" value="${jdbc.password}" /> 32 </dataSource> 33 </environment> 34 </environments> 35 36 <!-- 加载映射文件 --> 37 <mappers> 38 <mapper resource="sqlmap/User.xml" /> 39 <mapper resource="mapper/UserMapper.xml" /> 40 </mappers> 41 </configuration>
在mapper.xml配置文件中,就可以使用设置的别名了
别名大小写不敏感

4、mappers(映射器)
Mapper配置的几种方法:
(1)<mapper resource=" "/>
使用相对于类路径的资源(常用)
如:<mapper resource="sqlmap/User.xml" />
(2)<mapper class=" "/>
使用mapper接口类路径
如:<mapper class="cn.itcast.mybatis.mapper.UserMapper"/>
注意:此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。
(3)<package name=" "/>
注册指定包下的所有mapper接口
如:<package name="cn.itcast.mybatis.mapper"/>
注意:此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。
七、整合(Spring)后开发常用

class 容器中已经加载的工厂路径
name 定义扫描的单元
value 定义扫描该包或者该包下的所有子包中的类


浙公网安备 33010602011771号