Mybatis(1)——demo,缓存,映射,动态sql

1 Mybatis

使用了 MyBatis 之后,只需要提供 SQL 语句就好,基于java的持久层框架。
持久层: 可以将业务数据存储到磁盘,具备长期存储能力,只要磁盘不损坏,在断电或者其他情况下,重新开启系统仍然可以读取到这些数据。
优点: 可以使用巨大的磁盘空间存储相当量的数据,并且很廉价;
缺点:慢(相对于内存而言)

GroupId,ArtifactId 统称为“坐标”是为了保证项目唯一性而提出的,如果你要把你项目弄到maven本地仓库去,你想要找到你的项目就必须根据这两个id去查找。
GroupId:定义了项目属于哪个组;
Artifacted:定义了当前maven项目在组中唯一的ID,项目的唯一的标识符,实际对应项目的名称,就是项目根目录的名称。
在这里插入图片描述

1 demo

maven,webapp项目,实现单表增删改查

1.下载和搭建 MyBatis 的开发环境。
在【File】菜单下找到【Settings】,然后再【Plugins】下点击【Browse repositories…】
在搜索栏中输入【MyBatis Plugin】,然后点击【Install】
Free MyBatis plugin

2.步骤:
(1) pom.xml文件

// mybatis核心包
<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis</artifactId>
  <version>3.4.6</version>
</dependency>
// mysql驱动包
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.46</version>
</dependency>

(2) mybatis.xml文件
建立模板,方便下次新建xml文件:File–settings–Editor–File and Code Templates

<?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>
    <!-- 加载 java 的配置文件或者声明属性信息 -->
    <!-- <properties resource="db.properties"/> -->
    <settings>
        <!--当返回行的所有列都是空时, MyBatis 默认返回 null-->
        <setting name="returnInstanceForEmptyRow" value="true"/>
        <!--显示 sql 语句-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
        <!--数据库的字段名的下划线 => pojo 属性中的 驼峰命名法-->
        <!-- <setting name="mapUnderscoreToCamelCase" value="true"/> -->
    </settings>
    <!-- 自定义别名 -->
    <typeAliases>
        <!-- 单个别名定义 -->
        <!-- <typeAlias type="com.itheima.mybatis.po.User" alias="user"/> -->
        <!-- 批量别名定义(推荐) -->
        <!-- package:指定包名称来为该包下的 po 类声明别名,默认的别名就是类名(首字母大小写都可) -->
        <!--<package name="com.hsj.pojo" />-->
    </typeAliases>
    <!-- 配置 mybatis 的环境信息,与 spring 整合,该信息由 spring 来管理 -->
    <environments default="development">
        <!--测试环境-->
        <!--开发环境-->
        <environment id="development">
            <!--使用了 JDBC 的提交和回滚设置,它依赖于从数据源得到的连接来管理事务作用域-->
            <transactionManager type="JDBC"/>
            <!--使用数据池,复用实例-->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url"
                          value="jdbc:mysql://localhost:3306/admin?useUnicode=true&amp;characterEncoding=utf8"/>
                <property name="username" value="root"/>
                <property name="password" value="1234"/>
            </dataSource>
        </environment>
        <!--生产环境-->
    </environments>
    <mappers>
        <!-- 映射文件方式 1,一个一个的配置
        <mapper resource="com/hsj/pojo/UserMapper.xml"/>-->
        <!-- 映射文件方式 2,自动扫描包内的 Mapper 接口与配置文件(推荐) -->
        <!-- <package name="com/hsj/pojo"/> -->
        <mapper resource="mapper/EmployeeMapper.xml"/>
    </mappers>
</configuration>

注意:底层规定 标签顺序不可改变。
(3) pojo类
建立数据库连接,生成pojo类

在这里插入图片描述
添加无参构造器:反射时 映射 空对象

(4) 数据库映射XML

(5) 创建数据库操作对应的接口
EmployeeMapper.java

public interface EmployeeMapper {
    List<Employee> findAll();
    void addEmployee(Employee employee);
    void updateEmployee(Employee employee);
    Employee getEmployee(Employee employee);
    void delEmployee(Employee employee);
}

