2-Mybatis相关概念

2.1 对象/关系数据库映射(ORM)

ORM全称Object/Relation Mapping:表示对象-关系映射的缩写
ORM完成⾯向对象的编程语⾔到关系数据库的映射。当ORM框架完成映射后,程序员既可以利⽤⾯向对象程序设计语⾔的简单易⽤性,⼜可以利⽤关系数据库的技术优势。ORM把关系数据库包装成⾯向对象的模型。ORM框架是⾯向对象设计语⾔与关系数据库发展不同步时的中间解决⽅案。采⽤ORM框架后,应⽤程序不再直接访问底层数据库,⽽是以⾯向对象的⽅式来操作持久化对象,⽽ORM框架则将这些⾯向对象的操作转换成底层SQL操作。ORM框架实现的效果:把对持久化对象的保存、修改、删除等操作,转换为对数据库的操作。

2.2 Mybatis简介

MyBatis是⼀款优秀的基于ORM的半⾃动轻量级持久层框架,它⽀持定制化SQL、存储过程以及⾼级映射。
MyBatis避免了⼏乎所有的JDBC代码和⼿动设置参数以及获取结果集。MyBatis可以使⽤简单的XML或注解来配置和映射原⽣类型、接⼝和Java的POJO (Plain Old Java Objects,普通⽼式Java对 象)为数据库中的记录。

2.3 Mybatis历史

原是apache的⼀个开源项⽬iBatis, 2010年6⽉这个项⽬由apache software foundation 迁移到了google code,随着开发团队转投Google Code旗下,ibatis3.x正式更名为Mybatis ,代码于2013年11⽉迁移到Github。iBATIS⼀词来源于“internet”和“abatis”的组合,是⼀个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAO)

2.4 Mybatis优势

Mybatis是⼀个半⾃动化的持久层框架,对开发⼈员开说,核⼼sql还是需要⾃⼰进⾏优化,sql和java编
码进⾏分离,功能边界清晰,⼀个专注业务,⼀个专注数据。

3-Mybatis基本应⽤

3.1 快速⼊⻔

MyBatis官⽹地址:http://www.mybatis.org/mybatis-3/

3.1.1 开发步骤:

①添加MyBatis的坐标
②创建user数据表
③编写User实体类
④编写映射⽂件UserMapper.xml
⑤编写核⼼⽂件SqlMapConfig.xml
⑥编写测试类

3.1.2 环境搭建:

  1. 导⼊MyBatis的坐标和其他相关坐标
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
<java.version>1.8</java.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>



<!--引入依赖-->
<dependencies>
<!--mybatis坐标-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<!--mysql驱动坐标-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.41</version>
<scope>runtime</scope>
</dependency>
<!--单元测试坐标-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
  1. 创建user数据表
-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(50) DEFAULT NULL,
`password` varchar(50) DEFAULT NULL,
`birthday` varchar(50) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
  1. 编写User实体
public class User {

private Integer id;
private String username;
private String password;
private String birthday;
//省略get个set⽅法
}

  1. 编写UserMapper映射⽂件
<?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="user">
<select id="findAll" resultType="com.lemon.pojo.User">
select * from User
</select>
</mapper>
  1. 编写MyBatis核⼼⽂件
<!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:///test"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/lemon/mapper/UserMapper.xml"/>
</mappers>
</configuration>
  1. 编写测试代码
@Test
public void test1() throws IOException {
//1.Resources工具类,配置文件的加载,把配置文件加载成字节输入流
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
//2.解析了配置文件,并创建了sqlSessionFactory工厂
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
//3.生产sqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();// 默认开启一个事务,但是该事务不会自动提交
//在进行增删改操作时,要手动提交事务
//4.sqlSession调用方法:查询所有selectList 查询单个:selectOne 添加:insert 修改:update 删除:delete
List<User> users = sqlSession.selectList("user.findAll");
for (User user : users) {
System.out.println(user);
}
sqlSession.close();

}

