MyBatis最简单讲解

目录

1.简单的上手:

2.Mybatis解决多参处理

3.Mybatis整合日志

4.Mybatis缓存机制

1.一级缓存

2.二级缓存

5.resultMap和resultType的区别

6.动态SQL

1. < sql > 和 < incloud >

2.< if >标签

3.< where >

4.< foreach >

7.#{} 和 ${}的区别(面试题)

8.mybatis中使用分页插件PageHelper

1.首先依赖jar包

2.需要在mybatis-config.xml中配置分页插件

3.使用分页插件


首先对MyBatis框架做一个简单的介绍,mybatis就是一个持久层的框架,对JDBC进行的封装,用于操作数据库的框架,是一个ORM(对象关系映射)框架的一种。

1.简单的上手:

1.依赖mybatis的jar包

<!-- mysql连接驱动-->
<dependency>
     <groupId>mysql</groupId>
     <artifactId>mysql-connector-java</artifactId>
     <version>8.0.28</version>
</dependency>

<!-- mybatis-->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.7</version>
</dependency>

<!-- 单元测试-->
<dependency>
     <groupId>junit</groupId>
     <artifactId>junit</artifactId>
     <version>4.13.2</version>
     <scope>test</scope>
</dependency>

2.创建一个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">

<!--MyBatis配置-->
<configuration>
    <!--添加properties配置文件路径(外部配置、动态替换)-->
    <properties resource="jdbc.properties" />
    <!--JDBC环境配置、选中默认环境-->
    <environments default="MySql">
        <!--MySql数据库环境配置-->
        <environment id="MySql">
            <!--事务管理-->
            <transactionManager type="JDBC"/>
            <!--连接池-->
            <dataSource type="org.apache.ibatis.datasource.pooled.PooledDataSourceFactory">
                <!--使用$ + 占位符-->
                <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注册-->
    <mappers>
        <!--注册Mapper文件的所在位置-->
        <mapper resource="mapper/UserMapper.xml"/>
        <!--这个是使用注解时使用的-->
        <!--<mapper class=""/>-->
    </mappers>
</configuration>

3.创建一个jdbc的配置文件 jdbc.properties 

复制的小伙伴要把数据库连接的url修改一下和数据库名我的是nine,还有数据库账号和密码

#jdbc.properties
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/nine?useUnicode=true&serverTimezone=Asia/Shanghai&characterEncoding=UTF8
jdbc.username=root
jdbc.password=123456789

4.编写代码

这里有两种操作数据库的方式

第一种是使用传统的Mapper.xml的配置文件。

第二种是使用注解进行操作。

我这里写的是Mapper.xml的方式,因为企业很多都是还是用的Mapper.xml的方式因为接口层和sql层能分开,可以降低耦合度

1. 首先写entity实体层

    这里用了 Lombok的@Data注解,注解主要包含了getter和setter方法 和 toString方法

@Data
public class User {
    private Integer id;
    private String name;
    private String username;
    private String password;
}

2.dao层

我这里写了最简单的新增和查询

public interface UserDao {
    // 新增
    int save(User user);
    // 查询
    List<User> select();
}

3.mapper.xml

<mapper namespace = "这里写dao层的地址和类" />