快捷键:鼠标位于EmployeeMapper ,alt+enter
EmployeeMapper.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.java201.dao.EmployeeMapper">
    <select id="findAll" resultType="com.java201.pojo.Employee">
        select * from employee;
    </select>
    <insert id="addEmployee">
        insert into employee values (#{id},#{ename},#{eage},#{employ})
    </insert>
    <delete id="delEmployee">
        delete from employee where id=#{id}
    </delete>
    <select id="getEmployee" resultType="com.java201.pojo.Employee">
        select * from employee where id=#{id}
    </select>
    <update id="updateEmployee">
        update employee set ename=#{ename},eage=#{eage} where id=#{id}
    </update>
</mapper>

(PS:接口里面的方法名和 mapper 里面的 id 要对应起来)
(6).控制器(测试类)
执行流程

@Test
    public void testfindAll() {
        try{
            // 1. 加载核心配置文件
            InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml");
            // 2. 创建session工厂
            SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
            // 3. 创建session => 相当于数据库连接对象
            SqlSession session = factory.openSession();
            // 4. 获取mapper的代理对象
            EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
            // 5. 执行正常的操作
            // 5.1 查询全部
            List<Employee> employees = mapper.findAll();
            for(Employee employee : employees) {
                System.out.println(employee);
            }
            // 5.2 新增
            Employee employ = new Employee();
            employ.setId("111");
            employ.setEage("23");
            employ.setEname("憨憨");
            employ.setEmploy("程序员");
            mapper.addEmployee(employ);
            // 5.3 删除
            Employee employ = new Employee();
            employ.setId("111");
            mapper.delEmployee(employ);
            // 5.4 修改
            Employee employ = new Employee();
            employ.setId("2");
            Employee employee = mapper.getEmployee(employ);
            employee.setEname("王哈哈哈");
            mapper.updateEmployee(employee);
            // 6. 提交事务
            session.commit();
            // 7. 关闭资源
            session.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

1.1 SqlMapConfig.xml 中配置的标签元素和顺序

  1. properties(属性)
  2. settings(全局配置参数)
  3. typeAliases(类型别名)
  4. typeHandlers(类型处理器)
  5. objectFactory(对象工厂)
  6. plugins(插件)
  7. environments(环境集合属性对象)
    |–environment(环境子属性对象)
    |–transactionManager(事务管理)
    |–dataSource(数据源)
  8. mappers(映射器)

1,3,8是重点标签

1.2 两种操作数据库的方式

1、通过 session 获取对应的 Mapper 接口的代理对象,然后通过该代理对象 调用对应的方法。(建议使用)

UserMapper mapper = session.getMapper(UserMapper.class);
List<User> users = mapper.findAll();

2、通过 session 直接调用接口中的方法

List<User> users = session.selectList("findAll");
//findAll接口中的方法

(PS:接口和 mapper.xml 缺一不可)

2 缓存

应用程序和数据库交互的过程是一个相对比较耗时的过程。
缓存存在的意义:让应用程序减少对数据库的访问,提升程序运行效率

2.1 一级缓存

SQISession级别的缓存。在操作数据库时需要构造SqlSession 对象,在对象中有一个数据结构(HashMap) 用于存储缓存数据。不同的SqlSession 之间的缓存数据区域(HashMap) 是互相不影响的。默认是开启的
key:sql语句
value:获取的值

同一个SqlSession对象调用同一个< select>时,只有第一次访问数据库,之后把查询结果缓存到SqlSession缓存区(内存)中去。

缓存的是statement对象.(简单记忆必须是用一个是用一个< select>),在 myabtis 时一个< select>对应一个 statement 对象。

有效范围必须是同一个 SqlSession 对象。

一旦涉及数据改动(增删改),mybatis自动清除一级缓存,防止读取脏数据。

2.2 二级缓存

mapper级别的缓存。多个SqISession 去操作同一个mapper的sql 语句,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession 的。需要手动开启

有效范围:同一个 factory 内哪个 SqlSession 都可以获取。

1.在 SQLMapConfig.xml 设置二级缓存的总开关(< setting name=“cacheEnabled” value=“true”/>);
2.还要在具体的 mapper.xml 中开启二级缓存(< cache/>);
3.如果不写 readOnly=”true”需要把实体类序列化 = = = = 因为查询出的对象要被序列化后存入内存,所以需要实体类实现 Serializable 接口。< cache readOnly=” true”>< /cache >
4.要想二级缓存生效,必须提交事务。
当 SqlSession 对象 close()时或 commit()时会把 SqlSession 缓存的数据刷(flush)到 SqlSessionFactory 缓存区中。

刷新二级缓存:
数据改变(增删改);再开启一个 sqlSession3,当 sqlSession1 查询完成后,sqlSession3 执行一次插入操作,为了避免脏读会刷新缓存,然后再用 sqlSession2 进行查询,缓存中就没有数据。

事务隔离:https://blog.csdn.net/weixin_45044097/article/details/103037246

3 输入输出映射

数据库(下划线命名法),pojo(驼峰命名法)
数据库下划线命名转换为驼峰命名法:
< setting name=“mapUnderscoreToCamelCase” value=“true”/>

3.1 如何解析sql语句

Mybatis对于用户在XXMapper.xml文件中配置的sql解析主要分为2个时机:
静态sql:程序启动的时候解析
动态sql:用户进行查询等sql相关操作的时候解析
sql文本中包含${}参数占位符则为动态sql,否则为静态sql。 静态sql效率会比动态sql好。

加载核心配置文件,解析标签,sql,动态代理,加载到方法。。。。。。

面试题:Mybatis中的Dao接口和XML文件里的SQL是如何建立关系的?
http://www.mybatis.cn/archives/467.html

3.2 #{ }和${ }的区别

#{ }
表示一个占位符号(和传统jdbc中的?作用一致),可以实现preparedStatement 向占位符中设置值, 自动进行 java 类型和 jdbc 类型转换。可以接收简单类型值或 pojo 属性值。如果parameterType 传输单个简单类型值, #{}括号中可以是 value 或其它名称。在预编译的时候会把参数使用一个占位符?代替,进入数据库后会把?替换成具体的属性值,需要进行数据类型装换,能有效防止sql注入;

$ { }
表示拼接sql串通过,$ {}可以将 parameterType 传入的内容拼接在 sql 中且不进行 jdbc 类型转换, ${}可以接收简单类型值或 pojo 属性值,如果 parameterType 传输单个简单类型值, ${}括号中只能是 value。
可能发生sql注入,因为在动态解析的时候会把这部分sql语句当做sql片段进行sql拼接而不会发生数据类型的装换,到数据库之后就会变成一个已经定型的sql语句了。

3.3 参数的传入

1.单参数传递

占位符的名字和参数名一致

2.多参数传递
  1. 传递对象(pojo):占位符的名字和pojo的属性名一致

  2. 传递map:占位符的名字和map的key一致
    在这里插入图片描述
    在这里插入图片描述

  3. 直接传递多参数:特殊占位符的名字注意: 允许的参数名 [arg1, arg0, param1, param2],如果有三个参数则为 arg3 或者param3…以此类推
    在这里插入图片描述
    注意参数arg1, arg0对应起来。

对应接口文件:
在这里插入图片描述
4. 注解的方式:自定义名字=====>比较常用

  • @Param( value=”参数") 和 占位符一致
<insert id="insert">
        insert into dept(id,deptName) values (#{id},#{deptName})
    </insert>

接口中:
Integer insert(@Param(value=“id”)String id, @Param(value=“deptName”)String deptName)

map传出

下划线转驼峰;
结果映射:
在这里插入图片描述
在这里插入图片描述

注解的使用

在这里插入图片描述
在这里插入图片描述
还需要在 sqlMapConfig.xml 中配置一下 mapper 接口的路径:
在这里插入图片描述

parameterType 和 resultType

  1. parameterType:指定输入参数类型, mybatis 通过 ognl 从输入对象中获取参数值拼接在 sql 中。
  2. resultType:指定输出结果类型, mybatis 将 sql 查询结果的一行记录数据映射为 resultType 指定类型的对象。如果有多条数据,则分别进行映射,并把对象放到容器 List 中。

4 动态sql

见下篇文章:
https://blog.csdn.net/weixin_45044097/article/details/103138976

发布了79 篇原创文章 · 获赞 7 · 访问量 1843

猜你喜欢

转载自blog.csdn.net/weixin_45044097/article/details/103009667
今日推荐