学习了 hibernate 这个持久层框架之后, 在来学习 Mybatis 简直是无压力, 因为 Mybatis 入门门栏很低, 如果学习过了 hibernate 的话, 对于 Mybatis 的学习很简单了, 如果没学习过 hibernate 直接学习 Mybatis 也没关系, 也很好理解.
写 Mybatis 这一章节博客, 大致分为这样一种思路
mybatis 入门 --> 全局配置文件和映射文件详解 --> 高级映射 (一对一, 一对多, 多对多) --> 延迟加载机制 -->一级缓存, 二级缓存(整合 ehcache) --> spring 整合 mybatis --> 逆向工程
如果你想直接查看 mybatis 的标准 helloworld, 那么跳过这章, 看第二章.
一, Mybatis 的简介
mybatis 封装了 jdbc 的持久层框架, 前身为 ibatis, 在配置文件中编写 sql, 是不完全 ORM 映射框架.
查看百度百科的介绍
1, 支持普通 sql 查询
2, 高级映射
3, 存储过程
4, 消除了几乎所有 jdbc 代码和参数的手工设置以及结果集的检索, 等等特点, 都会讲解到, 今天先认识一下为什么说 mybatis 消除了所有 jdbc 代码和参数的设置, 通过普通的 jdbc 有哪些不足, 从而认识到 mybatis 的好处.
二, 分析 jdbc 的问题
- //1, 注册驱动, 什么是驱动? 能够让 java 连接数据库, 也就是实现 jdbc 接口规范就是驱动
- Class.forName("com.mysql.jdbc.Driver");// 硬编码
- /*
- * 2, 通过驱动管理者获取数据库连接
- * DriverManager 是驱动实现类的管理者.
- * url: 连接数据库的位置, 端口号, 数据库名
- * jdbc:MySQL://localhost:3306/test_01
- */
- Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test_1", "root", "root");//(硬编码)
- /*
- * 3, 获得 sql 语句执行者
- * statement: 执行 sql 语句对象
- * sql 语句必须是完整的.
- * preparedStatement: 预处理(常用)
- * sql 语句可以不是完整的, 可以将参数用? 替代, 然后在预编译后加入未知参数
- *
- */
- // 定义 sql 语句,? 表示占位符
- String sql = "select * from user where id = ?"; // 硬编码
- PreparedStatement ps = conn.prepareStatement(sql);
- ps.setInt(1, 1); // 硬编码
- //4, 获取 sql 语句执行结果, resultset
- /*
- * executeQuery(): 查询操作
- * executeUpdate(): 增删改操作
- */
- ResultSet rs= ps.executeQuery();
- //5, 处理结果
- while(rs.next()){
- System.out.println(rs.getInt(1));;//index 代表第几列, 从 1 开始
- }
- //6, 关闭连接
- rs.close();
- ps.close();
- conn.close();
- //1, 注册驱动, 什么是驱动? 能够让 java 连接数据库, 也就是实现 jdbc 接口规范就是驱动
- Class.forName("com.mysql.jdbc.Driver");// 硬编码
- /*
- * 2, 通过驱动管理者获取数据库连接
- * DriverManager 是驱动实现类的管理者.
- * url: 连接数据库的位置, 端口号, 数据库名
- * jdbc:MySQL://localhost:3306/test_01
- */
- Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test_1", "root", "root");//(硬编码)
- /*
- * 3, 获得 sql 语句执行者
- * statement: 执行 sql 语句对象
- * sql 语句必须是完整的.
- * preparedStatement: 预处理(常用)
- * sql 语句可以不是完整的, 可以将参数用? 替代, 然后在预编译后加入未知参数
- *
- */
- // 定义 sql 语句,? 表示占位符
- String sql = "select * from user where id = ?"; // 硬编码
- PreparedStatement ps = conn.prepareStatement(sql);
- ps.setInt(1, 1); // 硬编码
- //4, 获取 sql 语句执行结果, resultset
- /*
- * executeQuery(): 查询操作
- * executeUpdate(): 增删改操作
- */
- ResultSet rs= ps.executeQuery();
- //5, 处理结果
- while(rs.next()){
- System.out.println(rs.getInt(1));;//index 代表第几列, 从 1 开始
- }
- //6, 关闭连接
- rs.close();
- ps.close();
- conn.close();
这种方式的缺陷
1, 创建连接存在硬编码
2, 执行 statement 时存在硬编码
3, 频繁的开闭数据库连接, 会影响数据库的性能.
现在就对这个所产生的问题与使用 mybatis 进行对比.
三, 初级的 mybatis
跟 hibernate 一样, 也是需要拥有两个配置文件,
全局配置文件 和 映射文件, 在编写这两个映射文件之前, 必须创建 mybatis 环境(jar 包等)
创建 java 工程
3.1,jar 包
MySQL(1)
Mybatis(1 个核心包 + 9 个依赖包)
总共 11 个 jar
3.2, 初始化数据库脚本
暂时只需要一张表 id 是自增的, 为主键
3.3, 添加 log4j.properties
该内容可以在 mybatis 的 jar 包中找到
- # Global logging configuration
- log4j.rootLogger=DEBUG, stdout
- # MyBatis logging configuration...
- log4j.logger.org.mybatis.example.BlogMapper=TRACE
- # 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%n
- # Global logging configuration
- log4j.rootLogger=DEBUG, stdout
- # MyBatis logging configuration...
- log4j.logger.org.mybatis.example.BlogMapper=TRACE
- # 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%n
3.4, 全局配置文件
建议使用 sqlMapConfig.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>
- <!--
- 属性
- <properties></properties>
- 全局参数设置
- <settings></settings>
- 类型别名
- <typeAliases></typeAliases>
- 类型处理器
- <typeHandles></typeHandles>
- 对象工厂
- <objectFactory></objectFactory>
- 插件
- <plugins></plugins>
- 以上属性在后边会详细讲解到, 现在我们就只需要关注一下下面的配置即可
- 如下所配置的就是使用这点东西.
- environments(环境信息集合)
- environment(单个环境信息)
- transactionManager(事物)
- dataSource(数据源)
- environment
- environments
- mappers(映射器)
- -->
- <!-- 配置 mybatis 的环境信息 -->
- <environments default="development">
- <environment id="development">
- <!-- 配置 JDBC 事务控制, 由 mybatis 进行管理 -->
- <transactionManager type="JDBC"></transactionManager>
- <!-- 配置数据源, 采用 dbcp 连接池 -->
- <dataSource type="POOLED">
- <property name="driver" value="com.mysql.jdbc.Driver"/>
- <property name="url" value="jdbc:mysql://localhost:3306/test_1?useUnicode=true&characterEncoding=utf8"/>
- <property name="username" value="root"/>
- <property name="password" value="root"/>
- </dataSource>
- </environment>
- </environments>
- <!-- 加载 mapper 映射文件 -->
- <mappers>
- <mapper resource="sqlmap/User.xml"/>
- </mappers>
- </configuration>
<?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>
- <!--
- 属性
- <properties></properties>
- 全局参数设置
- <settings></settings>
- 类型别名
- <typeAliases></typeAliases>
- 类型处理器
- <typeHandles></typeHandles>
- 对象工厂
- <objectFactory></objectFactory>
- 插件
- <plugins></plugins>
- 以上属性在后边会详细讲解到, 现在我们就只需要关注一下下面的配置即可
- 如下所配置的就是使用这点东西.
- environments(环境信息集合)
- environment(单个环境信息)
- transactionManager(事物)
- dataSource(数据源)
- environment
- environments
- mappers(映射器)
- -->
- <!-- 配置 mybatis 的环境信息 -->
- <environments default="development">
- <environment id="development">
- <!-- 配置 JDBC 事务控制, 由 mybatis 进行管理 -->
- <transactionManager type="JDBC"></transactionManager>
- <!-- 配置数据源, 采用 dbcp 连接池 -->
- <dataSource type="POOLED">
- <property name="driver" value="com.mysql.jdbc.Driver"/>
- <property name="url" value="jdbc:mysql://localhost:3306/test_1?useUnicode=true&characterEncoding=utf8"/>
- <property name="username" value="root"/>
- <property name="password" value="root"/>
- </dataSource>
- </environment>
- </environments>
- <!-- 加载 mapper 映射文件 -->
- <mappers>
- <mapper resource="sqlmap/User.xml"/>
- </mappers>
- </configuration>
3.5, 映射文件和操作
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 进行一个分类管理 -->
- <!-- 注意: namespace 在 mapper 代理时, 具有重要且特殊的作用 -->
- <mapper namespace="test">
- // 编写映射条件, 也就是下面的
- </mapper>
<?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 进行一个分类管理 -->
- <!-- 注意: namespace 在 mapper 代理时, 具有重要且特殊的作用 -->
- <mapper namespace="test">
- // 编写映射条件, 也就是下面的
- </mapper>
该映射文件是为了解决 jdbc 中 statement 的硬编码的问题, 所以, 在此映射文件中, 只需要指定输入参数类型, 返回结果参数类型, sql 语句等就差不多了, 也就是将原本 jdbc 所遇到的硬编码问题全部是使用 xml 配置文件来替代, 有什么需要就修改配置文件即可, 现在来看看该映射文件是如何编写的.
通过增删改查这四个操作来讲解.
3.6.1, 查询 按 id 查询出 user 对象 注意看下面的注释
- <!--
- 使用 id 进行查询
- 查询, 使用 select 来表示一个查询的 statement, 相当于 statement.executeQuery
- id: 表示该 statement 唯一标识
- parameterType: 输入参数类型
- resultType: 输出参数类型, 使用的是 User 类, 则会将查询出来的记录封装到该类中
- #{id}: 使用 #{}接收输入的参数, 其中的 "id" 属性名任意, 可以为 uid, 也可以为别的.
- -->
- <select id="findUserById" parameterType="java.lang.Integer" resultType="com.wuhao.mybatis.domain.User">
- SELECT * FROM user WHERE id= #{id}
- </select>
- <!--
- 使用 id 进行查询
- 查询, 使用 select 来表示一个查询的 statement, 相当于 statement.executeQuery
- id: 表示该 statement 唯一标识
- parameterType: 输入参数类型
- resultType: 输出参数类型, 使用的是 User 类, 则会将查询出来的记录封装到该类中
- #{id}: 使用 #{}接收输入的参数, 其中的 "id" 属性名任意, 可以为 uid, 也可以为别的.
- -->
- <select id="findUserById" parameterType="java.lang.Integer" resultType="com.wuhao.mybatis.domain.User">
- SELECT * FROM user WHERE id= #{id}
- </select>
操作
- // 根据用户 id 进行查询. findUserById
- @Test
- public void test() throws IOException{
- // 跟 hibernate 一样, 需要获取一大堆东西
- // 1, 读取配置文件
- String resource = "SqlMapConfig.xml";
- InputStream inputStream = Resources.getResourceAsStream(resource);
- // 2, 根据配置文件创建 SqlSessionFactory
- SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
- // 3,SqlSessionFactory 创建 SqlSession
- SqlSession sqlSession = sqlSessionFactory.openSession();
- // 4,SqlSession 执行 statement, 并返回映射结果
- /*
- * test.findUserById: 在映射配置文件中, mapper 的 namespace 为 test,
- * 其中有一个 select, 也就代表查询的 statement.
- * 1: 输入参数为 1
- * 返回的结果类型为 User
- */
- User user = sqlSession.selectOne("test.findUserById", 1);
- System.out.println(user);
- //5, 关闭 sqlsession 资源
- sqlSession.close();
- }
- // 根据用户 id 进行查询. findUserById
- @Test
- public void test() throws IOException{
- // 跟 hibernate 一样, 需要获取一大堆东西
- // 1, 读取配置文件
- String resource = "SqlMapConfig.xml";
- InputStream inputStream = Resources.getResourceAsStream(resource);
- // 2, 根据配置文件创建 SqlSessionFactory
- SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
- // 3,SqlSessionFactory 创建 SqlSession
- SqlSession sqlSession = sqlSessionFactory.openSession();
- // 4,SqlSession 执行 statement, 并返回映射结果
- /*
- * test.findUserById: 在映射配置文件中, mapper 的 namespace 为 test,
- * 其中有一个 select, 也就代表查询的 statement.
- * 1: 输入参数为 1
- * 返回的结果类型为 User
- */
- User user = sqlSession.selectOne("test.findUserById", 1);
- System.out.println(user);
- //5, 关闭 sqlsession 资源
- sqlSession.close();
- }
3.6.2, 查询, 模糊查询, 对 username 字段进行模糊查询
user.xml 映射文件
操作
3.6.3, 增加 User, insert
user.xml,insert 操作, 对主键 id 有几种不同的处理方式, 具体看下图的解释
操作
3.6.4, 删除 delete
映射文件
操作
3.6.5, 更新 update
映射文件
操作
小总结: 编写了最基础的全局配置文件和映射文件.
全局配置文件: 连接数据库所需要的帐号密码等属性, 事务等操作
映射文件: 通过对比原始 jdbc 连接数据库, 其实 mybatis 中的映射文件就是对 statement 的硬编码进行改进, 我们配置的都市 statement 需要的东西
sql 语句, 输入参数类型代替 sql 语句中的占位符, 输出参数类型表示输出结果, 都可以对应着 statement 的操作
parameterType: 指定输入参数的 java 类型, 可以填写别名或 Java 类的全限定名. 别名的用法在详细讲解全局配置文件的时候会讲解到, 在那边可以配置
resultType: 指定输出结果的 java 类型, 可以填写别名或 Java 类的全限定名.
- #{}和 ${}的用法
- #{}: 相当于预处理中的占位符?
- #{}里面的参数表示接收 java 输入参数的名称
- #{}可以接受 HashMap, 简单类型, POJO 类型的参数
简单类型:#{}里面可以是 value, 可以是任意值
POJO 类型的参数: 必须是 POJO 中的属性名
hashmap:key 值名
${}: 相当于拼接 SQL 串, 对传入的值不做任何解释的原样输出.
${}会引起 SQL 注入, 所以要谨慎使用.
${}可以接受 HashMap, 简单类型, POJO 类型的参数.
当接受简单类型的参数时,${}里面只能是 value.
sqlSession 操作时 selectOne 和 selectList
selectOne: 只能查询 0 或 1 条记录, 大于 1 条记录的话, 会报错
selectList: 可以查询 0 或 N 条记录
对于增删改操作, 切记需要 commmit 操作才能够生效.
四, 开发 dao 的方式
上面我们就单纯测试了使用 mybatis 对数据库的增删改查操作, 在开发中, 我们都是开发 dao 接口和 dao 实现类, 那么就在 dao 实现类中调用 sqlsession 的方法对数据库的增删改差操作即可.
4.1,dao 接口
4.2,daoImpl 实现类
4.3, 测试
小总结:
这样开发有一个不好的地方, 就是不能够直接使用 dao 接口中的方法, 而是使用的 sqlSession 中的方法, 这样让人不能一目了然, 所以我们在开发中都不使用这种方式进行开发, 而是使用 Mapper 代理的方式, 什么意思呢? 接下来讲讲.
五, Mapper 代理开发的方式
Mapper 代理开发方式就是开发 mapper 接口(相当于 dao 接口)
1,mapper 接口的全限定名要和 mapper 映射文件的 namespace 一致
2,mapper 接口的方法名称要和 mapper 映射文件的 statement 的 id 一致
3,mapper 接口的方法参数类型要和 mapper 映射文件的 statement 的 parameterType 一致
4,mapper 接口的方法返回值类型要和 mapper 映射文件的 statement 的 resultType 一致
这样直接看肯定不好理解, 所以直接上代码.
三样东西, mapper 接口, 两个配置文件, 一个全局配置文件, 一个映射文件, 但是这个映射文件就有要求了, 除了上面所说的四点之外, 另外一点也最好遵循, 这里用不到, 但是后面会讲解为什么会这样使用, 就是 mapper 接口的名称要和映射文件的名称相同,
mapper 接口, UserMapper.java
映射文件, UserMapper.xml
全局配置文件. sqlMapConfig.xml
其他都跟上面一样, 重点讲一下这个 mappers 加载映射文件的问题, 为什么需要 mapper 接口和映射文件同名, 并且放入同一目录下
为了方便批量加载映射文件. 而使用这种方式, 前提条件就是接口和映射文件同名并且放入同一目录下.
测试
直接调用方法名即可
六, 总结
mybatis 的基本用法就是这样, 我想大家应该都有点感觉了, 就是在映射文件中编写 statement, 将输入参数和输出结果进行映射, 所以说 mybatis 是不完全映射的框架. 懂了基本的用法之后, 那么之后就会详细讲解其中的问题, 全局配置文件当中的配置, 映射文件中的详细配置(高级映射), 延迟加载, 一级缓存二级缓存等用法.
来源: https://www.cnblogs.com/surfcater/p/10225738.html