3.1.3 MyBatis的增删改查操作

1. MyBatis的插⼊数据操作

1)编写UserMapper映射⽂件

<!--添加用户-->
<!--parameterType:参数类型-->
<insert id="saveUser" parameterType="com.lemon.pojo.User" >
insert into user values(#{id}, #{username}, #{password}, #{birthday})
</insert>

2)编写插⼊实体User的代码

@Test
public void test2() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession(true);//事务自动提交

User user = new User();
user.setId(3);
user.setUsername("kobe1");
sqlSession.insert("user.saveUser", user);
// sqlSession.commit();


sqlSession.close();
}

3)插⼊操作注意问题

  • 插⼊语句使⽤insert标签
  • 在映射⽂件中使⽤parameterType属性指定要插⼊的数据类型
  • Sql语句中使⽤#{实体属性名}⽅式引⽤实体中的属性值
  • 插⼊操作使⽤的API是sqlSession.insert(“命名空间.id”,实体对象);
  • 插⼊操作涉及数据库数据变化,所以要使⽤sqlSession对象显示的提交事务,即sqlSession.commit()

2. MyBatis的修改数据操作

1)编写UserMapper映射⽂件

<!--修改-->  
<update id="updateUser" parameterType="com.lemon.pojo.User">
update user set username = #{username} where id = #{id}
</update>

2)编写修改实体User的代码

@Test  
public void test3() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession();

User user = new User();
user.setId(4);
user.setUsername("lucy");
sqlSession.update("user.updateUser",user);
sqlSession.commit();

sqlSession.close();
}

3)修改操作注意问题

  • 修改语句使⽤update标签
  • 修改操作使⽤的API是sqlSession.update(“命名空间.id”,实体对象)

3. MyBatis的删除数据操作

1)编写UserMapper映射⽂件

<!--删除-->  
<delete id="deleteUser" parameterType="java.lang.Integer">
delete from user where id = #{abc}
</delete>

2)编写删除数据的代码

@Test  
public void test4() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession();


sqlSession.delete("com.lagou.dao.IUserDao.deleteUser",6);
sqlSession.commit();

sqlSession.close();
}

3)删除操作注意问题

  • 删除语句使⽤delete标签
  • Sql语句中使⽤#{任意字符串}⽅式引⽤传递的单个参数
  • 删除操作使⽤的API是sqlSession.delete(“命名空间.id”,Object)

3.1.4 MyBatis的映射⽂件概述

3.1.5 ⼊⻔核⼼配置⽂件分析:

1. MyBatis核⼼配置⽂件层级关系

2. MyBatis常⽤配置解析

1)environments标签

数据库环境的配置,⽀持多环境配置

其中,事务管理器(transactionManager)类型有两种:

  • JDBC:这个配置就是直接使⽤了JDBC 的提交和回滚设置,它依赖于从数据源得到的连接来管理事务作⽤域。
  • MANAGED:这个配置⼏乎没做什么。它从来不提交或回滚⼀个连接,⽽是让容器来管理事务的整个⽣命周期(⽐如 JEE 应⽤服务器的上下⽂)。 默认情况下它会关闭连接,然⽽⼀些容器并不希望这样,因此需要将 closeConnection 属性设置为 false 来阻⽌它默认的关闭⾏为。

其中,数据源(dataSource)类型有三种:

  • UNPOOLED:这个数据源的实现只是每次被请求时打开和关闭连接。
  • POOLED:这种数据源的实现利⽤“池”的概念将 JDBC 连接对象组织起来。
  • JNDI:这个数据源的实现是为了能在如 EJB 或应⽤服务器这类容器中使⽤,容器可以集中或在外部配置数据源,然后放置⼀个 JNDI 上下⽂的引⽤。

2)mapper标签

