Mybatis-基础详解

1 Mybatis简介

  1. MyBatis是一款优秀的持久层框架(Dao)
  2. 它支持自定义 SQL、存储过程以及高级映射。
  3. MyBatis免除了几乎所有的 JDBC代码、设置参数和获取结果集的工作。
  4. MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java pojo(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
  5. 官方文档是最好的学习资料!Mybatis官方文档

2 快速入门

2.1 数据导入

CREATE DATABASE /*!32312 IF NOT EXISTS*/`mybatis_db` /*!40100 DEFAULT CHARACTER SET utf8 */;
USE `mybatis_db`;
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(50) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  `address` varchar(50) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
insert  into `user`(`id`,`username`,`age`,`address`) values (1,'UZI',19,'上海'),(2,'PDD',25,'上海');

2.2 导入依赖

<dependencies>
        <!--mybatis依赖-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.4</version>
        </dependency>
        <!--mysql驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.15</version>
        </dependency>
        <!--junit-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <!--log4j日志-->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
    </dependencies>

在build中配置resources,来防止我们资源导出失败的问题

<!--在build中配置resources来防止我们资源导出失败的问题-->
<build>
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <includes>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
        </resource>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
        </resource>
    </resources>
</build>

2.3 编写核心配置

在资源目录下创建: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>
    <properties resource="jdbc.properties"/>
    <settings>
        <!--开启自动驼峰命名映射-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
    <typeAliases>
        <package name="com.cycyong.pojo"></package>
    </typeAliases>
    <environments default="development">
        <environment id="development">
            <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>
    <!-- 定义mapper接口所在的包。要求xml文件存放的路径和mapper接口的包名要对应 -->
    <mappers>
        <package name="com.cycyong.mapper"/>
    </mappers>
</configuration>

jdbc.properties

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis_db?&useSSL=false&serverTimezone=UTC&characterEncoding=utf-8
jdbc.username=root
jdbc.password=root

2.4 定义接口及对应的xml映射文件

com.cycyong.mapper.UserMapper.java

public interface UserMapper {
    List<User> findAll();
}

com.cycyong.mapper.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="com.cycyong.mapper.UserMapper">

    <select id="findAll" resultType="com.cycyong.pojo.User">
      select * from user
    </select>
</mapper>

由于配置了扫描路径,所以xml文件也可放在mapper下

2.5 编写测试类

获取SqlSession,通过SqlSession获取UserMapper调用对应的方法

public static void main(String[] args) throws IOException {
    @Test
    public void test01() throws IOException {
        //定义mybatis配置文件的路径
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //获取Sqlsession对象
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //获取UserMapper实现类对象
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        //调用方法测试
        List<User> userList = userMapper.findAll();
        for (User user:userList) {
            System.out.println(user);
        }
        //释放资源
        sqlSession.close();
    }
}

2.6 测试

成功查询出结果!

在这里插入图片描述

3 参数获取

3.1 一个参数

3.1.1 基本参数

  1. 我们可以使用#{}直接来取值,写任意名字都可以获取到参数。但是一般用方法的参数名来取。

  2. parameterType可写可不写,mybatis会自动推断其类型

  3. #{}必须和实体类对应,大小写必须一样

例如:
接口中方法定义如下:

User findById(Integer id);

xml中内容如下:

<select id="findById" resultType="com.cycyong.pojo.User"> 
	select * from user where id = #{id}
</select>

3.1.2 pojo

  1. 我们可以使用POJO中的属性名来获取对应的值。
  2. #{}放pojo的属性名即可

例如:
接口中方法定义如下:

User findByUser(User user);

xml中内容如下:

<select id="findByUser" resultType="com.cycyong.pojo.User">
select * from user where id = #{id} and username = #{username} and age = #{age} and address = #{address}
</select>

3.1.3 Map

我们可以使用map中的key来获取对应的值。

例如:
接口中方法定义如下:

User findByMap(Map map);

xml中内容如下:

<select id="findByMap" resultType="com.cycyong.pojo.User">
    select * from user where id = #{id} and username = #{username} and age = #{age} and address = #{address}
</select>

方法调用:

Map map = new HashMap();
map.put("id",2);
map.put("username","PDD");
map.put("age",25);
map.put("address","上海");
userMapper.findByMap(map);

3.2 多个参数

Mybatis会把多个参数放入一个Map集合中,默认的key是argx和paramx这种格式。

例如:
接口中方法定义如下:

User findByCondition(Integer id,String username);

我们虽然可以使用对应的默认key来获取值,但是这种方式可读性不好。我们一般在方法参数前使用@Param来设置参数名。则xml以@Param对应的参数名对应。

例如:
接口中方法定义:

User findByCondition(@Param("id") Integer id,@Param("userName") String username);

最终map中的键值对如下:

{id=2, param1=2, userName=PDD, param2=PDD}

所以我们就可以使用如下方式来获取参数

<select id="findByCondition" resultType="com.cycyong.pojo.User">
     select * from user where id = #{id} and username = #{userName}
</select>

3.3 总结

建议如果只有一个参数的时候不用做什么特殊处理。如果是有多个参数的情况下一定要加上@Param来设置参数名。加上@Param之后,参数是按照注解的名字和xml对应。

最重要的是一定要参数(接口参数、pojo的属性)和xml中的#{}对应!

4 核心类

4.1 SqlSessionFactory

SqlSessionFactory是一个SqlSession的工厂类,用来获取SqlSession对象。

成员方法如下:

SqlSession openSession();
//获取SqlSession对象,传入的参数代表创建的SqlSession是否自动提交
SqlSession openSession(boolean autoCommit);

4.2 SqlSession

SqlSession 提供了在数据库执行 SQL 命令所需的所有方法 。它还提供了事务的相关操作。

  • 增删改需要提交事务
  • 查不需要提交事务

成员方法如下:

T getMapper(Class<T> type);//获取mapper对象
void commit();//提交事务
void rollback();//回滚事务
void close();//释放资源

5 实现CRUD

5.1 增加

①接口中增加相关方法

void insertUser(User user);

②映射文件UserMapper.xml增加响应的标签

    <insert id="insertUser">
        insert into user values(null,#{username},#{age},#{address})
    </insert>

注意:要记得提交事务。

SqlSession sqlSession = sqlSessionFactory.openSession(true);

或者

sqlSession.commit();

5.2 删除

①接口中增加相关方法

void deleteById(Integer id);

②映射文件UserMapper.xml增加响应的标签

<delete id="deleteById">
    delete from user where id = #{id}
</delete>

注意:要记得提交事务。

5.3 查找

①接口中增加相关方法

User findById(Integer id);

②映射文件UserMapper.xml增加响应的标签

<select id="findById" resultType="com.cycyong.pojo.User">
  	select * from user where id = #{id}
</select>

5.4 修改

①接口中增加相关方法

void updateUser(User user);

②映射文件UserMapper.xml增加响应的标签

<update id="updateUser">
   	UPDATE USER SET age = #{age} , username = #{username},address = #{address} WHERE id = #{id}
</update>

注意:要记得提交事务。

6 配置文件详解

  • mybatis-config.xml
  • mybatis的配置文件包含了会深深影响Mybatis行为的设置和属性信息
configuration(配置)
properties(属性)
settings(设置)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境配置)
environment(环境变量)
transactionManager(事务管理器)
dataSource(数据源)
databaseIdProvider(数据库厂商标识)
mappers(映射器)

6.1 环境配置

mybatis可以配置成适应多种环境

不过要记住:尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。

学会使用配置多套运行环境!

mybatis默认的事务管理器就是jdbc,连接池:POOLED

6.2 属性详情

6.2.1 properties

可以使用properties读取properties配置文件。使用其中的resource属性来设置配置文件的路径。

​ 然后使用${key}来获取配置文件中的值

例如:

在resources目录下有jdbc.properties文件,内容如下:

jdbc.driver =com.mysql.cj.jdbc.Driver
jdbc.url =jdbc:mysql://localhost:3306/mybatis_db?&useSSL=false&serverTimezone=UTC&characterEncoding=utf-8
jdbc.username =root
jdbc.password=jianjian123456

在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>
    <!--设置配置文件所在的路径-->
    <properties resource="jdbc.properties"></properties>
    <environments default="development">
        <environment id="development">
            <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>
</configuration>

6.2.2 settings

可以使用该标签来设置进行一些设置

例如:
数据库 ------> java实体类

A_COLUMN ------> aColumn

 <settings>
     <!--开启自动驼峰命名映射-->
     <setting name="mapUnderscoreToCamelCase" value="true"/>
 </settings>

具体的设置参考:setting配置详情

6.2.3 typeAliases

可以用来设置给全类名设置别名,简化书写。一般设置一个包下的类全部具有默认别名。默认别名是类目首字母小写。例如:com.cycyong.pojo.User别名为user

<typeAliases>
     <package name="com.cycyong.mapper"></package>
 </typeAliases>

6.2.4 environments

配置数据库相关的环境,例如事物管理器,连接池相关参数等。

    <!--设置默认环境-->
<environments default="development">
    <!--设置该环境的唯一标识-->
    <environment id="development">
        <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>

6.2.5 mappers

该标签的作用是加载映射的,加载方式有如下几种(主要使用第四种):
④将包内的映射器接口实现全部注册为映射器,例如:

<!-- 定义mapper接口所在的包。要求xml文件存放的路径和mapper接口的包名要对应 -->
<mappers>
    <package name="com.cycyong.mapper"/>
</mappers>

其他几种不常用!

7 打印日志

①log4j配置 在resources目录下创建log4j.properties文件,内容如下:

### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### direct messages to file mylog.log ###
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=c:/mylog.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### set log levels - for more verbose logging change 'info' to 'debug' ###

log4j.rootLogger=debug, stdout

②引入依赖

 <dependency>
     <groupId>log4j</groupId>
     <artifactId>log4j</artifactId>
     <version>1.2.17</version>
 </dependency>

8 #{}和${}的区别

如果使用#{}.他是预编译的sql可以防止SQL注入攻击
​如果使用${}他是直接把参数值拿来进行拼接,这样会有SQL注入的危险

如果使用的是#{}来获取参数值日志如下:

Preparing: select * from user where id = ? and username = ? and age = ? and address = ? 
Parameters: 2(Integer), 快乐风男(String), 29(Integer), 北京(String)

如果使用${}来获取参数值日志如下:

Preparing: select * from user where id = 2 and username = 快乐风男 and age = 29 and address = 北京 

9 动态SQL

在实际开发中的SQL语句没有之前的这么简单,很多时候需要根据传入的参数情况动态的生成SQL语句。Mybatis提供了动态SQL相关的标签去使用。

9.1 if

可以使用if标签进行判断,条件成立才会把if标签中的内容拼接进sql语句中。
例如:

<select id="findByCondition" resultType="com.cycyong.pojo.User">
     select * from user
     where  id = #{id}
    <if test="username!=null">
       and username = #{username}
    </if>
</select>

如果参数username为null则执行的sql为:
select * from user where id = ?

如果参数username不为null则执行的sql为:
select * from user where id = ? and username = ?

注意:在test属性中表示参数的时候不需要写#{},写了会出问题。

9.2 trim(where set)

① where
可以使用where标签动态的拼接where并且去除前缀的and或者or。

例如:

<select id="findByCondition" resultType="com.cycyong.pojo.User">
    select * from user
    <where>
        <if test="id!=null">
            id = #{id}
        </if>
        <if test="username!=null">
            and username = #{username}
        </if>
    </where>
</select>

如果id和username都为null,则执行的sql为:
select * from user

如果id为null,username不为null,则执行的sql为:
select * from user where username = ?

②set
可以使用set标签动态的拼接set并且去除后缀的逗号。

例如:

<update id="updateUser">
    UPDATE USER
    <set>
        <if test="username!=null">
            username = #{username},
        </if>
        <if test="age!=null">
            age = #{age},
        </if>
        <if test="address!=null">
            address = #{address},
        </if>
    </set>
    where id = #{id}
</update>

如果调用方法时传入的User对象的id为2,username不为null,其他属性都为null则最终执行的sql为:
update user set username = ? where id = ?

9.3 foreach

可以使用foreach标签遍历集合或者数组类型的参数,获取其中的元素拿来动态的拼接SQL语句。

例如:
方法定义如下 :

List<User> findByIds(@Param("ids") Integer[] ids);

如果期望动态的根据实际传入的数组的长度拼接SQL语句。例如传入长度为4个数组最终执行的SQL为:

select * from User WHERE id in( ? , ? , ? , ?, ? ) 

则在xml映射文件中可以使用以下写法:

<select id="findByIds" resultType="com.cycyong.pojo.User">
    select * from User
    <where>
        <foreach collection="ids" open="id in(" close=")" item="id" separator=",">
            #{id}
        </foreach>
    </where>
</select>

collection:表示要遍历的参数。

open:表示遍历开始时拼接的语句

item:表示给当前遍历到的元素的取的名字

separator:表示每遍历完一次拼接的分隔符

close:表示最后一次遍历完拼接的语句

注意:如果方法参数是数组类型,默认的参数名是array,如果方法参数是list集合默认的参数名是list。建议遇到数组或者集合类型的参数统一使用@Param注解进行命名。

9.4 choose、when、otherwise

当我们不想使用所有的条件,而只是想从多个条件中选择一个使用时。可以使用choose系列标签。类似于java中的switch。

例如:
接口中方法定义如下:

List<User> selectChose(User user);

期望:

  1. 如果user对象的id不为空时就通过id查询
  2. 如果id为null,username不为null就通过username查询
  3. 如果id和username都会null就查询id为3的用户

xml映射文件如下:

<select id="selectChose" resultType="com.cycyong.pojo.User">
     select * from user
     <where>
         <choose>
             <when test="id!=null">
                 id = #{id}
             </when>
             <when test="username!=null">
                 username = #{username}
             </when>
             <otherwise>
                 id = 3
             </otherwise>
         </choose>
     </where>
 </select>

小技巧:

  • choose类似于java中的switch

  • when类似于java中的case

  • otherwise类似于java中的dufault

一个choose标签中最多只会有一个when中的判断成立。从上到下去进行判断。如果成立了就把标签体的内容拼接到sql中,并且不会进行其它when的判断和拼接。如果所有的when都不成立则拼接otherwise中的语句。

10 SQL片段抽取

我们在xml映射文件中编写SQL语句的时候可能会遇到重复的SQL片段。这种SQL片段我们可以使用sql标签来进行抽取。然后在需要使用的时候使用include标签进行使用。

例如:

<sql id="baseSelect" >id,username,age,address</sql>
<select id="findAll" resultType="com.cycyong.pojo.User">
    select <include refid="baseSelect"/>  from user
</select>

最终执行的sql为: select id,username,age,address from user

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

cycyong

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

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

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

打赏作者

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

抵扣说明:

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

余额充值