Mybatis学习笔记

Mybaits3

写在文章前面

根据B站大佬狂神说的视频学习的Mybatis,然后整理的笔记。

1、简介

1、1 什么是Mybatis

  • 是一款优秀的持久层框架。
  • 是一个开源、轻量级的,JDBC的替代方案。
  • 支持自定义 SQL、存储过程以及高级映射。
  • 免除了几乎所有的JDBC代码以及设置参数和获取结果集的工作。
  • 可以通过简单的XML或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
  • 内部封装了JDBC,简化了加载驱动、创建连接、创建 statement 等繁杂的过程,开发者只需要关注 SQL 语句本身。
  • 是一个半自动化的ORM框架 (Object Relationship Mapping) —>对象关系映射

1、2 MyBatis历史

  • MyBatis本是apache的一个开源项目iBatis,2002 年由 Clinton Begin 发布。
  • 2010 年从 Apache 迁移到 Google,并改名为 MyBatis。
  • 2013 年又迁移到了 Github。

1、3 MyBatis优点

  • 是免费且开源的。
  • 与 JDBC 相比,减少了 50% 以上的代码量。
  • 简单易学:本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件。
  • 灵活:不会对应用程序或者数据库的现有设计强加任何影响。 sql写在xml里,便于统一管理和优化。通过sql语句可以满足操作数据库的所有需求。
  • 提供 XML 标签,支持编写动态 SQL 语句。
  • 提供映射标签,支持对象与数据库的 ORM 字段关系映射。
  • 使用的人多!公司需要!随大流!

1、4 MyBatis缺点

  • 编写 SQL 语句工作量较大,对开发人员编写 SQL 语句的功底有一定要求。
  • SQL 语句依赖于数据库,导致数据库移植性差,不能随意更换数据库。

2、Mybatis第一个程序

2、1 创建数据库、表

CREATE DATABASE `mybatis`;
USE `mybatis`;

