这是我参与8月更文挑战的第5天,活动详情查看:8月更文挑战
一、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:github.com/mybatis/myb…
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>
-