Mybatis入门到精通
Mybatis简介
MyBatis 是一个可以自定义SQL、存储过程和高级映射的持久层框架。MyBatis 摒除了大部分的JDBC代码、手工设置参数和结果集重获。MyBatis 只使用简单的XML 和注解来配置和映射基本数据类型、Map 接口和POJO 到数据库记录。相对Hibernate和Apache OJB等“一站式”ORM解决方案而言,Mybatis 是一种“半自动化”的ORM实现。
需要使用的Jar包:mybatis-3.4.6.jar(mybatis核心包)
下载地址:
https://mvnrepository.com/artifact/org.mybatis/mybatis
Mybatis构造
1。mybatis需要配置SqlMapConfig.xml,此文件作为mybatis的全局配置文件,配置了mybatis的运行环境等信息。mapper.xml文件即sql映射文件,文件中配置了操作数据库的sql语句。此文件需要在SqlMapConfig.xml中加载。
2。通过mybatis环境等配置信息构造SqlSessionFactory即会话工厂
3。由会话工厂创建sqlSession即会话,操作数据库需要通过sqlSession进行。
3mybatis底层自定义了Executor执行器接口操作数据库,Executor接口有两个实现,一个是基本执行器、一个是缓存执行器。
4。Mapped Statement也是mybatis一个底层封装对象,它包装了mybatis配置信息及sql映射信息等。mapper.xml文件中一个sql对应一个Mapped Statement对象,sql的id即是Mapped statement的id。
5。Mapped Statement对sql执行输入参数进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql前将输入的java对象映射至sql中,输入参数映射就是jdbc编程中对preparedStatement设置参数。
6。Mapped Statement对sql执行输出结果进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql后将输出结果映射至java对象中,输出结果映射过程相当于jdbc编程中对结果的解析处理过程。
Mybatis入门
第一步:先创建一个数据库已经表,再添加几条测试的数据,以供我们来操作
CREATE DATABASE mybatis
CREATE TABLE `user` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`username` VARCHAR(32) NOT NULL COMMENT '用户名称',
`birthday` DATE DEFAULT NULL COMMENT '生日',
`sex` CHAR(1) DEFAULT NULL COMMENT '性别',
`address` VARCHAR(256) DEFAULT NULL COMMENT '地址',
PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8;
INSERT INTO `user` VALUES (1,'老王', '2015-07-08', '男', '长沙市');
INSERT INTO `user` VALUES (2,'张三', '2014-07-10', '女', '北京市');
INSERT INTO `user` VALUES (3,'李四', '2018-08-08', '男', '河南省');
第二步:创建java项目,创建Mybatis核心配置文件sqlMapConfig.xml SqlMapConfig.xml是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>
<environments default="development">
<environment id="development">
<!-- 使用jdbc的事务 -->
<transactionManager type="JDBC"/>
<!-- 使用连接池 连接数据库 -->
<dataSource type="POOLED">
<!-- 我这里用的是mysql 8.0以上的才需要后面加'?serverTimezone=UTC' 如果你不是的话就不需要 -->
<!--
不是8.0以上的设置是这样的
<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"/>
-->
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC"/>
<!--这里是mysql的用户名如果没用修改过 一般情况下都是 root -->
<property name="username" value="root"/>
<!--这里是mysql登录的密码 你设置什么就填什么 -->
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!-- 配置映射器的位置 -->
</configuration>
**第三步:创建和数据库表对应的pojo类 **
public class User implements Serializable {
private Integer id;
private String username; //用户姓名
private String sex; //性别
private Date birthday; //生日
private String address;//住址
public User(){
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
Mapper动态代理方式 Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象。。。开发中使用这种方式来进行开发,简便快捷,代码复用性高,免去很多重复繁琐代码。
第四步:创建UserMapper的接口
//根据id查询数据
List<User> findyUserByid(Integer id);
//根据用户名进行模糊查询
List<User> findUserByUsername(String username);
//添加
Integer insertUser(User user);
//根据id修改
Integer updateUser(Integer id);
//根据id删除
Integer deleteUser(Integer id);
第五步:创建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:这里引入UserMapper的接口 我的UserMapper放在mapper包下 你们也可以建一个 -->
<mapper namespace="mapper.UserMapper">
<!--id为sql语句的id,parameterType为参数类型,resultType为结果类型,#{}为占位符-->
<!--根据id查找用户,#{}里面可以随便写-->
<select id="findyUserByid" parameterType="java.lang.Integer" resultType="pojo.User">
select * from user where id =#{id}
</select>
</mapper>
**第六步sqlMapConfig配置文件中要引入映射文件 **
<mappers>
<mapper resource="mapper.UserMapper.xml"/>
</mappers>
第六步,测试程序,简单的操作
public class MybatisTest {
@Test
public void findyUserByidtest() {
SqlSession sqlSession = null;
try {
InputStream in = Resources.getResourceAsStream("sqlMapConfig.xml");
//创建SqlSessionFactoryBuilder对象用来创建工厂
SqlSessionFactoryBuilder builder= new SqlSessionFactoryBuilder();
//创建工厂
SqlSessionFactory factory=builder.build(in);
//创建Session
sqlSession=factory.openSession();
//这里是反射了一个UserMapper 用来执行sql
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
//这里是查询id为1的数据 当然你也可以查询其他的
List<User> list = mapper.findyUserByid(1);
for (User user : list) {
System.out.println(user);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
sqlSession.close();
}
}
}
模糊查询
<select id="findUserByUsername" parameterType="java.lang.String" resultType="pojo.User">
select * from user where username like "%"#{username}"%"
<!--这里还有一种写法
select * from user where username like concat('%',#{username},'%')
-->
</select>
@Test
public void findUserByUsernametest() {
SqlSession sqlSession = null;
try {
InputStream in = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactoryBuilder builder= new SqlSessionFactoryBuilder();
SqlSessionFactory factory=builder.build(in);
sqlSession=factory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> list = mapper.findUserByUsername('王');
for (User user : list) {
System.out.println(user);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
sqlSession.close();
}
}
添加
<!-- 添加操作 -->
<insert id="insertUser" parameterType="pojo.User">
insert into user(username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address})
</insert>
@Test
public void insertUserTest() {
SqlSession sqlSession = null;
Integer count = 0; //返回影响的行数
try {
InputStream in = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactoryBuilder builder= new SqlSessionFactoryBuilder();
SqlSessionFactory factory=builder.build(in);
sqlSession=factory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = new User();
user.setUsername("齐天大圣");
user.setBirthday(new Date());
user.setSex("男");
user.setAddress("花果山");
count = mapper.insertUser(user)
System.out.println("受影响的行数:"+count);
//这里需要提交事务 当时Mybaits默认的自动提交 当为了安全起见还是自己提交一下比较好
sqlSession.commit();
} catch (IOException e) {
e.printStackTrace();
}finally {
sqlSession.close();
}
}
修改
<!-- 修改操作 -->
<update id="updateUser" parameterType="pojo.User">
update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id}
</update>
@Test
public void updateUserTest() {
SqlSession sqlSession = null;
Integer count = 0; //返回影响的行数
try {
InputStream in = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactoryBuilder builder= new SqlSessionFactoryBuilder();
SqlSessionFactory factory=builder.build(in);
sqlSession=factory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = new User();
user.setId(1);
user.setUsername("天蓬元帅");
user.setBirthday(new Date());
user.setSex("女");
user.setAddress("银河");
count = mapper.updateUser(user);
System.out.println("受影响的行数:"+count);
sqlSession.commit();
} catch (IOException e) {
e.printStackTrace();
}finally {
sqlSession.close();
}
}
删除
<!-- 删除操作 -->
<delete id="deleteUser" parameterType="Integer">
delete from user where id=#{id}
</delete>
@Test
public void deleteUserTest() {
SqlSession sqlSession = null;
Integer count = 0; //返回影响的行数
try {
InputStream in = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactoryBuilder builder= new SqlSessionFactoryBuilder();
SqlSessionFactory factory=builder.build(in);
sqlSession=factory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
count = mapper.deleteUser(1);
System.out.println("受影响的行数:"+count);
sqlSession.commit();
} catch (IOException e) {
e.printStackTrace();
}finally {
sqlSession.close();
}
}
经过上面几个示例下面 是不是觉得有很多操作相同,很多只改了执行的方法,这样写下来是不是很累很麻烦。既然有麻烦的自然就有简单的。下面所讲的是一个mybatis的工具类
Mybatis工具类
下面我们开始编写Mybits的工具类
public class MybatisUtil {
<!--这里是因为我们只需要创建一个工厂就够了 不需要每次都创建 所以放到static块里面-->
private static SqlSessionFactory factory;
static{
try {
InputStream in = Resources.getResourceAsStream("sqlMapConfig.xml");
factory = new SqlSessionFactoryBuilder().build(in);
} catch (IOException e) {
e.printStackTrace();
}
}
public static SqlSession createSqlseesion(){
//关闭自动提交事物 true:是开启自动提交事务 默认是开启自动提交事务 这里可以不需要写
return factory.openSession(false);
}
public static void closeSqlSession(SqlSession sqlSession){
if (null!=sqlSession){
sqlSession.close();
}
}
}
创建好工具类后,我们来测试一遍。这里我们将上面的删除来进行改造一下
@Test
public void deleteUserTest() {
SqlSession sqlSession = null;
Integer count = 0; //返回影响的行数
try {
//通过类名来调用里面的方法
sqlSession = MybatisUtil.createSqlseesion();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
count = mapper.deleteUser(1);
System.out.println("受影响的行数:"+count);
sqlSession.commit();
} catch (IOException e) {
e.printStackTrace();
}finally {
MybatisUtil.closeSqlSession(sqlSession);
}
}
在用MyBatis框架连接数据库时,往往要经常创建sessionFactory,重复的编写大量代码,故将其中的重复代码提出成一个工具类,这样直接调用方法即可,可简化代码编写和优化运行效率,不需要重复的读取mybatis核心配置文件和反复new工厂对象。。以上就是MybatisUtil工具类的用法
动态sql
if
<select id="findActiveBlogWithTitleLike"
resultType="Blog">
SELECT * FROM BLOG
WHERE state = ‘ACTIVE’
<if test="title != null">
AND title like #{title}
</if>
</select>
choose, when, otherwise
<select id="findActiveBlogLike"
resultType="Blog">
SELECT * FROM BLOG WHERE state = ‘ACTIVE’
<choose>
<when test="title != null">
AND title like #{title}
</when>
<when test="author != null and author.name != null">
AND author_name like #{author.name}
</when>
<otherwise>
AND featured = 1
</otherwise>
</choose>
</select>
where, set
<update id="updateAuthorIfNecessary">
update Author
<set>
<if test="username != null">username=#{username},</if>
<if test="password != null">password=#{password},</if>
<if test="email != null">email=#{email},</if>
<if test="bio != null">bio=#{bio}</if>
</set>
where id=#{id}
</update>
foreach
<select id="selectPostIn" resultType="domain.blog.Post">
SELECT *
FROM POST P
WHERE ID in
<foreach item="item" index="index" collection="list"
open="(" separator="," close=")">
#{item}
</foreach>
</select>