一、MyBatis简介
1.1 什么是Mybatis
MyBatis 是一款优秀的持久层框架
它支持自定义 SQL、存储过程以及高级映射。
MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。
MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。
如何获得Mybatis?
maven仓库
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.2</version> </dependency>
Github:https://github.com/mybatis/mybatis-3/releases
中文文档:https://mybatis.org/mybatis-3/zh/getting-started.html
1.2 持久化
数据持久化
持久化就是将程序的数据在持久状态和瞬时状态转化的过程
内存:断电即失
数据库(JDBC),I/O文件持久化
生活:冷藏、罐头
1.3 持久层
Dao层、Service层、Controller层
完成持久化工作的代码块
层的界限十分明显
1.4 为什么需要Mybatis?
帮助程序员将数据存储到数据库中
方便、传统的JDBC代码太复杂,Mybatis框架更容易上手
简单易学、灵活
sql和代码的分离,提高了可维护性。
提供映射标签,支持对象与数据库
orm字段关系映射
提供对象关系映射标签,支持对象关系组建维护
提供xml标签,支持编写动态sql。
最重要的一点:使用的人多
二、第一个Mybatis程序
思路:
1.创建父工程 引入mysql mybatis Junit 依赖
2.maven子工程 编写mybatis核心配置文件 mybatis-config.xml 连接数据库
3.untils层 pojo层 dao层
4.编写mybatis工具类 编写实体类
5.编写Mapper接口 以及对应UseMapper.xml配置文件
6.Junit测试
2.1 新建项目
建立mysql数据库
CREATE DATABASE MYBATIS; USE MYBATIS; CREATE TABLE user( id INT(20) NOT NULL PRIMARY KEY, name VARCHAR(30) DEFAULT NULL, pwd VARCHAR(30) DEFAULT NULL )ENGINE = INNODB DEFAULT CHARSET = utf8; INSERT INTO user(id, name, pwd) VALUES (1, '孙孙孙', 2002), (2, '铭铭铭', 1208), (3, '孙不坚', 1234);
新建项目
1.新建一个普通的maven项目
2.删除src目录
3.导入maven依赖
将该工程当做父工程
<!--导入依赖--> <dependencies> <!--mysql驱动--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.47</version> </dependency> <!--mybatis驱动--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.3</version> </dependency> <!--junit驱动--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> </dependencies>
4.创建子工程
2.2 创建一个模块
编写Mybatis的核心配置文件
<?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核心配置文件--> <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://localhost:3306/mybatis?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC"/> <property name="username" value="root"/> <property name="password" value="sm1208"/> </dataSource> </environment> </environments> <!--每一个Mapper.xml都需要Mybatis核心配置文件中注册!--> <mappers> <mapper resource="com/sun/dao/UserMapper.xml"/> </mappers> </configuration>
编写Mybatis的工具类
package com.sun.utils; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import java.io.IOException; import java.io.InputStream; //sqlSessionFactory --> sqlSession public class MybatisUtils { private static SqlSessionFactory sqlSessionFactory = null; static { try { // 使用Mybatis 第一步:获取sqlSessionFactory对象 String resource = "mybatis-config.xml"; InputStream in = Resources.getResourceAsStream(resource); sqlSessionFactory = new SqlSessionFactoryBuilder().build(in); } catch (IOException e) { e.printStackTrace(); } } // 有了SqlSessionFactory,顾名思义,我们就可以从中获得 SqlSession 的实例了 // SqlSession 完全包含了面向数据库执行 SQL 命令所需要的所有方法 public static SqlSession getSqlSession(){ return sqlSessionFactory.openSession(); } }
2.3 编写代码
实体类
package com.sun.pojo; public class User { private int id; private String name; private String pwd; public User() { } public User(int id, String name, String pwd) { this.id = id; this.name = name; this.pwd = pwd; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPwd() { return pwd; } public void setPwd(String pwd) { this.pwd = pwd; } @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + ", pwd='" + pwd + '\'' + '}'; } }
Mapper接口
package com.sun.dao; import com.sun.pojo.User; import java.util.List; public interface UserMapper { //查询所有的用户 List<User> getUserList(); }
接口实现类,由原来的UserDaoImp转变为一个Mapper配置文件,即UseMapper.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=绑定一定是对应的Dao/Mapper接口 --> <mapper namespace="com.sun.dao.UserMapper"> <!-- select查询语句 --> <select id="getUserList" resultType="com.sun.pojo.User"> select * from mybatis.user; </select> </mapper>
2.4 测试
junit 测试
package com.sun.dao; import com.sun.pojo.User; import com.sun.utils.MybatisUtils; import org.apache.ibatis.session.SqlSession; import org.junit.Test; import java.util.List; public class UserMapperTest { @Test public void test(){ // 第一步:获取SqlSession对象 SqlSession sqlSession = MybatisUtils.getSqlSession(); // 方式一:getMapper UserMapper userMapper = sqlSession.getMapper(UserMapper.class); List<User> userList = userMapper.getUserList(); for (User user : userList) { System.out.println(user); } // 关闭 SqlSession sqlSession.close(); } }
2.5 常见问题
a 解决maven引入依赖资源过滤问题
<!-- 在build中配置resources,防止资源导出失败的问题 --> <build> <resources> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>true</filtering> </resource> <resource> <directory>src/main/java</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>true</filtering> </resource> </resources> </build>
b 解决xml文件中文字符集产生报错的问题
//引入依赖 <!-- <properties>--> <!-- <!– 设置默认编码 –>--> <!-- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>--> <!-- </properties>-->
c 核心配置文件中注册 mappers
注意点:org.apache.ibatis.binding.BindingException: Type interface com.xulong.dao.UserDao is not known to the MapperRegistry.
<!--每一个Mapper.xml都需要Mybatis核心配置文件中注册!--> <mappers> <mapper resource="com/sun/dao/UserMapper.xml"/> </mappers>
三、CRUD
namespace中的包名要和 Dao/Mapper 接口的包名一致
在xml文件sql
id : 就是对应的 namespace 中的方法名
resultType : Sql 语句执行的返回值
parameterType :参数类型
编写接口 编写对应Mapper中的sql语句 编写测试
增 删 改 需要提交事务 !
1. Select
//根据ID查询用户 User getUserByID(int id);
<select id="getUserByID" parameterType="int" resultType="com.sun.pojo.User"> select * from mybatis.user where id = #{id}; </select>
@Test public void getUserByID(){ SqlSession sqlSession = MybatisUtils.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); User user = mapper.getUserByID(1); System.out.println(user); sqlSession.close(); }
2. Insert
int addUser(User user); <!-- 对象中的属性可以直接取出来 --> <insert id="addUser" parameterType="com.sun.pojo.User"> insert into mybatis.user (id, name, pwd) values (#{id}, #{name}, #{pwd}); </insert> @Test public void addUser(){ SqlSession sqlSession = MybatisUtils.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); User user = new User(4, "孙明明", "1324214"); int result = mapper.addUser(user); if (result > 0){ System.out.println("插入成功!"); } //提交事务 sqlSession.commit(); sqlSession.close(); }
3. Updata
//修改用户 int updateUser(User user);
<update id="updateUser" parameterType="com.sun.pojo.User"> update mybatis.user set name = #{name}, pwd = #{pwd} where id = #{id}; </update>
@Test public void updateUser(){ SqlSession sqlSession = MybatisUtils.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); User user = new User(5, "旺财", "14432434"); mapper.updateUser(user); int result = mapper.updateUser(user); if (result > 0){ System.out.println("修改成功!"); } sqlSession.commit(); sqlSession.close(); }
4. Delete
//删除用户 int deleteUser(int id);
<delete id="deleteUser" parameterType="int"> delete from mybatis.user where id = #{id}; </delete>
@Test public void deleteUser(){ SqlSession sqlSession = MybatisUtils.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); mapper.deleteUser(4); sqlSession.commit(); sqlSession.close(); }
5. Map
假设我们的实体类,数据库中的表、字段或者参数过多,我们应当考虑使用Map。
//万能的Map int addUser1(Map<String, Object> map);
<!-- 对象中的属性可以直接取出来 传递Map中的key --> <insert id="addUser1" parameterType="Map"> insert into mybatis.user (id, name, pwd) values (#{userid}, #{username}, #{password}); </insert>
@Test public void addUser1(){ SqlSession sqlSession = MybatisUtils.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); Map<String, Object> map = new HashMap<>(); map.put("userid", 5); map.put("username", "赵六"); map.put("password", "144324324"); mapper.addUser1(map); sqlSession.close(); }
Map传递参数,直接在sql中取出key即可【parameterType=“Map”】
对象传递参数,直接在sql中取对象的属性即可【parameterType=“Object”】
只有一个基本类型参数的情况下,可以直接在sql中取到,不需要parameterType的设置
多个参数用Map,或者注解
四、核心配置解析
mybatis-config.xml配置解析
1. 属性 (properties)
xml里属性都是可外部配置且可动态替换的,我们可以通过properties属性来实现引用配置文件。
编写一个配置文件 db.properties
driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/mybatis?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC username=root password=sm1208
在核心配置文件中引入
直接引入外部文件
<!-- 引入外部配置文件 -->
<properties resource="db.properties"> </properties>
可以在其中增加一些属性配置
<!-- 引入外部配置文件 --> <properties resource="db.properties"> <property name="username" value="root"/> <property name="password" value="sm1208"/> </properties>
如果两个文件有同一个字段,优先使用外部配置文件
2. 设置 (settings)
3. 类型别名(typeAliases)
类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写。
第一种配置方式 ,User 可以用在任何使用 com.sun.pojo.User 的地方使用。
<typeAliases> <typeAlias alias="User" type="com.sun.pojo.User"/> </typeAliases>
第二种配置方式,指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean,例如:
扫描实体类pojo的包,它的默认别名就为这个类的类名User。
<typeAliases> <package name="com.sun.pojo"/> </typeAliases>
在实体类比较少的情况,推荐使用第一种方式,如果实体类多的情况下,建议使用第二种方式,第一种可以DIY别名,第二种则不行,如果想实现第二种的DIY,在第二种配置方式的基础上还需要在实体类上增加注解:
import org.apache.ibatis.type.Alias; @Alias("hello") public class User { }
4. 类型处理器(typeHandlers)
5. 对象工厂(objectFactory)
6. 插件(plugins)
7. 环境配置(environments)
MyBatis 可以配置成适应多种环境,尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。
默认使用的环境 ID(比如:default=“development”)。
每个 environment 元素定义的环境 ID(比如:id=“development”)。
事务管理器的配置(比如:type=“JDBC”)。
数据源的配置(比如:type=“POOLED”)。
环境可以随意命名,但务必保证默认的环境 ID 要匹配其中一个环境 ID。
8. 数据库厂商标识(databaseIdProvider)
9. 映射器(mappers)
MyBatis 的行为已经由上述元素配置完了,我们现在就要来定义 SQL 映射语句了。 但首先,我们需要告诉 MyBatis 到哪里去找到这些语句。 在自动查找资源方面,Java 并没有提供一个很好的解决方案,所以最好的办法是直接告诉 MyBatis 到哪里去找映射文件,**即映射器注册问题MapperRegistry:注册绑定我们的Mapper文件。**你可以使用相对于类路径的资源引用,或完全限定资源定位符(包括 file:/// 形式的 URL),或类名和包名等。例如:
【推荐使用】
<!-- 使用相对于类路径的资源引用 --> <mappers> <mapper resource="com/sun/dao/UserMapper.xml"/> </mappers>
使用class文件进行绑定
<!-- 使用映射器接口实现类的完全限定类名 --> <mappers> <mapper class="com.sun.dao.UserMapper"/> </mappers>
接口和其对应的Mapper配置文件必须同名
接口和其对应的Mapper配置文件必须在同一个包下
使用扫描包进行注入绑定
<!-- 将包内的映射器接口实现全部注册为映射器 --> <mappers> <package name="com.sun.dao"/> </mappers>
接口和其对应的Mapper配置文件必须同名
接口和其对应的Mapper配置文件必须在同一个包下
10. 生命周期和作用域
五、使用注解开发
1. 面向接口编程
大家之前都学习过面向对象编程,也学习过接口,但在真正的开发中,很多时候我们会选择面向接口编程。
根本原因:解耦,可拓展,提高复用,分层开发中,上层不用管具体的实现,大家都遵守共同的标准,使得开发变得容易,规范性更好。
在一个面向对象的系统中,系统的各种功能是由许许多多的不同对象协助完成的。在这种情况下,各个对象内部是如何实现自己的,对系统设计人员来讲就不那么重要了。
而各个对象之间的协作关系则成为系统设计的关键。小到不同类之间的通信,大道各模块之间的交互,在系统设计之初都是要着重考虑的,这也是系统设计的主要工作内容。面向接口编程就是按照这种思想来编程。
关于接口的理解
接口从更深层次的理解,应是定义(规范、约束)与实现(名实分离的原则)的分离。
接口的本身反映了系统设计人员对系统的抽象理解。
接口应有两种
第一类是对一个个体的抽象,它可对应为一个抽象体(abstract class)
第二类是对一个个体某一方面的抽象,即形成一个抽象面(interface)
一个体可能有多个抽象面,抽象体和抽象面是有区别的。
三个面向区别
面向向对象是指,我们考虑问题时,以对象为单位,考虑它的属性及方法。
面向过程是指,我们考虑问题时,以一个具体的流程(事务过程)为单位,考虑它的实现。
接口设计与非接口设计是针对复用技术而言的,与面向对象(过程)不是一个问题,更多的体现就是对系统整体的架构。
2. 使用注解开发
注解在接口上实现
@Select("select * from user") List<User> getUsers();
在核心配置文件中绑定接口
<!-- 绑定接口 --> <mappers> <mapper class="com.fj.dao.UserMapper"/> </mappers>
测试
@Test public void test(){ SqlSession sqlSession = MybatisUtils.getSqlSession(); //底层主要应用反射 UserMapper mapper = sqlSession.getMapper(UserMapper.class); List<User> users = mapper.getUsers(); for (User user : users){ System.out.println(user); } sqlSession.close(); }
本质:反射机制实现
底层:动态代理
Mybatis详细执行流程
3.注解-CRUD
我们可以在工具类创建的时候实现自动提交事务
public static SqlSession getSqlSession(){ return sqlSessionFactory.openSession(true); }
编写接口,添加注解
@Select("select * from user") List<User> getUsers(); // 方法中如果有多个参数,那么每一个参数前都必须加上@Param("") @Select("select * from user where id = #{id}") User getUserByID(@Param("id") int id); // User getUserByID(@Param("id") int id, @Param("name") String name); @Insert("insert into user (id, name, pwd) values (#{id}, #{name}, #{password})") int addUser(User user); @Update("update user set name = #{name}, pwd = #{password} where id = #{id}") int updateUser(User user); @Delete("delete from user where id = #{id}") int deleteUser(@Param("id") int id);
测试类
【注意,我们必须要将接口绑定到核心配置文件mybatis-config.xml文件中】
<!-- 绑定接口 --> <mappers> <mapper class="com.sun.dao.UserMapper"/> </mappers>
持续更新中…




