Mybatis 快速入门详解

Mybatis 详解

image-20211228135542111

简介

MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。

MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。

MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

使用

①添加MyBatis的坐标

②创建user数据表 [默认已创建]

③编写User实体类 [默认已创建]

④编写映射文件UserMapper.xml

⑤编写核心文件Mybatis_config.xml

⑥编写测试类

Mybatis 坐标

<!--mybatis坐标-->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.4.5</version>
</dependency>
<!--mysql驱动坐标-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.18</version>
</dependency>
<!--单元测试坐标-->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
</dependency>
<!--日志坐标-->
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.12</version>
</dependency>

数据库与实体类

SQL语句,可直接导入

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for users
-- ----------------------------
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users`  (
  `uid` int NOT NULL AUTO_INCREMENT,
  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  `gender` char(2) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`uid`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of users
-- ----------------------------
INSERT INTO `users` VALUES (1, '张三', '男');
INSERT INTO `users` VALUES (2, '李四', '男');

SET FOREIGN_KEY_CHECKS = 1;

User 实体类字段

public class User {
    int id;
    String name;
    String gender;
}

Mybatis_config

将此配置文件放在resources目录下

<?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>
    <!-- mybatis环境-->
    <environments default="development">
        <!-- 第一个环境,id处也可以是default-->
        <environment id="development">
            <!-- JDBC事务-->
            <transactionManager type="JDBC"/>
            <!-- 连接数据库配置-->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://127.0.0.1:3306/cms_hisoft?useSSL=false&amp;useUnicode=true&amp;characterEncoding=utf-8&amp;serverTimezone=GMT-8"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
	<!-- 加载映射文件 -->
    <mappers>
        <mapper resource="com/bright/Dao/mapper/userMapper.xml"/>
    </mappers>
</configuration>

映射实现

创建接口

public interface User {
    public List<User> selectAll();
}

创建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">
<mapper namespace="userMapper">
    <select id="selectAll" resultType="com.bright.pojo.User">
        select * from users
    </select>

    <insert id="insert" parameterType="com.bright.pojo.User">
        insert into users values(#{id},#{name},#{gender})
    </insert>

    <update id="modify" parameterType="com.bright.pojo.User">
        update users set name=#{name},gender=#{gender} where id=#{id};
    </update>

    <delete id="delete" parameterType="com.bright.pojo.User">
        delete from users where id=#{id}
    </delete>
</mapper>

增删改查测试

查询数据,不需要提交事务

public class MyBatisTest {

    @Test
    public void test1() throws IOException {
        //获得核心配置文件
        InputStream resourceAsStream= Resources.getResourceAsStream("Mybatis-config.xml");
        //获得session工厂对象
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        //获得session回话对象
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //执行操作  参数:namespace+id
        List<User> userList = sqlSession.selectList("userMapper.selectAll");
        //打印数据
        System.out.println(userList);
        //释放资源
        sqlSession.close();
    }
}

增删改,与查询数据不同的是增删改需要提交事务

插入数据

User user=new User("1","张三,"男");
sqlSession.insert("userMapper.insert",user);
sqlSession.commit();//提交事务

更新数据

User user=new User("1","李四","男");
sqlSession.update("userMapper.modify",user);
sqlSession.commit();//提交事务

删除数据

User user=new User();
user.setI(1);
sqlSession.delete("userMapper.delete",user);
sqlSession.commit();//提交事务

详解

执行流程

img

String resource = "org/mybatis/builder/mybatis-config.xml"; 
//获得核心配置文件
InputStream inputStream = Resources.getResourceAsStream(resource); 
//获取工厂构造器
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); 
//获得session工厂对象
SqlSessionFactory factory = builder.build(inputStream);
//获取session会话对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//执行SQL Mapper
List<User> userList = sqlSession.selectList("userMapper.selectAll");
sqlSession.insert("userMapper.insert",user);
sqlSession.update("userMapper.modify",user);
sqlSession.delete("userMapper.delete",user);
//结束
sqlSession.close();

MybatisUtils

封装了Mybatis执行SQL Mapper前的流程

public class MybatisUtils {
    private static SqlSessionFactory sqlSessionFactory;
    static {
        try {
            String resource = "mybatis-config.xml";
            InputStream inputStream = null;
            inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public static SqlSession getSqlSession(){
        return sqlSessionFactory.openSession();
    }
}

两种查询

Mybatis 查询方法

方式一 .getMapper(UserMapper.class);

需要在Mapper.xml,使用全类名指定

<mapper namespace="com.bright.Dao.UserMapper"></mapper>
public class test {
    @Test
    public void testSql(){
        //获取sqlSession对象
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        //sqlSession.getMapper() 执行SQL
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        //调用实现类的getUserList方法
        List<User> userList = userMapper.getUserList();
        //遍历输出
        for (User user : userList) {
            System.out.println(user);
        }
        //关闭资源
        sqlSession.close();
    }
}

方式二 .selectList("namespace+id")

mapper.xml可以使用全类名也可以用类名,关键是要和代码中的统一

<mapper namespace="com.bright.Dao.UserMapper"></mapper>
sqlSession.selectList("com.bright.Dao.UserMapper.selectAll");
<mapper namespace="UserMapper"></mapper>
sqlSession.selectList("UserMapper.selectAll");
public class test {
    @Test
    public void testSql(){
        //获取sqlSession对象
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        List<User> userList = null;
        //com.bright.Dao.UserMapper是namespace所指内容,selectAll是下面的方法
        userList=sqlSession.selectList("UserMapper.selectAll");
        //遍历输出
        for (User user : userList) {
            System.out.println(user);
        }
        //关闭资源
        sqlSession.close();
    }
}

配置文件解析

Mybatis_config 文件内字段分析

Properties 配置

通过配置属性来引用配置文件

db.properties

#MySQL8以下将配置改为 com.mysql.jdbc.Driver
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/cms_hisoft?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false
username=root
password=123456

通过properties引入外部配置文件

<properties resource="db.properties"></properties>

<environments default="development">
    <environment id="development">
        <transactionManager type="JDBC"/>
        <dataSource type="POOLED">
            <property name="driver" value="${driver}"/>
            <property name="url" value="${url}"/>
            <property name="username" value="${username}"/>
            <property name="password" value="${password}"/>
        </dataSource>
    </environment>
</environments>

  • 可以直接引入外部文件
  • 可以在其中增加一些属性配置
  • 如果两个文件同时有同名字段,优先使用外部配置文件的
类型别名

类型别名(typeAliases)设置返回类型的别名,为了解决Mapper.xml中的使用全类名引用的情况

<mapper namespace="com.bright.Dao.UserMapper">
    <select id="selectAll" resultType="com.bright.pojo.User">
        select * from users
    </select>
</mapper>

通过指定一个类来给起短名,如果定义了别名则可以在resultType中直接引用

<typeAliases>
    <typeAlias type="com.bright.pojo.UserAll" alias="user"/>
</typeAliases>
<mapper namespace="com.bright.Dao.UserMapper">
    <select id="selectAll" resultType="user">
        select * from users
    </select>
</mapper>

还可以通过扫描package来批量指定JavaBean

在没有注解的情况下会使用JavaBean的小写名来当作别名

UserAn -> userAn 小驼峰可以正常使用

UserAn -> useran 全小写也可以正常使用

<typeAliases>
    <package name="com.bright.pojo"/>
</typeAliases>

在使用扫描package的情况下,可使用注解形式起别名

@Alias("user")
public class User{...}

问题

在使用别名时会导致Mybatis中DefaultVFS出现类名乱码

[org.apache.ibatis.io.DefaultVFS]-Reader entry: ����   4 Q
//采用*.*的方式
<select id="queryById" resultType="com.*.*.Book" parameterType="long">
		......
</select>

mybatis 的 DefaultVFS 日志乱码问题 - feshfans - 博客园 (cnblogs.com)

DefaultVFS 乱码问题官方回复

Setting(设置)

常用来设置Log4j日志

<settings>
    <setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
Mappers(映射器)

方式一:通过指定资源文件xml注册

<mappers>
    <mapper resource="com/bright/mapper/UserMapper.xml"/>
</mappers>

泛匹配扫描

<mappers>
    <mapper resource="com/bright/mapper/*Mapper.xml"/>
</mappers>

方式二:通过class指定映射

<mappers>
    <mapper class="com.bright.mapper.UserMapper"/>
</mappers>
  • 接口和他的Mapper配置文件必须同名
  • 接口和他的Mapper配置文件必须在同一个包下

方式三:使用package

<mappers>
    <package name="com.bright.mapper"/>
</mappers>

ResultMap

解决属性名和字段名不一致的问题,将数据表中的列与实体类中的属性对应上

UserMapper.xml

<resultMap id="" type="UserMap">
    <!--column对应数据表中字段,property对应javabean中属性-->
    <result column="id" property="id"/>		
    <result column="name" property="username"/>
    <result column="pwd" property="password"/>
</resultMap>
<!--指定resultMap名字为UserMap-->
<select id="getUserList" resultMap="UserMap">
    select * from user
</select>

Log4j 日志

Log4j是Apache的开源项目,Log4j可以控制日志输出的地方为控制台、GUI组件、文件等;可以设置输出日志的等级;只需要操作配置文件即可,无需改动代码。

Log4j.properties

#将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码
log4j.rootLogger=DEBUG,console,file

#控制台输出的相关设置
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%c]-%m%n

#文件输出的相关设置
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/sysrun.log
log4j.appender.file.MaxFileSize=10mb
log4j.appender.file.Threshold=DEBUG
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n

#日志输出级别
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG

在mybatis核心文件中配置log4j

mybatis-config.xml

<configuration>
    <!--引入配置-->
    <properties resource="db.properties"></properties>
    <!--设置日志-->
    <settings>
        <setting name="logImpl" value="LOG4J"/>
    </settings>
    <environments default="development">
    ....
    </environments>
</configuration>

在类中使用

//设置log为当前类
static Logger logger = Logger.getLogger(test.class);
@Test
public void testLog4j(){
  //设置log级别
    logger.info("info:进入了Log4j");
    logger.debug("debug:进入了Log4j");
    logger.error("error:进入了Log4j");
}

注解实现CRUD

之前提到的都是用Mapper映射xml实现的sql语句操作数据库,sql语句主要是写到了xml文件中,Mybatis还提供了注解实现sql语句操作数据库,更加简化了代码编写。但是如果是更复杂的sql,还是需要用xml来编写,注解的方式只适合一些简单的sql语句。

userMapper 接口

//查询所有用户
@Select("select * from user")
List<User> getUserList();

//根据id查询用户,利用@param注解传参
@Select("select * from user where id = #{id}")
User getUserById(@Param("id") int id);

//add user
@Insert("insert into user (id, name, pwd) values (#{id}, #{username}, #{password})")
int addUser(Map map);

//update user
@Update("update user set name=#{username},pwd=#{password} where id = #{id}")
int updateUser(User user);

//delete user
@Delete("delete from user where id = #{id}")
int deleteUser(@Param("id") int id);

关于@Param注解

  • 用于基本类型或String,引用类型不需要
  • 在sql中引用的就是这里@Param中的值

mybatis-config.xml 绑定接口(注意用注解绑定的就是接口)

<mappers>
    <mapper class="com.bright.mapper.UserMapper"></mapper>
</mappers>

测试

static Logger logger = Logger.getLogger(test.class);

@Test
public void testGetUserList(){
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);

    List<User> userList = mapper.getUserList();
    for (User user : userList) {
        logger.info("info:"+user);
    }
    sqlSession.close();
}

关于#{}与${}

#{}为预编译;${}为直接拼接,可能引发sql注入

Mybatis-动态SQL

动态SQL:利用Mybatis中自带的标签,根据不同的条件生成不同的SQL语句。

if
<select id="selectById" parameterType="Map" resultMap="Student">
    select * from user where
    <if test="id != null!">
        id = #{id}
    </if>
</select>
where
<select id="select" parameterType="Map" resultMap="Student">
    select * from user where
      <if test="id != null!">
          id = #{id}
      </if>
      <if test="id != null!">
          and name = #{name}
      </if>
</select>

上面的SQL语句在拼接的过程中,可能会出现以下情况造成SQL语句执行错误

select * from user where and name = xxx;

可以使用where标签来解决这个问题,where 元素只会在至少有一个子元素的条件返回 SQL 子句的情况下才去插入“WHERE”子句。而且,若语句的开头为“AND”或“OR”,where 元素也会将它们去除,将代码改为

<select id="select" parameterType="Map" resultMap="Student">
    select * from user
    <where>
        <if test="id != null!">
          	id = #{id}
      	</if>
  			<if test="name != null!">
        	  and name = #{name}
      	</if>
    </where>
</select>
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>

set 元素可以和ifchoose用于动态包含需要更新的列,忽略其它不更新的列;

set 元素会动态地在行首插入 SET 关键字,并会删掉额外的逗号

choose

类似于java中swtich case语句,满足when标签中的表达式,则执行该when中的sql语句,若都不满足则执行otherwise中的sql语句

<select id="StudentMapper" parameterType="Map" resultMap="Student">
  select * from user
  <where>
  	<choose>
      <when test="id != null!">
        id = #{id}
      </when>
      <when test="name != null!">
        and name = #{name}
      </when>
      <otherwise>
        and 1=1
      </otherwise>
    </choose>
  </where>
</select>

trim

mybatis的trim标签一般用于去除sql语句中多余的and关键字,逗号,或者给sql语句前拼接 “where“、“set“以及“values(“ 等前缀,或者添加“)“等后缀,可用于选择性插入、更新、删除或者条件查询等操作。

//拼接的前缀
prefix=""
//去除指定前缀
prefixOverrides="" 
//拼接后缀
suffix=""
//去除指定后缀
suffixOverrides=""

场景模拟:去除多余and

<select id="findActiveBlogLike" resultType="Blog">
  SELECT * FROM BLOG 
  WHERE 
  <if test="state != null">
    state = #{state}
  </if> 
  <if test="title != null">
    AND title like #{title}
  </if>
  <if test="author != null and author.name != null">
    AND author_name like #{author.name}
  </if>
</select>

以上动态SQL运行后,可能会出现以下两个问题

问题一SQL

SELECT * FROM BLOG 
WHERE

问题二SQL

SELECT * FROM BLOG
WHERE 
AND title like ‘someTitle’

解决方法

使用where解决

<select id="findActiveBlogLike"
     resultType="Blog">
  SELECT * FROM BLOG 
  <where> 
    <if test="state != null">
         state = #{state}
    </if> 
    <if test="title != null">
        AND title like #{title}
    </if>
    <if test="author != null and author.name != null">
        AND author_name like #{author.name}
    </if>
  </where>
</select>

使用trim解决

<trim prefix="WHERE" prefixOverrides="AND">
	<if test="state != null">
	  state = #{state}
	</if> 
	<if test="title != null">
	  AND title like #{title}
	</if>
	<if test="author != null and author.name != null">
	  AND author_name like #{author.name}
	</if>
</trim>

场景模拟:update去除多余 ,

<insert id="insert" parameterType="com.bright.user">
	insert into user
	(
		<if test="name!=null" >
			name,
		</if>
		<if test="gender!=null" >
			gender
		</if>
	)
	values(
		<if test="name!=null" >
			name,
		</if>
		<if test="gender!=null" >
			gender
		</if>
	)
</insert>

问题SQL

Insert into user(name,) values(name,);

解决方法

<insert id="insert" parameterType="com.bright.user">
	insert into user
	<trim prefix="(" suffix=")" suffixOverrides=",">
		<if test="name!=null" >
			name,
		</if>
		<if test="gender!=null" >
			gender
		</if>
	</trim>
	<trim prefix="values(" suffix=")" suffixOverrides=",">
		<if test="name!=null" >
			name,
		</if>
		<if test="gender!=null" >
			gender
		</if>
	</trim>
</insert>

参考

(4条消息) Mybatis快速入门_kopoo的博客-CSDN博客_mybatis坐标

Java之Mybatis - CoLoo - 博客园 (cnblogs.com)

(4条消息) mybatis trim标签的使用_wt_better的博客-CSDN博客_mybatis trim

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
课程简介这是一门使用Java语言,SpringBoot框架,从0开发一个RESTful API应用,接近企业级的项目(我的云音乐),课程包含了基础内容,高级内容,项目封装,项目重构等知识,99%代码为手写;因为这是项目课程;所以不会深入到源码讲解某个知识点,以及原理,但会粗略的讲解下基础原理;主要是讲解如何使用系统功能,流行的第三方框架,第三方服务,完成接近企业级项目,目的是让大家,学到真正的企业级项目开发技术。适用人群刚刚毕业的学生想提高职场竞争力想学从零开发SpringBoot项目想提升SpringBoot项目开发技术想学习SpringBoot项目架构技术想学习企业级项目开发技术就是想学习SpringBoot开发能学到什么从0开发一个类似企业级项目学会能做出市面上90%通用API快速增加1到2年实际开发经验刚毕业学完后能找到满意的工作已经工作学完后最高涨薪30%课程信息全课程目前是82章,155小时,每节视频都经过精心剪辑。在线学习分辨率最高1080P课程知识点1~11章:学习方法,项目架构,编码规范,Postman使用方法,Git和Github版本控制12~16章:搭建开发环境,快速入门SpringBoot框架17~20章:快速入门MySQL数据库21~30章:MyBatis,登录注册,找回密码,发送短信,发送邮件,企业级接口配置31~41章:实现歌单,歌单标签,音乐,列表分页,视频,评论,好友功能42~48章:阿里云OSS,话题,MyBatis-plus,应用监控49~53章:Redis使用,集成Redis,SpringCache,HTTP缓存54~58章:Elasticsearch使用,集成Elasticsearch,使用ES搜索59~61章:商城,集成支付宝SDK,支付宝支付62~64章:常用哈希和加密算法,接口加密和签名65~67章:实时挤掉用户,企业级项目测试环境,企业级接口文档68~69章:SpringBoot全站HTTPS,自签证书,申请免费证书70~73章:云MySQL数据库,云Redis数据库使用,轻量级应用部署环境,域名解析74~80章:Docker使用,生产级Kubernetes集群,域名解析,集群全站HTTPS81~82章:增强和重构项目,课程总结,后续学习计划

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ABright.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值