CREATE TABLE `user`(
  `id` INT 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')

2、2 导入mybatis、mysql、junit依赖

<!-- mybatis -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.5</version>
</dependency>
<!--mysql 驱动-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.29</version>
</dependency>
<!-- junit测试 -->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
</dependency>

2、3 编写配置文件,文件位置一般放在resources目录中

  1. 数据库配置文件,db.properties
Driver=com.mysql.jdbc.Driver
Url=jdbc:mysql://localhost:3306/mybatis?useSSL=false&userUnicode=true&characterEncoding=utf-8
UserName=root
PassWord=123456
  1. Mybatis核心配置文件,mybaits-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>
    <!-- 加载properties文件 -->
    <properties resource="db.properties"></properties>
    
	<!-- 设置别名,使用的时候直接用别名就行 -->
    <typeAliases>
        <!-- 方式一 -->
        <typeAlias type="com.liushq.pojo.User" alias="user" />

        <!-- 方式二  给指定包下所有实体设置别名,默认别名为类名的首字目小写形式,例如:User类的别名为user-->
        <package name="com.liushq.pojo" />
    </typeAliases>
    
    <!-- 配置mybatis运行环境 -->
    <environments default="development">
        <environment id="development">
            <!-- 使用JDBC的事务管理 -->
            <transactionManager type="JDBC"></transactionManager>
            <dataSource type="POOLED">
                <!-- MySQL数据库驱动 -->
                <property name="driver" value="${Driver}"/>
                <!-- 连接数据库的URL -->
                <property name="url" value="${Url}" />
                <property name="username" value="${UserName}" />
                <property name="password" value="${PassWord}" />
            </dataSource>
        </environment>
    </environments>
    <!-- 将mapper文件加入到配置文件中 -->
    <mappers>
        <mapper resource="com/liushq/mapper/UserMapper.xml" />
    </mappers>
</configuration>

2、4 创建项目

  1. 创建一个普通maven项目mybatis-study,并删除src文件夹。
    项目目录结构
    完整的pom.xml文件内容
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.liushq</groupId>
    <artifactId>mybatis-study</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.5</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.29</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>

    <build>
        <!--为防止mapper.xml文件无法输出,需进行如下配置-->
        <resources>
            <!-- src/main/java文件夹下,可以存放 *.properties、*.xml 文件,不用过滤 -->
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
        </resources>
    </build>
</project>
  1. 在项目下新建模块mybatis-01,并完善项目结构及配置。
    项目目录结构
  2. 在utils包下,编写MyBatis工具类,MyBaitsUtils
package com.liushq.utils;

public class MyBaitsUtils {
    private static SqlSessionFactory sqlSessionFactory;
    static {
        try {
            InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static SqlSession getSqlSession() {
        return sqlSessionFactory.openSession();
    }
}
  1. 在pojo包下,编写User实体类
package com.liushq.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;
    }
}
  1. 在mapper包下,编写UserMapper接口
package com.liushq.mapper;

public interface UserMapper {
    List<User> getUserList();

    List<User> getUserListByMap(Map<String,Object> map);

    User getUserInfo(int id);

    int addUser(User user);

    int updateUser(User user);

    int deleteUser(int id);
}
  1. 在resourses下,新建mapper文件夹,并在该文件夹下编写UserMapper.xml配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.liushq.mapper.UserMapper">
    <select id="getUserList" resultType="com.liushq.pojo.User">
        select * from user;
    </select>

    <select id="getUserListByMap" parameterType="map" resultType="com.liushq.pojo.User">
        select * from mybatis.user where name like '%${name}%';
    </select>

    <select id="getUserInfo" parameterType="int" resultType="com.liushq.pojo.User">
        select * from mybatis.user where id=#{id};
    </select>

    <insert id="addUser" parameterType="com.liushq.pojo.User">
        insert into mybatis.user(id,name,pwd) values(#{id},#{name},#{pwd})
    </insert>

    <update id="updateUser" parameterType="com.liushq.pojo.User">
        update mybatis.user set name=#{name},pwd=#{pwd} where id=#{id}
    </update>

    <delete id="deleteUser" parameterType="int">
        delete from mybatis.user where id=#{id}
    </delete>
</mapper>
  1. 在service包下,编写UserService接口及实现类
package com.liushq.service;

public interface UserService {
    List<User> getUserList();

    List<User> getUserListByMap(String name);

    User getUserInfo(int id);

    int addUser(User user);

    int updateUser(User user);

    int deleteUser(int id);
}
package com.liushq.service.Impl;

public class UserServiceImpl implements UserService {
    private SqlSession sqlSession = MyBaitsUtils.getSqlSession();
    private UserMapper mapper = sqlSession.getMapper(UserMapper.class);

    @Override
    public List<User> getUserList() {
        List<User> list=mapper.getUserList();
        sqlSession.close();
        return list;
    }

    @Override
    public List<User> getUserListByMap(String name) {
        Map<String,Object> map=new HashMap<>();
        map.put("name",name);
        List<User> list=mapper.getUserListByMap(map);
        sqlSession.close();
        return list;
    }

    @Override
    public User getUserInfo(int id) {
        User user=mapper.getUserInfo(id);
        sqlSession.close();
        return user;
    }

    @Override
    public int addUser(User user) {
        int res=mapper.addUser(user);
        sqlSession.commit();
        sqlSession.close();
        return res;
    }

    @Override
    public int updateUser(User user) {
        int res=mapper.updateUser(user);
        sqlSession.commit();
        sqlSession.close();
        return res;
    }

    @Override
    public int deleteUser(int id) {
        int res=mapper.deleteUser(id);
        sqlSession.commit();
        sqlSession.close();
        return res;
    }
}
  1. 编写测试类
package com.liushq.service;

import com.alibaba.fastjson.JSONObject;

public class UserServiceTest {
   private UserService service=new UserServiceImpl();

    @Test
    public void getUserList(){
        List<User> userList = service.getUserList();
        for (User user : userList) {
            System.out.println(JSONObject.toJSONString(user));
        }
    }

    @Test
    public void getUserListByMap(){
        List<User> userList = service.getUserListByMap("i");
        for (User user : userList) {
            System.out.println(user);
        }
    }

    @Test
    public void getUserInfo(){
        User user = service.getUserInfo(1);
        System.out.println(user);
    }

    @Test
    public void addUser(){
        User user=new User(5,"xiaoma1","123123");
        int res= service.addUser(user);
        System.out.println(res>0?"添加成功":"添加失败");
    }

    @Test
    public void updateUser(){
        User user=new User(5,"xiaoma1111","123123111");
        int res= service.updateUser(user);
        System.out.println(res>0?"修改成功":"修改失败");
    }

    @Test
    public void deleteUser(){
        int res= service.deleteUser(4);
        System.out.println(res>0?"删除成功":"删除失败");
    }
}
  1. json处理,需要在mybatis-01的pom.xml中添加json依赖,这里用的是com.alibaba.fastjson
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.83</version>
    <scope>test</scope>
</dependency>
  1. 测试结果,getUserList方法
    测试结果
  2. 完整项目结构图
    完整项目结构图

3、XML映射器(Mapper.xml)及CRUD操作

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.liushq.mapper.UserMapper">
</mapper>
  • namespace:命名空间
    • 绑定DAO接口,必须跟某个接口同名。
    • 相当于通过xml配置文件,实现了mapper接口。
  • select:查询标签,对应sql中的select查询语句。
    • id:对应mapp接口中的接口名称。
    • parameterType:接口的参数类型。
    • resultType:接口的返回结果类型。
    • resultMap:返回外部 resultMap 的命名引用。
<select id="getUserInfo" parameterType="int" resultType="com.liushq.pojo.User">
    select * from mybatis.user where id=#{id};
</select>
  • insert:插入数据标签,对应sql中的insert语句。
<insert id="addUser" parameterType="com.liushq.pojo.User">
   insert into mybatis.user(id,name,pwd) values(#{id},#{name},#{pwd})
</insert>
  • update:更新数据标签,对应sql中的update语句。
<update id="updateUser" parameterType="com.liushq.pojo.User">
    update mybatis.user set name=#{name},pwd=#{pwd} where id=#{id}
</update>
  • delete:删除标签,对应sql中的delete语句。
<delete id="deleteUser" parameterType="int">
    delete from mybatis.user where id=#{id}
</delete>

注意点:增、删、改操作需要提交事务!

4、Mybatis-config.xml配置解析

mybatis中可以配置的内容如下:

<!-- 需要严格注意元素节点的顺序!顺序不对会报错 -->
configuration(配置)
	properties(属性)
	settings(设置)
	typeAliases(类型别名)
	typeHandlers(类型处理器)     <!--用的少,自行看官网说明-->
	objectFactory(对象工厂)      <!--用的少,自行看官网说明-->
	plugins(插件)                <!--用的少,自行看官网说明-->
	environments(环境配置)
		environment(环境变量)
		transactionManager(事务管理器)
		dataSource(数据源)
	databaseIdProvider(数据库厂商标识)
	mappers(映射器)

4、1 properties(属性)

这些属性可以在外部进行配置,并可以进行动态替换。你既可以在典型的 Java 属性文件中配置这些属性,也可以在 properties 元素的子元素中设置。例如:

<!-- 这是一种写法 -->
<properties resource="db.properties"></properties>

<!-- 还可以在标签引用内,再添加属性 -->
<properties resource="db.properties">
  <property name="UserName" value="root"/>
  <property name="PassWord" value="123456"/>
</properties>

如果一个属性在不只一个地方进行了配置,比如:UserName跟PassWord,在db.properties配置文件里有,在properties标签中也有,那么,MyBatis 将按照下面的顺序来加载:

  • 首先读取在 properties 标签元素体内指定的属性。
  • 然后根据 properties 元素中的 resource 属性读取引用的配置文件,并覆盖之前读取过的同名属性。
  • 最后读取作为方法参数传递的属性,并覆盖之前读取过的同名属性。
  • 意思就是在properties标签中设置的属性,会被在db.properties配置文件中的同名属性所覆盖。

设置好的属性后,就可以在整个配置文件中用来替换需要动态配置的属性值。例如:

<dataSource type="POOLED">
   <!-- MySQL数据库驱动 -->
   <property name="driver" value="${Driver}"/>
   <!-- 连接数据库的URL -->
   <property name="url" value="${Url}" />
   <property name="username" value="${UserName}" />
   <property name="password" value="${PassWord}" />
</dataSource>

4、2 settings(设置)

这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为。 下表描述了设置中各项设置的含义、默认值等。这里只罗列一些常用的、比较重要的,其他的可以自行看官网文档。

设置名描述有效值默认值
cacheEnabled全局性地开启或关闭所有映射器配置文件中已配置的任何缓存。true或falsetrue
lazyLoadingEnabled延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态。true或falsefalse
mapUnderscoreToCamelCase是否开启驼峰命名自动映射,即从经典数据库列名 A_COLUMN 映射到经典 Java 属性名 aColumn。true或falsefalse
logImpl指定 MyBatis 所用日志的具体实现,未指定时将自动查找。SLF4J、LOG4J(3.5.9 起废弃)、LOG4J2、 JDK_LOGGING、COMMONS_LOGGING、STDOUT_LOGGING、NO_LOGGING未设置

一个配置完整的 settings 元素的示例如下:

<settings>
  <setting name="cacheEnabled" value="true"/>
  <setting name="lazyLoadingEnabled" value="true"/>
  <setting name="aggressiveLazyLoading" value="true"/>
  <setting name="multipleResultSetsEnabled" value="true"/>
  <setting name="useColumnLabel" value="true"/>
  <setting name="useGeneratedKeys" value="false"/>
  <setting name="autoMappingBehavior" value="PARTIAL"/>
  <setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
  <setting name="defaultExecutorType" value="SIMPLE"/>
  <setting name="defaultStatementTimeout" value="25"/>
  <setting name="defaultFetchSize" value="100"/>
  <setting name="safeRowBoundsEnabled" value="false"/>
  <setting name="safeResultHandlerEnabled" value="true"/>
  <setting name="mapUnderscoreToCamelCase" value="false"/>
  <setting name="localCacheScope" value="SESSION"/>
  <setting name="jdbcTypeForNull" value="OTHER"/>
  <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
  <setting name="defaultScriptingLanguage" value="org.apache.ibatis.scripting.xmltags.XMLLanguageDriver"/>
  <setting name="defaultEnumTypeHandler" value="org.apache.ibatis.type.EnumTypeHandler"/>
  <setting name="callSettersOnNulls" value="false"/>
  <setting name="returnInstanceForEmptyRow" value="false"/>
  <setting name="logPrefix" value="exampleLogPreFix_"/>
  <setting name="logImpl" value="SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING"/>
  <setting name="proxyFactory" value="CGLIB | JAVASSIST"/>
  <setting name="vfsImpl" value="org.mybatis.example.YourselfVfsImpl"/>
  <setting name="useActualParamName" value="true"/>
  <setting name="configurationFactory" value="org.mybatis.example.ConfigurationFactory"/>
</settings>

4、3 类型别名(typeAliases)

类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写。例如:

<!-- 方式一:直接配置类名的别名 -->
<typeAliases>
    <typeAlias type="com.liushq.pojo.User" alias="User" />
</typeAliases>

<!-- 方式二:指定一个包名,MyBatis会在包名下搜索需要的实体,别名默认为类名的首字母小写形式 -->
<typeAliases>
  <package name=""com.liushq.pojo"/>
</typeAliases>

在UserMapper.xml中,没设置别名前

<select id="getUserList" resultType="com.liushq.pojo.User">
    select * from user;
</select>

设置别名后,resultType中的类名可以直接使用别名

<select id="getUserList" resultType="User">
    select * from user;
</select>

官网中有详细的别名介绍,可以自行查看。

4、4 环境配置(environments)

MyBatis 可以配置成适应多种环境,这种机制有助于将 SQL 映射应用于多种数据库之中,尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。

<!-- 配置mybatis运行环境 在default中指定使用哪个环境,environment 可以有多个-->
<environments default="development">
	<!-- development开发环境-->
    <environment id="development">
        <!-- 使用JDBC的事务管理 -->
        <transactionManager type="JDBC"></transactionManager>
        <!-- 数据源 POOLED 利用“池”的概念将 JDBC 连接对象组织起来 -->
        <dataSource type="POOLED">
            <!-- MySQL数据库驱动 -->
            <property name="driver" value="${Driver}"/>
            <!-- 连接数据库的URL -->
            <property name="url" value="${Url}" />
            <property name="username" value="${UserName}" />
            <property name="password" value="${PassWord}" />
        </dataSource>
    </environment>
    
    <!-- test测试环境-->
    <environment id="test">
    	...
    </environment>
</environments>
  • environment:配置具体环境,可以有多个,id必须唯一。
  • transactionManager:事务管理器,有JDBC、MANAGED 2种可选。
    • JDBC:这个配置直接使用了 JDBC 的提交和回滚功能,它依赖从数据源获得的连接来管理事务作用域。
    • MANAGED:这个配置几乎没做什么。它从不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如 JEE 应用服务器的上下文)。 默认情况下它会关闭连接。
  • dataSource:数据源,有UNPOOLED、POOLED、JNDI 3种可选。
    • UNPOOLED:这个数据源的实现会每次请求时打开和关闭连接。虽然有点慢,但对那些数据库连接可用性要求不高的简单应用程序来说,是一个很好的选择。
    • POOLED:这种数据源的实现利用“池”的概念将 JDBC 连接对象组织起来,避免了创建新的连接实例时所必需的初始化和认证时间。 这种处理方式很流行,能使并发 Web 应用快速响应请求。
    • JNDI:这个数据源实现是为了能在如 EJB 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个 JNDI 上下文的数据源引用。

4、5 映射器(mappers)

既然 MyBatis 的行为已经由上述元素配置完了,我们现在就要来定义 SQL 映射语句了。 但首先,我们需要告诉 MyBatis 到哪里去找到这些语句。 在自动查找资源方面,Java 并没有提供一个很好的解决方案,所以最好的办法是直接告诉 MyBatis 到哪里去找映射文件。

<mappers>
  <!-- 方式一:使用相对于类路径的资源引用 -->
  <mapper resource="mapper/UserMapper.xml"/>
  <!-- 方式二:使用相对于类路径的资源引用 -->
  <mapper class="com.liushq.mapper.UserMapper"/>
  <!-- 将包内的映射器接口全部注册为映射器,接口和它的Mapper配置文件必须同名,且位于同一目录下 -->
  <package name="com.liushq.mapper"/>
</mappers>

5、ResultMap用法

更新中。。。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值