1.MyBatis概述
- MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。
- Mybatis通过xml或注解的方式将要执行的各种statement(statement、preparedStatement、CallableStatement)配置起来,并通过java对象和statement中的sql进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射成java对象并返回。
2.为什么要使用MyBatis(使用JDBC编程有哪些问题)?
- 数据库链接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库链接池可解决此问题
- Sql语句在代码中硬编码,造成代码不易维护,实际应用sql变化的可能较大,sql变动需要改变java代码
- 使用preparedStatement向占有位符号传参数存在硬编码,因为sql语句的where条件不一定,可能多也可能少,修改sql还要修改代码,系统不易维护
- 对结果集解析存在硬编码(查询列名),sql变化导致解析代码变化,系统不易维护,如果能将数据库记录封装成pojo对象解析比较方便
3.MyBatis架构
- MyBatis配置
SqlMapConfig.xml,此文件作为mybatis的全局配置文件,配置了mybatis的运行环境等信息
mapper.xml文件即sql映射文件,文件中配置了操作数据库的sql语句。此文件需要在SqlMapConfig.xml中加载
- 通过mybatis环境等配置信息构造SqlSessionFactory即会话工厂
-由会话工厂创建sqlSession即会话,操作数据库需要通过sqlSession进行。
-mybatis底层自定义了Executor执行器接口操作数据库,Executor接口有两个实现,一个是基本执行器、一个是缓存执行器。 - Mapped Statement也是mybatis一个底层封装对象,它包装了mybatis配置信息及sql映射信息等。mapper.xml文件中一个sql对应一个Mapped Statement对象,sql的id即是Mapped statement的id。
- Mapped Statement对sql执行输入参数进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql前将输入的java对象映射至sql中,输入参数映射就是jdbc编程中对preparedStatement设置参数。
- Mapped Statement对sql执行输出结果进行定义,包括HashMap、基本类型、pojo,Executor
4.MyBatis入门
创建Maven工程,修改pom.xml导入MyBatis以及Junit和MySql驱动的jar包
<dependencies>
<!-- MySQL驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.45</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
classpath目录下创建MyBatis的核心配置文件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 resource="db.properties" />
<typeAliases>
<!-- 使用包扫描的方式批量定义别名定以后别名等于类名,不区分大小写,
但是建议按照java命名规则来,首字母小写,以后每个单词的首字母大写
-->
<package name="com.johnfnash.learn.mybatis.entity"/>
</typeAliases>
<environments default="development">
<environment id="development">
<!-- 使用jdbc事务管理 -->
<transactionManager type="JDBC" />
<!-- 数据库连接池 -->
<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>
</environment>
</environments>
<!-- 加载映射文件 -->
<mappers>
<mapper resource="mappers/UserMapper.xml"/>
<!-- 下面的好像不行 -->
<!-- <package name="com.johnfnash.learn.mybatis.mapper"/> -->
</mappers>
</configuration>
注意:这里数据库连接相关信息放入了 db.properties 文件中,使用 properties 标签引入配置文件,并在下面使用 ${xxx} 的形式引用。
创建测试数据库
创建po类 —Po类作为mybatis进行sql映射使用,po类通常与数据库表对应
package com.johnfnash.learn.mybatis.entity;
import java.util.Date;
public class User {
private int id;
private String username;// 用户姓名
private String sex;// 性别
private Date birthday;// 生日
private String address;// 地址
// getter, setter
@Override
public String toString() {
return "User [id=" + id + ", username=" + username + ", sex=" + sex + ", birthday=" + birthday + ", address="
+ address + "]";
}
}
创建sql映射文件UserMapper.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隔离 -->
<mapper namespace="com.johnfnash.learn.mybatis.mapper.UserMapper">
<!-- 将数据库表字段映射到类的属性 -->
<resultMap type="User" id="UserResultMap">
<id property="id" column="id"/>
<result property="username" column="username" />
<result property="sex" column="sex" />
<result property="birthday" column="birthday" />
<result property="address" column="address" />
</resultMap>
<!--
id:sql语句唯一标识
parameterType:指定传入参数类型,可以忽略,直接使用内联参数
resultType:返回结果集类型
#{}占位符:起到占位作用,如果传入的是基本类型(string,long,double,int,boolean,float等),那么#{}中的变量名称可以随意写.
-->
<select id="findUserById" parameterType="java.lang.Integer" resultMap="UserResultMap">
select * from user where id=#{id}
</select>
<!--
如果返回结果为集合,可以调用selectList方法,这个方法返回的结果就是一个集合,所以映射文件中应该配置成集合泛型的类型
${}拼接符:字符串原样拼接,如果传入的参数是基本类型(string,long,double,int,boolean,float等),那么${}中的变量名称必须是value
注意:拼接符有sql注入的风险,所以慎重使用
-->
<select id="findUserByUserName" parameterType="java.lang.String" resultType="User">
select * from user where username like '%${value}%'
</select>
<!--
#{}:如果传入的是pojo类型,那么#{}中的变量名称必须是pojo中对应的属性.属性.属性.....
如果要返回数据库自增主键:可以使用select LAST_INSERT_ID()
-->
<insert id="insertUser" parameterType="User" >
<!-- 执行 select LAST_INSERT_ID()数据库函数,返回自增的主键
keyProperty:将返回的主键放入传入参数的Id中保存.
order:当前函数相对于insert语句的执行顺序,在insert前执行是before,在insert后执行是AFTER
resultType:id的类型,也就是keyproperties中属性的类型
-->
<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
select LAST_INSERT_ID()
</selectKey>
insert into user (username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address})
</insert>
<delete id="delUserById" parameterType="int">
delete from user where id=#{id}
</delete>
<update id="updateUserById" parameterType="User">
update user set username=#{username} where id=#{id}
</update>
</mapper>
加载映射文件 --mybatis框架需要加载映射文件,将User.xml添加在SqlMapConfig.xml
<!-- 加载映射文件 -->
<mappers>
<mapper resource="mappers/UserMapper.xml"/>
</mappers>
创建测试类UserTest进行测试
查询单个User对象
package com.johnfnash.learn.mybatis;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
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 org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.johnfnash.learn.mybatis.entity.User;
public class MybatisTest {
private final String RESOURCE = "SqlMapConfig.xml";
private SqlSession session;
@Before
public void Before() throws IOException {
// 通过流将核心配置文件加载进来
InputStream inputStream = Resources.getResourceAsStream(RESOURCE);
// 通过配置文件创建会话工厂
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
// 通过会话工厂获取会话
session = factory.openSession();
}
@After
public void after() {
// 关闭会话
if(session != null) {
session.close();
}
}
@Test
public void test1() {
// 通过会话执行sql 第一个参数是名称空间+SqlID 第二个参数表示sql执行需要的参数
User user = session.selectOne("com.johnfnash.learn.mybatis.mapper.UserMapper.findUserById", 1);
System.out.println(user);
}
}
通过username进行模糊查询
@Test
public void test2() {
// 调用User.xml中的魔化查询方法 返回集合
List<User> selectList = session.selectList("com.johnfnash.learn.mybatis.mapper.UserMapper.findUserByUserName", "张");
// 循环结果
System.out.println(selectList.size());
for (User user : selectList) {
System.out.println(user.toString());
}
}
添加一条User用户到数据库
@Test
public void test3() {
// 创建需要插入的User对象
User user = new User();
user.setUsername("Jimisun");
user.setSex("1");
user.setAddress("北京");
System.out.println("====插入前的User的id=" + user.getId());
// 会话调用插入的sql
session.insert("com.johnfnash.learn.mybatis.mapper.UserMapper.insertUser", user);
// 默认mybatis自动开启事务,需要手动提交事务
session.commit();
System.out.println("====插入后的User的id=" + user.getId());
}
删除一条记录
@Test
public void test4() throws IOException {
// 会话执行sql操作
session.delete("com.johnfnash.learn.mybatis.mapper.UserMapper.delUserById", 10);
// 提交事务
session.commit();
}
更新一条记录
@Test
public void test5() throws Exception {
//创建User对象
User user = new User ();
user.setId(1);
user.setUsername("王麻子222");
session.update("com.johnfnash.learn.mybatis.mapper.UserMapper.updateUserById", user);
//提交事务
session.commit();
}
5.使用MyBatis的开发方法
原生Dao方法
- UserDao 接口
- UserDaoImpl 实现类
- findUserById() -----方法内使用MyBatis框架进行操作
// 核心配置文件
String resource = "SqlMapConfig.xml";
// 通过流将核心配置文件加载进来
InputStream inputStream = Resources.getResourceAsStream(resource);
// 通过配置文件创建会话工厂
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
// 通过会话工厂获取会话
SqlSession openSession = factory.openSession();
// 通过会话执行sql 第一个参数是名称空间+SqlID 第二个参数表示sql执行需要的参数
User user = openSession.selectOne("test.findUserById", 1);
System.out.println(user.toString());
// 关闭会话
openSession.close();
Mapper接口开发
Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象,代理对象的方法体同上边Dao接口实现类方法。
- 开发规范
- Mapper.xml文件中的namespace与mapper接口的类路径相同。
- Mapper接口方法名和Mapper.xml中定义的每个statement的id相同
- Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同
- Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同
- 开发目录
- UserDao 接口 遵循上面规则
- UserServiceImpl直接调用
@Override
public User findUserById(Integer id) throws IOException {
SqlSession session = SqlSessionUtil.getSession();
//通过getMapper方法来实例化接口
UserMapper mapper = session.getMapper(UserMapper.class);
User user = mapper.findUserById(id);
session.close();
return user;
}
其中, SqlSessionUtil 工具类如下:
package com.johnfnash.learn.mybatis.util;
import java.io.IOException;
import java.io.InputStream;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
public class SqlSessionUtil {
private final static String RESOURCE = "SqlMapConfig.xml";
public static SqlSession getSession() throws IOException {
// 通过流将核心配置文件加载进来
InputStream inputStream = Resources.getResourceAsStream(RESOURCE);
// 通过配置文件创建会话工厂
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
// 通过会话工厂获取会话
SqlSession session = factory.openSession();
return session;
}
}
6.SqlMapConfig.xml配置文件
- properties(属性) 常用于加载配置文件
<properties resource="db.properties" />
<environments default="development">
<environment id="development">
<!-- 使用jdbc事务管理-->
<transactionManager type="JDBC" />
<!-- 数据库连接池-->
<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>
</environment>
</environments>
- typeAliases(类型别名)
<typeAliases>
<!-- 定义单个pojo类别名
type:类的全路劲名称
alias:别名
-->
<!-- <typeAlias type="cn.itheima.pojo.User" alias="user"/> -->
<!-- 使用包扫描的方式批量定义别名
定以后别名等于类名,不区分大小写,但是建议按照java命名规则来,首字母小写,以后每个单词的首字母大写
-->
<package name="cn.itheima.pojo"/>
</typeAliases>
- mappers(映射器)
- 相对于类路径的资源
<mapper resource="sqlmap/User.xml" />
- 使用mapper接口开发
<mapper class="cn.redrat.mybatis.mapper.UserMapper"/>
- 注册指定包下所有的mapper接口
<package name="cn.redrat.mybatis.mapper"/>
注意:此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。
7.输入映射和输出映射
Mapper.xml映射文件中定义了操作数据库的sql,每个sql是一个statement,映射文件是mybatis的核心。
- parameterType(输入类型)
- 传递基本类型包含String
- 传递pojo对象
- 传递vo对象
- resultType(输出类型)
- 返回pojo类型
- 返回集合
- 返回基本类型包含String
- resultMap
- 映射数据库字段与实体类属性
<!-- 将数据库表字段映射到类的属性 -->
<resultMap type="User" id="UserResultMap">
<id property="id" column="id"/>
<result property="username" column="username" />
<result property="sex" column="sex" />
<result property="birthday" column="birthday" />
<result property="address" column="address" />
</resultMap>
注:如果数据库字段名与实体类属性名不一致,需要对字段名取别名或者使用 resultMap 进行映射。一对一、一对多映射也使用得到 resultMap。
本文转自:MyBatis基础入门