MyBatis (1)
MyBatis的使用第二部分,传送地址:MyBatis的使用(2) 使用注解的MyBatis 联合查询 分步查询 动态sql
文章目录
- MyBatis (1)
- 一、MyBatis简介
- 二、第一个MyBatis程序
- 三、使用MyBatis完成CRUD
- 四、MyBatis配置解析
- 1. 环境变量 (environments)
- 2. 事务管理器 (transactionManager)
- 3. 数据源 (dataSource)
- 4. 属性 (properties)
- 5. 类型别名 (typeAliases)
- 6. 映射器 (mappers)
- 五、MyBatis的生命周期和作用域
- 六、ResultMap的使用
- 七、日志工厂
- 八、其他注意点
一、MyBatis简介
MyBatis是一款持久层框架,几乎避免了所有JDBC代码的复杂编码过程
中文文档地址:https://mybatis.org/mybatis-3/zh/index.html
二、第一个MyBatis程序
- 创建数据库(mybatis)和表(user)
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,'周杰伦','123456'),
(2,'张学友','123456'),
(3,'郭富城','123890')
- IDEA中创建一个普通的Maven项目(POM工程)MyBatis,此工程的pom.xml中导入依赖
<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.6</version>
</dependency>
<!--导入Junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
<!-- 将src/main/java目录下的资源也打包 -->
<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>
- 创建一个上述Maven工程的子Maven工程mybatis-01 (右键new module)
此工程会自动导入父工程依赖的jar包,此工程的pom.xml中也加入将src/main/java打包的代码
子工程的src/main/resources/目录下右键new → File;
创建MyBatis的核心配置文件mybatis-config.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核心配置文件-->
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<!-- xml文件中 "&" 需要转义成为 "&" -->
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=false&useUnicode=true&characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
</configuration>
- 子工程的src/main/java/目录下创建一个包com.qizegao.utils
编写MyBatis工具类MybatisUtils.java
public class MybatisUtils {
//1. 获取SqlSessionFactory接口的对象
private static SqlSessionFactory sqlSessionFactory;
static {
try {
//声明MyBatis的核心配置文件mybatis-config.xml的位置
String resource = "mybatis-config.xml";
InputStream resourceAsStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
} catch (IOException e) {
e.printStackTrace();
}
}
//2. 获取SqlSession接口的对象
//SqlSession中包含了操作数据库的方法
public static SqlSession getSqlSession() {
return sqlSessionFactory.openSession();
}
}
- 子工程的src/main/java目录下创建一个包com.qizegao.pojo
编写User类
public class User {
private int id;
private String name;
private String pwd;
//以及标准java bean的其余结构
}
- 子工程的src/main/java目录下创建一个包com.qizegao.dao
编写UserMapper接口(与UserDao作用一致)
public interface UserMapper {
List<User> getUserList();
}
- 子工程的src/main/resources目录下创建com.qizegao.dao包
包下创建配置文件UserMapper.xml (名字与UserMapper对应),此文件相当于之前的UserDaoImpl
<?xml version="1.0" encoding="UTF8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace属性绑定一个对应的Dao/Mapper接口,写全类名 -->
<mapper namespace="com.qizegao.dao.UserMapper">
<!-- select标签代表查询语句 -->
<!-- id属性对应Mapper接口中要执行的方法名 -->
<!-- resultType属性表示查询结果的类型,写全类名 -->
<select id="getUserList" resultType="com.qizegao.pojo.User">
select * from user
</select>
</mapper>
- 每一个Mapper.xml都需要在MyBatis的核心配置文件mybatis-config.xml中注册
故在mybatis-config.xml中添加如下:
<mappers>
<mapper resource="com/qizegao/dao/UserMapper.xml"/>
</mappers>
- 子工程的src/test/java目录下创建包com.qizegao.dao (测试包尽量与原包同名)
包下创建测试类UserMapperTest
public class UserMapperTest {
@Test
public void test() {
//1. 获取SqlSession对象
SqlSession sqlSession = MybatisUtils.getSqlSession();
//2. 获取UserMapper对象,执行其中的方法
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List<User> list = userMapper.getUserList();
//3. 打印查询结果
System.out.println(list);
//4. 关闭sqlSession
sqlSession.close();
}
}
运行结果:成功获取到数据
注意:
- 如果出现异常:
解决方式:使用IDEA自带的maven配置环境
- 如果出现异常:
解决方式:将Mapper.xml文件首部的UTF-8修改为UTF8
- 如果Mapper.xml没有在MyBatis的配置文件mybatis-config.xml中注册,则报异常:
三、使用MyBatis完成CRUD
- 查询
//UserMapper类中添加方法
User getUserById(int id);
<!-- UserMapper.xml的mapper标签中添加标签 -->
<!-- parameterType属性表示id属性对应的方法参数的类型 -->
<select id="getUserById" parameterType="int" resultType="com.qizegao.pojo.User">
select * from user where id = #{id}
</select>
//测试类中添加
@Test
public void test2() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.getUserById(1);
System.out.println(user);
//User{id=1, name='周杰伦', pwd='123456'}
sqlSession.close();
}
- 插入
//UserMapper类中添加方法
int addUser(User user);
<!-- UserMapper.xml的mapper标签中添加标签 -->
<insert id="addUser" parameterType="com.qizegao.pojo.User">
<!-- 对象中的属性可以通过#{}直接提取出来 -->
insert into mybatis.user (id, name, pwd) values (#{id},#{name},#{pwd});
</insert>
@Test
public void test2() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
int res = userMapper.addUser(new User(7, "黎明", "33445566"));
System.out.println("受影响的行数:" + res);//受影响的行数:1
sqlSession.commit(); //增删改需要提交事务
sqlSession.close();
}
- 修改
//UserMapper类中添加方法
int updateUser(User user);
<!-- UserMapper.xml的mapper标签中添加标签 -->
<update id="updateUser" parameterType="com.qizegao.pojo.User">
update user set name=#{name}, pwd=#{pwd} where id=#{id}
</update>
@Test
public void test2() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
int i = mapper.updateUser(new User(7, "蔡虚坤", "78956"));
System.out.println("受影响的行数:" + i); //受影响的行数:1
sqlSession.commit(); //增删改需要提交事务
sqlSession.close();
}
- 删除
//UserMapper类中添加方法
int deleteUser(int id);
<!-- UserMapper.xml的mapper标签中添加标签 -->
<delete id="deleteUser" parameterType="int">
delete from user where id=#{id}
</delete>
public void test2() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
int i = mapper.deleteUser(7);
System.out.println("受影响的行数:" + i); //受影响的行数:1
sqlSession.commit(); //增删改需要提交事务
sqlSession.close();
}
四、MyBatis配置解析
在MyBatis的核心配置文件mybatis-config.xml (任意起名)的configuration标签中写配置
1. 环境变量 (environments)
MyBatis配置文件中可以配置多种环境,使用environment标签声明,但只可以选择其中一种环境,通过environments标签的default属性决定使用哪一种环境
2. 事务管理器 (transactionManager)
默认使用JDBC,其余可去中文文档查看
3. 数据源 (dataSource)
默认使用POOLED,其余可去中文文档查看
如下代码所示:
<configuration>
<!-- 以下配置了两个环境,default标签中写某一环境的id属性值从而去使用它 -->
<environments default="development">
<environment id="development"> <!-- id属性给此环境起一个名称 -->
<transactionManager type="JDBC"/> <!-- 默认 -->
<dataSource type="POOLED"> <!-- 默认 -->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
<!-- 第二个环境 -->
<environment id="newEnvironment">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
</configuration>
4. 属性 (properties)
可以使用properties标签引用外部配置文件
(1) src/main/resources目录下创建一个配置文件db.properties
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatisuseSSL=false&useUnicode=true&characterEncoding=UTF-8
(2) mybatis-config.xml中编写
<configuration>
<!-- 引入外部配置文件 -->
<properties resource="db.properties">
<!-- properties标签中也可以声明key - value,与外部配置文件配合使用 -->
<property name="username" value="root"/>
<property name="password" value="root"/>
</properties>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<!-- 使用${}动态获取配置文件声明的key - value -->
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
</configuration>
注意:
- 如果外部配置文件的key和properties标签中声明的key同名,优先使用配置文件的
- mybatis - config.xml文件中congratulation标签中的标签声明有顺序要求
5. 类型别名 (typeAliases)
类型别名存在的意义是减少全类名的冗余,用法有两种 (在配置文件mybatis - config.xml中)
(1) 给全类名起别名
<typeAliases>
<!-- 以后在Mapper.xml中使用此类型时无需再写全类名,直接写User即可 -->
<typeAlias type="com.qizegao.pojo.User" alias="User"/>
</typeAliases>
(2) 扫描指定包下的类,某一类的别名默认是类名首字母小写
<typeAliases>
<!-- 此包下的User类的别名成为user -->
<package name="com.qizegao.pojo"/>
</typeAliases>
注意:可以在对应的类上加注解@Alias(“xxx”),则类名的别名成为指定的xxx
6. 映射器 (mappers)
用来注册绑定的Mapper.xml文件,有三种方式
每个Mapper.xml文件都需要在MyBatis的核心配置文件中注册
(1) 使用resources属性
<mappers>
<mapper resource="com/qizegao/dao/UserMapper.xml"></mapper>
</mappers>
(2) 使用class属性
<mappers>
<!-- class属性中写Mapper.xml文件绑定的Mapper接口 -->
<mapper class="com.qizegao.dao.UserMapper"></mapper>
<!--
1. 接口和其Mapper.xml配置文件必须同名
2. 接口和其Mapper.xml配置文件必须在同一个包下
-->
</mappers>
(3) 使用package标签
<mappers>
<!-- package标签可以扫描指定包下的Mapper.xml文件 -->
<package name="com.qizegao.dao"/>
<!--
1. 接口和其Mapper.xml配置文件必须同名
2. 接口和其Mapper.xml配置文件必须在同一个包下
-->
</mappers>
五、MyBatis的生命周期和作用域
如图所示:
- SqlSessionFactoryBuilder
使用其创建了SqlSessionFactory之后,就不再需要它了
- SqlSessionFactory
(1) 可以理解为数据库连接池
(2) 它一旦被创建就应该在运行期间一直存在,没有理由丢弃它或重新创建另一个实例
- SqlSession
(1) 可以理解为是连接到连接池的一个请求
(2) 它的实例不是线程安全的,因此不能被共享
(3) 使用完之后应该关闭,防止资源被占用
六、ResultMap的使用
为了解决属性名和数据库表中的列名不一致的问题,用法如下:
假设数据库表中有三列: id name pwd
假设对应类声明了三个属性: id name password
<!-- 在Mapper.xml中的mapper标签中使用 -->
<!--
1. id属性给resultMap标签做标识
2. type属性表示结果集要映射成为什么类型(为哪个类自定义封装规则)
-->
<resultMap id="UserMap" type="User">
<!-- 只需要写名字不同的项目即可,无需所有属性全部声明,未声明的需要列名属性名一一对应 -->
<!--
1. column属性表示数据库表中的列名
2. property属性表示类中的属性名
-->
<result column="pwd" property="password"/>
</resultMap>
<!-- resultMap属性指定使用哪一个resultMap标签 -->
<select id="getUserById" resultMap="UserMap"> <!-- sql语句 --> </select>
七、日志工厂
一个数据库操作出现了异常,使用日志是最好的排错助手
在mybatis-config.xml中的configuration标签中使用settings标签指明使用哪一种日志实现
常见的日志实现有两种:
(1) STDOUT_LOGGING (标准日志输出)
i. 配置文件中声明
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
ii. 测试类中执行一条sql语句,控制台输出:
(2) LOG4J的使用自行网上搜索
八、其他注意点
- ${} 和 #{} 的区别
MyBatis有两种取值方式:
#{属性名}:是预编译的方式,参数的位置都使用?替代,参数值都是预编译设置进去的;
比较安全,不会有sql注入问题
${属性名}:直接和sql语句拼串,不安全
一般都使用#{},在不支持预编译的位置要进行取值才使用${}
- 查询结果是Map类型
(1) 查询结果是一项封装成为一个Map对象时,resultType属性值为 ”map”
(2) 查询结果是多项封装成为一个Map对象时,需要在Mapper接口的方法上使用注解
@MapKey(“xxx”),将查询结果的xxx列作为key封装这个map,resultType属性值为
value对应的类型(不再是map)
- resultMap标签补充
(1) result标签用法如上所述
(2) id标签用来指定主键列的对应规则,与result标签的用法一致
主键列也可以使用result标签,但推荐使用id标签