该标签的作⽤是加载映射的,加载⽅式有如下⼏种:

  • 使⽤相对于类路径的资源引⽤,例如:
    <mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
  • 使⽤完全限定资源定位符(URL),例如:
    <mapper url="file:///var/mappers/AuthorMapper.xml"/>
  • 使⽤映射器接⼝实现类的完全限定类名,例如:
    <mapper class="org.mybatis.builder.AuthorMapper"/>
  • 将包内的映射器接⼝实现全部注册为映射器,例如:
    <package name="org.mybatis.builder"/>

3.1.6 Mybatis相应API介绍

1. SqlSession⼯⼚构建器SqlSessionFactoryBuilder

常⽤API:SqlSessionFactory build(InputStream inputStream)

通过加载mybatis的核⼼⽂件的输⼊流的形式构建⼀个SqlSessionFactory对象

String resource = "org/mybatis/builder/mybatis-config.xml";
InputStream inputStream =
Resources.getResourceAsStream(resource);
SqlSessionFactoryBuilder builder = new
SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(inputStream);

其中, Resources ⼯具类,这个类在 org.apache.ibatis.io 包中。Resources 类帮助你从类路径下、⽂件系统或⼀个 web URL 中加载资源⽂件。

2. SqlSession⼯⼚对象SqlSessionFactory

SqlSessionFactory 有多个个⽅法创建SqlSession 实例。常⽤的有如下两个:

3. SqlSession会话对象

SqlSession 实例在 MyBatis 中是⾮常强⼤的⼀个类。在这⾥你会看到所有执⾏语句、提交或回滚事务和获取映射器实例的⽅法。

执⾏语句的⽅法主要有:

<T> T selectOne(String statement, Object parameter)
<E> List<E> selectList(String statement, Object parameter)
int insert(String statement, Object parameter)
int update(String statement, Object parameter)
int delete(String statement, Object parameter)

操作事务的⽅法主要有:

void commit()
void rollback()

3.2 Mybatis的Dao层实现

3.2.1 传统开发⽅式

编写UserDao接⼝

public interface UserDao {
List<User> findAll() throws IOException;
}

编写UserDaoImpl实现

public class UserDaoImpl implements UserDao {
public List<User> findAll() throws IOException {
InputStream resourceAsStream =
Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new
SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
List<User> userList = sqlSession.selectList("userMapper.findAll");
sqlSession.close();
return userList;
}
}

测试传统⽅式

@Test
public void testTraditionDao() throws IOException {
UserDao userDao = new UserDaoImpl();
List<User> all = userDao.findAll();
System.out.println(all);
}

3.2.2 代理开发⽅式

1. 代理开发⽅式介绍

采⽤ Mybatis 的代理开发⽅式实现 DAO 层的开发,这种⽅式是我们后⾯进⼊企业的主流。

Mapper 接⼝开发⽅法只需要程序员编写Mapper 接⼝(相当于Dao 接⼝),由Mybatis 框架根据接⼝定义创建接⼝的动态代理对象,代理对象的⽅法体同上边Dao接⼝实现类⽅法。

Mapper 接⼝开发需要遵循以下规范:

  • Mapper.xml⽂件中的namespace与mapper接⼝的全限定名相同
  • Mapper接⼝⽅法名和Mapper.xml中定义的每个statement的id相同
  • Mapper接⼝⽅法的输⼊参数类型和mapper.xml中定义的每个sql的parameterType的类型相同
  • Mapper接⼝⽅法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同

代理开发⽅式实现

编写UserMapper接⼝

public interface IUserDao {  

//查询所有用户
public List<User> findAll() throws IOException;

//多条件组合查询:演示if
public List<User> findByCondition(User user);

//多值查询:演示foreach
public List<User> findByIds(int[] ids);

}

测试代理⽅式

@Test
public void testProxyDao() throws IOException {
InputStream resourceAsStream =
Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new
SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
//获得MyBatis框架⽣成的UserMapper接⼝的实现类
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.findById(1);
System.out.println(user);
sqlSession.close();
}