MyBatis 本是 apache 的一个开源项目 iBatis, 2010 年这个项目由 apache software foundation 迁移到了 google code,并且改名为 MyBatis 。2013 年 11 月迁移到 Github。
MyBatis 是一个优秀的持久层框架,它对 jdbc 的操作数据库的过程进行封装,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动、创建 connection、创建 statement、手动设置参数、结果集检索等 jdbc 繁杂的过程代码。
Mybatis 通过 xml 或注解的方式将要执行的各种 statement(statement、preparedStatemnt、CallableStatement)配置起来,并通过j ava 对象和 statement 中的 sql 进行映射生成最终执行的 sql 语句,最后由 Mybatis 框架执行 sql 并将结果映射成 java 对象并返回。
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通过MappedStatement在执行sql后将输出结果映射至java对象中,输出结果映射过程相当于jdbc编程中对结果的解析处理过程。
我们先来写一个入门程序,来了解一下 Mybatis 具体的使用流程,具体的细节会在后面一一讲解。
第一步:创建数据库和数据表
CREATE DATABASE mybatis;
CREATE TABLE `user` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`username` VARCHAR(32) NOT NULL COMMENT '用户名称',
`birthday` DATE DEFAULT NULL COMMENT '生日',
`sex` CHAR(1) DEFAULT NULL COMMENT '性别',
`address` VARCHAR(256) DEFAULT NULL COMMENT '地址',
PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8;
INSERT INTO `user` VALUES ('1', '王五', NULL, '2', NULL);
INSERT INTO `user` VALUES ('10', '张三', '2014-07-10', '1', '广东深圳');
INSERT INTO `user` VALUES ('16', '张小明', NULL, '1', '广东广州');
INSERT INTO `user` VALUES ('22', '陈小明', NULL, '1', '广东广州');
INSERT INTO `user` VALUES ('24', '张三丰', NULL, '1', '广东广州');
INSERT INTO `user` VALUES ('25', '陈小明', NULL, '1', '广东广州');
INSERT INTO `user` VALUES ('26', '王五', NULL, NULL, NULL);
第二步:创建 java 项目,导入 DTD 约束文件和jar包,配置 Mybatis 核心配置文件sqlMapConfig.xml ,SqlMapConfig.xml 是配置文件内容为数据源、事务管理。(配置文件写在 src 根目录下即可,或者也可以在 src下创建一个文件夹 config,用于统一存放配置文件)
<configuration>
<typeAliases>
<package name="com.pngyul.mybatis.pojo" />
typeAliases>
<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://localhost:3306/mybatis?characterEncoding=utf-8" />
<property name="username" value="root" />
<property name="password" value="root" />
dataSource>
environment>
environments>
<mappers>
<mapper resource="User0.xml" />
mappers>
configuration>
第三步:创建和数据库表对应的 pojo 类
public class User implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private Integer id;
private String username;// 用户姓名
private String sex;// 性别
private Date birthday;// 生日
private String address;// 地址
public Integer getId() {
return id;
}
public void setId(Integer 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 + "]";
}
}
第四步:创建 sql 映射文件 Use0.xml
<mapper namespace="test">
<select id="findUserById" parameterType="Integer" resultType="com.pngyul.mybatis.pojo.User">
select * from user where id =#{id}
select>
mapper>
第五步:测试程序
@Test
public void findUserById() throws IOException {
// 加载核心配置文件
String resource = "sqlMapConfig.xml";
InputStream in = Resources.getResourceAsStream(resource);
// 创建SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
// 创建SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
// 执行Sql语句
User user = sqlSession.selectOne("test.findUserById", 10);
System.out.println(user);
}
模糊查询
<select id="findUserByUsername" parameterType="String" resultType="com.pngyul.mybatis.pojo.User">
select * from user where username like "%"#{haha}"%"
select>
select * from user where username like '%${value}%'
//根据用户名称模糊查询用户列表
@Test
public void findUserByUsername() throws Exception {
String resource = "sqlMapConfig.xml";
InputStream in = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
SqlSession sqlSession = sqlSessionFactory.openSession();
List users = sqlSession.selectList("test.findUserByUsername", "五");
for (User user2 : users) {
System.out.println(user2);
}
}
添加
<insert id="insertUser" parameterType="com.pngyul.mybatis.pojo.User">
insert into user(username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address})
insert>
@Test
public void test() throws IOException {
String resource="sqlMapConfig.xml";
InputStream in=Resources.getResourceAsStream(resource);
SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(in);
SqlSession sqlSession=factory.openSession();
User user=new User();
user.setUsername("pngyul");
user.setBirthday(new Date());
user.setSex("男");
user.setAddress("广东");
sqlSession.insert("test.insertUser", user);
sqlSession.commit();
sqlSession.close();
}
添加并返回数据库自增主键
<insert id="saveUser" parameterType="com.pngyul.mybatis.pojo.User">
<selectKey keyColumn="id" keyProperty="id" order="AFTER"
resultType="Integer">
SELECT LAST_INSERT_ID()
selectKey>
INSERT INTO `user`
(username,birthday,sex,address) VALUES
(#{username},#{birthday},#{sex},#{address})
insert
@Test
public void insertUser() throws Exception {
String resource = "sqlMapConfig.xml";
InputStream in = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
SqlSession sqlSession = sqlSessionFactory.openSession();
User user = new User();
user.setAddress("广东");
user.setBirthday(new Date());
user.setSex("男");
user.setUsername("ccfff");
int i = sqlSession.update("test.insertUser", user);
sqlSession.commit();
System.err.println(user.getId());
sqlSession.close();
}
修改
update>
<delete id="deleteUserById" parameterType="Integer">
delete from user where id=#{id}
delete>
@Test
public void updateUserById() throws Exception {
String resource = "sqlMapConfig.xml";
InputStream in = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
SqlSession sqlSession = sqlSessionFactory.openSession();
User user = new User();
user.setAddress("广东");
user.setBirthday(new Date());
user.setSex("女");
user.setUsername("ccfff");
user.setId(30);
int i = sqlSession.update("test.updateUserById", user);
sqlSession.commit();
sqlSession.close();
}
删除
<delete id="deleteUser" parameterType="Integer">
delete from user where id=#{id}
delete>
@Test
public void test() throws IOException {
String resource="sqlMapConfig.xml";
InputStream in=Resources.getResourceAsStream(resource);
SqlSessionFactoryBuilder builder= new SqlSessionFactoryBuilder();
SqlSessionFactory factory=builder.build(in);
SqlSession sqlSession=factory.openSession();
sqlSession.delete("deleteUser", 27);
sqlSession.commit();
sqlSession.close();
}
简单举个例子,了解一下即可
/1、编写mapper文件,并引入到核心配置文件中
<select id="findUserById" parameterType="Integer"
resultType="User">
select * from user where id = #{v}
select>
//2、定义一个UserDao接口
public interface UserDao {
User queryUserById(Integer id);
}
//3、UserDao实现类
package com.pngyul.mybatis.dao;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import com.pngyul.mybatis.pojo.User;
public class UserDaoImpl implements UserDao {
private SqlSessionFactory sqlSessionFactory;
public UserDaoImpl(SqlSessionFactory sqlSessionFactory) {
super();
this.sqlSessionFactory = sqlSessionFactory;
}
@Override
public User queryUserById(Integer id) {
SqlSession sqlsession = sqlSessionFactory.openSession();
User user = sqlsession.selectOne("test.findUserById", id);
sqlsession.close();
return user;
}
}
//测试
public class Junit {
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(10);
System.out.println(user);
}
Mapper接口开发方法只需要程序员编写Mapper接口(相当于 Dao 接口),由 Mybatis 框架根据接口定义创建接口的动态代理对象。
Mapper接口开发需要遵循以下四个规范:
演示 Mapper 动态代理方式步骤:
1、编写Mapper文件
<mapper namespace="com.pngyul.mybatis.mapper.UserMapper">
<select id="findUserById" parameterType="int" resultType="com.pngyul.mybatis.pojo.User">
select * from user where id =#{id}
select>
<select id="findUserByUsername" parameterType="String" resultType="com.pngyul.mybatis.mapper.UserMapper">
select * from user where username like '%${value}%'
select>
<insert id="insertUser" parameterType="com.pngyul.mybatis.mapper.UserMapper">
insert into user(username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address})
insert>
<update id="updateUser" parameterType="com.pngyul.mybatis.mapper.UserMapper">
update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id}
update>
<delete id="deleteUser" parameterType="Integer">
delete from user where id=#{id}
delete>
mapper>
2、创建Mapper接口
public interface UserMapper {
public User findUserById(int id);
public List findUserByUsername(String username);
public void insertUser(User user);
public void deleteUser(Integer id);
}
3、核心配置文件中引入映射文件
<mappers>
<mapper resource="mapper/UserMapper.xml"/>
mappers>
4、测试
public class MybatisTest {
@Test
public void test() throws IOException {
String resource="sqlMapConfig.xml";
InputStream in=Resources.getResourceAsStream(resource);
SqlSessionFactoryBuilder builder= new SqlSessionFactoryBuilder();
SqlSessionFactory factory=builder.build(in);
SqlSession sqlSession=factory.openSession();
UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
User user=userMapper.findUserById(1);
System.out.println(user);
}
}
开发中使用这种方式来进行开发,简便快捷,代码复用性高,免去很多重复繁琐代码。
MyBatis 的配置文件包含了 MyBatis 的设置和属性信息。文档的结构和顺序如下:
properties 属性
settings 设置
typeAliases 类型命名
typeHandlers 类型处理器
objectFactory 对象工厂
plugins 插件
environments(环境集合属性对象)
environment(环境子属性对象)
transactionManager(事务管理)
dataSource(数据源)
databaseIdProvider 数据库厂商标识
mappers 映射器
下面重点介绍几个:
properties(属性)
//db.peoperties文件
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8
jdbc.username=root
jdbc.password=root
//引入文件
<properties resource="db.properties"/>
<dataSource type="POOLED">
<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>
如果属性在不只一个地方进行了配置,那么 MyBatis 将按照下面的顺序来加载:
typeAliases(类型别名)
类型别名是为 Java 类型设置一个短的名字。它只和 XML 配置有关,存在的意义仅在于用来减少类完全限定名的冗余。
<typeAliases>
<typeAlias alias="user" type="cn.cad.pojo.User" />
<package name="cn.itcast.mybatis.pojo" />
<package name="其它包" />
typeAliases>
在mapper文件中就可以使用别名user。
Mybatis 已经为许多常见的 Java 类型内建了相应的类型别名。它们都是大小写不敏感的,例如 string,integer 等。
mappers(映射器)
映射器配置会告诉了 MyBatis 去哪里找映射文件。
<mapper resource=" " />:使用相对于类路径的资源(现在的使用方式)
<mapper url="file:///var/mappers/AuthorMapper.xml"/>:使用绝对路径,基本不会用
<mapper class="cn.itcast.mybatis.mapper.UserMapper"/>:使用mapper接口类路径。注意:此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。
<package name="xxx"/>:注册指定包下的所有mapper接口,此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。
PS::部分学习资料源于传智播客