<?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.mybatis.dao.UserDao">

    <select id="select" resultType="com.mybatis.entity.User">
        select id,name,username,password from t_user
    </select>
    <insert id="save" useGeneratedKeys="true" keyProperty="id">
        insert into t_user(name,username,password) values(#{name},#{username},#{password});
    </insert>
</mapper>

4.以上写完了我们写一个简单的单元测试进行测试

这里我封装了一个Mybatis的一个utils下面发一下

@Test
    public void t1() throws IOException {
        // 读取Mybatis的流文件
        InputStream stream = Resources.getResourceAsStream("mybatis-config.xml");
        // 构建sqlsession连接对象工厂
        SqlSessionFactory sqlSession = new SqlSessionFactoryBuilder().build(stream);
        // 通过工厂获得连接对象
        SqlSession session = sqlSession.openSession();
        // 通过连接对象获得接口实现类对象
        UserDao dao = session.getMapper(UserDao.class);
        // 调用接口中的方法
        System.err.println(dao.select());

        stream.close();
    }
    @Test
    public void t2() throws IOException {
        UserDao dao = MybatisUtils.getDao(UserDao.class);
        User user = new User();
        user.setName("wwww213");
        user.setUsername("aaaee123");
        user.setPassword("123456e2");
        System.err.println(dao.save(user));
        MybatisUtils.commit();
        MybatisUtils.close();
    }

 我这里没写commit 需要手动进行commit

public class MybatisUtils {
    //线程副本  解决线程安全 每个线程都有自己的对象
    private static ThreadLocal<SqlSession> local=new ThreadLocal<>();

    public static SqlSessionFactory factory;
    static {
        try{
            //1.读取配置文件
            InputStream is= Resources.getResourceAsStream("mybatis-config.xml");
            //2.实例化会话工厂对象
            factory=new SqlSessionFactoryBuilder().build(is);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    //获得连接(从tl中获得当前线程SqlSession)
    private static SqlSession openSession(){
        SqlSession session = local.get();
        if(session == null){
            session = factory.openSession();
            local.set(session);
        }
        return session;
    }

    /**
     * 获取对应的Dao*/
    public static <T> T getDao(Class<T> clz){
        SqlSession session=local.get();
        if(session==null){
            session=factory.openSession();
            local.set(session);
        }
        return session.getMapper(clz);
    }
    /**
     * 关闭释放*/
    public static void close(){
        SqlSession session=local.get();
        if(session!=null){
            session.commit();
            session.close();
            local.remove();//防止内存泄漏
        }
    }

    //提交事务(提交当前线程中的SqlSession所管理的事务)
    public static void commit(){
        SqlSession session = openSession();
        session.commit();
        close();
    }


}

这样就可以直接把数据存储到我们的数据库中了

2.Mybatis解决多参处理

这里有三种方式解决多参

1.就是把我们的参数列表传入一个对象进去就可以解决了

int update(User user);

2.使用注解方式@Param解决(常用)

int update(@Param"id" int id,@Param"name" String name);

3.使用Map集合解决(不太长用)

 // 新增多参
    @Insert("insert into t_user(name,username,password) values(#{name},#{username},#{password})")
    int add(Map<String,Object> map);

//单元测试
 @Test
    public void t2(){
        // 多参处理 Map
        UserDao dao = MybatisUtils.getDao(UserDao.class);
        Map<String,Object> map = new HashMap<>();
        map.put("name","123456");
        map.put("username","map多参处理");
        map.put("password","处理成功");
        System.out.println(dao.add(map));
        MybatisUtils.commit();
        MybatisUtils.close();

3.Mybatis整合日志

mybatis中整合log4j日志

1.首先依赖jar包

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

2.在resource中创建 log4j.properties文件

# Global logging configuration
log4j.rootLogger=DEBUG, stdout
# MyBatis logging configuration...
log4j.logger.org.mybatis.example.BlogMapper=TRACE
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

这样我们在启动的时候就会加载日志了

4.Mybatis缓存机制

1.一级缓存

mybatis中的一级缓存是SqlSession级别的缓存默认开启状态的无需手动开启,对于select查询语句的话,多次查询的话会把查询过的内容放进一级缓存中,为了保证数据一致性,当执行过DML语言(即,增 删 改)对数据发生改变的,会立即把缓存中的内容全部清除,当在执行select会重新存储下。在操作数据库时需要构造sqlSession对象,在对象中有一个数据结构(HashMap)用于存储缓存数据。不同的sqlSession之间的缓存数据区域(HashMap)是互相不影响的。

可以看到第一次和第二次都是查询语句 所以执行了一次 第三次执行了删除的语句,此时myabtis会把缓存给删除掉了,然后我们第四次执行的时候又重新创建了缓存。 

2.二级缓存

二级缓存是Mapper级别缓存,能把同查询存储在SqlsessionFactory中,并且可以设置存储大小和过期时间,需要配置全局文件来开启二级缓存,但是二级缓存在 Sqlsession.close() 或者 Sqlsession.commint后生效。

1.要在mybatis-config.xml配置一个全局文件 来开启二级缓存

<!--开启二级缓存-->
<settings>
        <setting name="cacheEnabled" value="true"/>
</settings>

2.在Mapper.xml文件中添加

<!-- size:存储多少条 默认1024条 
     flushInterval:代表触发过期时间
     eviction:属性 淘汰策略 如果缓存空间达到上限,通过淘汰策略移出原来的数据
             常用的淘汰策略,1.LRU 淘汰最少使用的 2.FIFO 先进先出淘汰最先存储的-->
<cache size="1024" flushInterval="1000" eviction="LRU"></cache>

3.在开启二级缓存的时候一定要在实体层进行序列化

public class User implements Serializable {
    private Integer id;
    private String name;
    private String username;
    private String password;
}

4.测试

// 二级缓存
    @Test
    public void t2(){
        SqlSession session = MybatisUtils.factory.openSession();
        System.err.println(session);
        UserDao dao = MybatisUtils.getDao(UserDao.class);
        System.err.println("第一次"+dao.select());
        session.close();

        SqlSession session1 = MybatisUtils.factory.openSession();
        System.err.println(session1);
        UserDao dao1 = MybatisUtils.getDao(UserDao.class);
        System.err.println("第二次"+dao1.select());
        session1.close();

5.resultMap和resultType的区别

resultType 需要指定的实体包名

<select id="select" resultType="com.mybatis.entity.User">
        select id,name,username,password from t_user
</select>

resultMap 可用性更高,可以解决实体层和表中字段不一致。

<resultMap id="map" type="com.mybatis.entity.User">
    <result property="id" column="id"></result>
    <result property="name" column="name"></result>
    <result property="username" column="username"></result>
    <result property="password" column="password"></result>
 </resultMap>
 
<select id="all" resultMap="map">
    <include refid="s"></include>
</select>

注意:resultMap和resultType中在select只能选择一个

6.动态SQL

1. < sql > 和 < incloud >

<sql>标签是对查询语句的封装可以直接复用

<incloud> 实现<sql>标签的引用 通过refid进行引用

<sql id="s">
    select id,name,username,password from t_user
</sql>

<select id="all" resultMap="map">
    <include refid="s"></include>
</select>

2.< if >标签

<if>标签实现条件判断,必须要在<if>标签里面加上test <if test="">

<select id="user" resultMap="map">
        <include refid="s"></include>
        <if test="id>0">
            where id=#{id}
        </if>
</select>

3.< where >

<where>标签 动态添加,内部有条件就添加<where>,如果没有就不需要添加<where>

<select id="user1" resultMap="map">
    <include refid="s"></include>
       <where>
            <if test="id>0">
                and id=#{id}
            </if>
            <if test="name.length>0">
                or name like #{name}
            </if>
        </where>
</select>

4.< foreach >

<foreach>标签用于循环操作批量处理,批量删除,批量新增,批量新增,批量查询等。

参数

描述

取值

Collection

容器类型

list、array、map

open

起始符

(

close

结束符

)

separator

分隔符

,

index

下标符

从0开始,依次递增

item

当前项

任意名称(循环中通过#{任意名称} 表达式访问)

<insert id="user3">
      insert into t_user(name,username,password) value
      <foreach collection="list" item="u" separator=",">
            (#{u.name},#{u.username},#{u.password})
      </foreach>
</insert>

7.#{} 和 ${}的区别(面试题)

#{} 号 相当于一个占位符,会把我们在xml里面的sql替换成 一个 ?但是#{}只能传递数据,可以防止SQL注入

${} 号不能防止SQL注入,在xml文件中我们的sql语句会原样输出,但是${}不仅仅可以传递数据,还可以传递sql关键字,表结构信息或拼接其他查询,比如表名和字段名。

8.mybatis中使用分页插件PageHelper

PageHelper是一个分页的一个插件可以用于分页查询

1.首先依赖jar包

<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
    <version>5.3.0</version>
</dependency>

2.需要在mybatis-config.xml中配置分页插件

<!--分页插件-->
<plugins>
    <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>

3.使用分页插件

// 分页
    @Test
    public void t1(){
        UserDao dao = MybatisUtils.getDao(UserDao.class);
        // 开启分页,1.pageNum:要查询的页数,2.每页线上数量
        PageHelper.startPage(2,5);
        /** 开启分页后后面必须跟上查询语句,查询的结果为 pageInfo,包含
         *  总页数,总条数,查询的结果数据*/
        PageInfo<User> pageInfo = new PageInfo<>(dao.select());
        // 查询页数
        System.err.println("总页数为:"+pageInfo.getPages());
        // 获取总条数
        System.err.println("总条数:"+pageInfo.getTotal());
        // 获取数据源
        System.err.println("数据源:"+pageInfo.getList());
        MybatisUtils.commit();
        MybatisUtils.close();
    }

以上就是Mybatis的内容了,后面还有没有更新完,明天我会把没有更新完的更新完,此文章全部是我用手敲的,如果帮助到大家了 麻烦帮忙点个赞点个收藏,文章中有什么不对的可以及时指出来我会来验证的,还望各位大神轻点吐槽。

 


版权声明:本文为cxyzhaosi原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。