mybatis

1.Mybatis

优秀的数据持久层框架

最新版本Maven配置:

<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis</artifactId>
  <version>3.5.7</version>
</dependency>
1.搭建工程:

mybatis依赖+数据库连接依赖

<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis</artifactId>
  <version>3.5.7</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.17</version>
</dependency>

因为mybatis留有对数据库的接口,需要实现对应数据库(如mysql)的接口包,此时mybatis依赖搭建完成。

2.配置文件:

主标签:< configuration>< /configuration>

可选配置:

1.< properties >设置properties文件(可选)可用来存放配置文件需要用到的数据,如:数据库连接的相关信息。配置之后可以在配置文件中使用${key}来代指。

2.< settings >基本设置(可选)可用来设置SQL日志

3.< typeAliases>类型别名配置(可选)

必须配置:

1.< environments> 数据库环境配置

2.< mappers> mapper文件注册,***Mapper.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="jdbc.properties"/>
    
    <!--配置 日志等功能-->
    <settings>
    <!--SQl日志-->
        <!--<setting name="logImpl" value="org.apache.ibatis.logging.stdout.StdOutImpl"/>-->
            <!--这是使用别名-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
    
    <!--类型别名配置-->
    <typeAliases>
        <!--这是单独对类取别名-->
        <!--<typeAlias type="com.qf.mybatis.model.User" alias="user"/>-->

        <!--这是对包下的所有类进行取别名,别名为类名且不区分大小写(二者只能选其一)-->
        <package name="com.dream.mybatis.model"/>
    </typeAliases>
    
    <!--数据库环境配置-->
    <environments default="dev">

        <!--表示开发时使用-->
        <environment id="dev">
            <transactionManager type="JDBC"></transactionManager>
            <dataSource type="com.dream.mybatis.dataSource.DruidDataSourceFactory">
                <!--对properties文件中存储的信息进行取值,取值时使用的是OGNL表达式 ${properties文件中的key}-->
                <property name="driverClassName" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>

        <!--表示作为产品时使用-->
        <environment id="product">
            <!--事务管理器配置 type指的是事务管理器使用的类-->
            <transactionManager type="JDBC"></transactionManager>
            <!--数据源配置-->
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver1}"/>
                <property name="url" value="${jdbc.url1}"/>
                <property name="username" value="${jdbc.username1}"/>
                <property name="password" value="${jdbc.password1}"/>
            </dataSource>
        </environment>

        <!--表示测试时使用-->
        <environment id="test">
            <!--事务管理器配置 type指的是事务管理器使用的类-->
            <transactionManager type="JDBC"></transactionManager>
            <!--数据源配置-->
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver2}"/>
                <property name="url" value="${jdbc.url2}"/>
                <property name="username" value="${jdbc.username2}"/>
                <property name="password" value="${jdbc.password2}"/>
            </dataSource>
        </environment>
    </environments>

    <!--最后是注册mappers-->
    <mappers>
        <mapper resource="mapper/studentMapper.xml"/>
        <mapper resource="mapper/userMapper.xml"/>
        <mapper resource="mapper/courseMapper.xml"/>
        <mapper resource="mapper/teacherMapper.xml"/>
    </mappers>
</configuration>
3. mapper.xml:

< mapper namespace=" "> 写对应的mapper接口全路径。

<?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.dream.mybatis.mapper.StudentMapper">
   <!--其中还有二级字标签-->
</mapper>

**二级子标签分别对应于数据库的 增删查改(CRUD) **

id需要完全对应本文件对应的mapper接口中的方法名,resultType为返回类型 且只有select标签有

<select id="getStudentByName" resultType="student">
	<!--sql语句书写-->   
</select>

<insert id="addStudent">
	<!--sql语句书写-->  
</insert>

<delete id="deleteStudent">
	<!--sql语句书写-->
</delete>

<update id="updateStudent">
	<!--sql语句书写-->
</update>
重要知识点:
1.mapper接口方法中的参数传递给xml文件:

取值有两种方式**KaTeX parse error: Expected 'EOF', got '#' at position 11: {表达式}**和**#̲{表达式}**,其中经常使用的…{}只是进行拼接,不能够有效的防止SQL注入。

在括号中的表达式书写,分为四种情况:

1.接口方法的参数只有一个基本类型的参数时:表达式可以取任意命名,都将会自动匹配。

2.单个引用类型的参数时,可以直接使用该类对象的属性名,mybatis将会自动注入。重点:map作为参数,可以直接以key作为键值对。

3.当有多个参数时,参数的表达式默认为arg0argN-1,param1paramN。当对应参数位置为引用数据类型时,可以直接使用对应的表达式.(例如:arg1.name,param2.name)

4.在接口方法的参数上使用@Param注解,注解中可以声明一个别名,该别名可以被xml文件自动识别到,从而进行注入(推荐

注:在SQL语言中需要使用拼接的可以使用SQL自带的concat方法。**

如:LIKE CONCAT(’%’, #{params.name}, ‘%’)

2.主键回填

主键回填分为两种情况:一种是主键自增长的主键回填,第二种是主键由数据库随机生成(uuid)。

注意order的属性值。

1.主键自增长:

接口中的方法:

public interface ArticleMapper {
    
    int addArticle(@Param("article") Article article);
}

map.xml文件

<mapper namespace="com.dream.mybatis.mapper.ScoreMapper">
    <insert id="addScore">
        <!-- selectKey表示选择键 通常都是用于主键回填功能 keyProperty表示回填的值设置到哪个属性上
       resultType表示回填的值的数据类型  order表示主键回填的时机 AFTER表示数据保存后 BEFORE表示数据插入之前-->
        <selectKey keyProperty="score.id" resultType="long" order="AFTER">
            <!--获取当前表的最后一个id-->
            SELECT LAST_INSERT_ID()
        </selectKey>
        <!--insert语句-->
        INSERT INTO score(name, score)VALUES(#{score.name}, #{score.score})
    </insert>
</mapper>

2.主键由数据库自动生成

<insert id="addArticle">
    <selectKey keyProperty="article.id" resultType="string" order="BEFORE">
    SELECT REPLACE(UUID(),'-','')
    </selectKey>
    INSERT INTO article(id, title, content, author)
    VALUES (#{article.id}, #{article.title}, #{article.content}, #{article.author})
</insert>
3.结果映射:
<mapper namespace="com.dream.mybatis.mapper.EmployeeMapper">

    <resultMap id="empMap" type="com.dream.mybatis.model.Employee">
        <id property="id" column="id" />
        <result property="name" column="name" />
        <!--数据表中列名与实体类中的属性名匹配-->
        <result property="entryTime" column="entry_time" />
        <!--数据表中列名与实体类中的属性名匹配-->
        <result property="leaveTime" column="leave_time" />
    </resultMap>

    <select id="getAllEmployees" resultMap="empMap">
        SELECT id,name,entry_time,leave_time FROM employee
    </select>
</mapper>
4.级联查询

级联查询需要使用结果映射。

一对一级联查询需要使用< association>标签

<mapper namespace="com.dream.mybatis.mapper.CourseMapper">
<!--    <resultMap id="courseMap" type="course">-->
<!--        <id column="cno" property="id"/>-->
<!--        <result property="name" column="cname"/>-->
<!--        <association property="teacher" javaType="teacher">-->
<!--            <id column="tno" property="id"/>-->
<!--            <result property="name" column="tname"/>-->
<!--        </association>-->
<!--    </resultMap>-->
<!--    <select id="getCourse" resultMap="courseMap">-->
<!--        SELECT-->
<!--            c.cno,-->
<!--            c.cname,-->
<!--            c.tno,-->
<!--            t.tname-->
<!--        FROM-->
<!--            `a_course` c-->
<!--                LEFT JOIN a_teacher t ON c.tno = t.tno-->
<!--        WHERE c.cname = #{arg0}-->
<!--    </select>-->

    <resultMap id="courseMap" type="course">
        <id column="cno" property="id"/>
        <result property="name" column="cname"/>
        <association property="teacher" column="{tid=tno}" select="getTeacher" />
    </resultMap>
    <select id="getCourse" resultMap="courseMap">
        SELECT
            cno,
            cname,
            tno
        FROM
            a_course
        WHERE cname = #{arg0}
    </select>
    <select id="getTeacher" resultType="teacher">
        SELECT
            tno id,
            tname name
        FROM
            a_teacher
        WHERE tno = #{tid}
    </select>
</mapper>

一对多级联查询需要使用< collection>标签

<mapper namespace="com.dream.mybatis.mapper.TeacherMapper">
<!--    <resultMap id="teaMap" type="tea">-->
<!--        <id column="tno" property="id"/>-->
<!--        <result property="name" column="tname"/>-->
<!--        <collection property="cous" column="tno" ofType="cou" >-->
<!--            <id column="cno" property="id"/>-->
<!--            <result property="name" column="cname"/>-->
<!--        </collection>-->
<!--    </resultMap>-->
<!--    <select id="getAllTea" resultMap="teaMap">-->
<!--        SELECT-->
<!--            t.tno,-->
<!--            t.tname,-->
<!--            c.cno,-->
<!--            c.cname-->
<!--        FROM-->
<!--            `a_course` c-->
<!--                RIGHT JOIN a_teacher t ON c.tno = t.tno-->
<!--    </select>-->

    <resultMap id="teaMap" type="tea">
        <id column="tno" property="id"/>
        <result property="name" column="tname"/>
        <collection property="cous"  column="{tid = tno}" select="getCou"/>
    </resultMap>
    <select id="getAllTea" resultMap="teaMap">
        SELECT
            tno,
            tname
        FROM
            a_teacher
    </select>
    <select id="getCou" resultType="cou">
        SELECT
            cno id,
            cname name
        FROM
            a_course
        WHERE tno = #{tid}
    </select>
</mapper>
5.标签的应用

sql和include标签:SQL语言的重用,

<sql id="fields">
    username, password,salt,sex,address
</sql>
<select id="getUserByUsername" resultType="user">
    SELECT
    <include refid="fields" />
    FROM
    `user`
    WHERE
    username = #{abcde}
</select>

if标签:在test中写上符合java的布尔表达式,

<if test="params.name != null and params.name != ''">
    AND name LIKE CONCAT('%', #{params.name}, '%')
</if>

where标签:嵌套在if之外,能够自动添加where和忽略第一个and或者or关键字,

set标签:在updata语句中使用,也是嵌套在if之外,能够自动添加set和忽略SQL语句的后缀,如逗号,可以动态选择修改属性,

<set>
    <if test="s.name != null and s.name != ''">
        name = #{s.name},
    </if>
    <if test="s.score != null and s.score != ''">
        score = #{s.score},
    </if>
</set>
<where>
    <if test="s.id != null and s.id != ''">
        AND id = #{s.id}
    </if>
</where>

trim标签:可以代替 where 标签和 set 标签

<!-- 其中 prefixOverrides 属性表示要被重写的前缀,prefix 属性表示用来替换重写的前缀内容。suffix和suffixOvverdides 属性表示对后缀的处理-->
<trim prefix="" prefixOverrides="" suffix="" suffixOverrides=""></trim>

foreach标签:循环标签经常用于sql含有in或not in的常见

<!-- 
	collection表示遍历的元素类型,如果参数没有使用注解命名,那么该属性值只能是list,array,map其中之一;如果参数使用了注解命名,那么该属性值直接使用注解指定的名称即可。
	item表示每次遍历时使用的对象名
	open表示前面添加的内容
	close表示最后添加的内容
	seperator表示每次遍历时内容组装使用的分割符
	index表示遍历时的下标
-->
<foreach collection="" item="" open="" seperator="" close="" index="">

</foreach>
4. Mybatis缓存
  1. 缓存的定义

缓存就是存储在内存中的临时数据,将用户经常查询的数据放在缓存(内存)中,用户再次查询数据的时候就不用从磁盘上(关系型数据库数据文件)查询,从缓存中查询,能够提高查询效率,解决了高并发系统的性能问题

  1. 缓存的优势

减少和数据库的交互次数,减少系统开销,提高系统效率

  1. 缓存使用场景

经常查询并且不经常改变的数据

  1. Mybatis 缓存

mybatis包含一个非常强大的查询缓存特性,可以非常方便地定制和配置缓存,缓存可以极大地提高查询效率

mybatis系统默认定义了两级缓存:一级缓存和二级缓存

  • 一级缓存:

    默认情况下只有一级缓存开启(SqlSession级别的缓存,也称为本地缓存),同一个 SqlSession 执行多次同构查询时,结果将放入一级缓存。

  • 二级缓存:

    需要手动开启和配置,它是基于SqlSessionFactory级别的缓存,同一个 SqlSessionFactory 构建的 SqlSession 发起的多次同构查询,如果SqlSession关闭,则会将数据保存在二级缓存中

4.1 全局缓存配置
 <!-- config.xml-->
<settings>
    <setting name="cacheEnabled" value="true"/>
</settings>
4.2 Mapper缓存配置
<!--
    cache标签表示使用缓存
    flushInterval:表示缓存刷新时间,单位是毫秒
    readyOnly:表示是否只读;true 只读,MyBatis 认为所有从缓存中获取数据的操作都是只读操作,不会修改数据。MyBatis 为了加快获取数据,直接就会将数据在缓存中的引用交给用户。不安全,速度快。读写(默认):MyBatis 觉得数据可能会被修改
    size:表示存放多少条数据
    eviction: 缓存回收策略,有这几种回收策略
        LRU - 最近最少回收,移除最长时间不被使用的对象
        FIFO - 先进先出,按照缓存进入的顺序来移除它们
        SOFT - 软引用,移除基于垃圾回收器状态和软引用规则的对象
        WEAK - 弱引用,更积极的移除基于垃圾收集器和弱引用规则的对象
    -->
<cache flushInterval="300000" readOnly="true" size="10000" eviction="LRU"/>
4.3 二级缓存失效

二级缓存缓存数据的前提是查询的 SqlSession 关闭,如果 SqlSession 没有关闭,那么数据将不会进入二级缓存,再次进行同构查询时,二级缓存由于没有数据,查询将进入数据库,造成二级缓存失效的现象。另一种情况是,当前查询的 SqlSession 已经关闭,数据也进入了二级缓存,但在下一次查询之前,如果中间发生了更新操作,该操作更新的数据在的二级缓存中存在,那么二级缓存也将失效。

5.分页插件 PageHelper
1. 如何获取PageHelper

官方网站: https://pagehelper.github.io/

最新版本Maven配置:

<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
    <version>5.3.0</version>
</dependency>
2. 插件配置
<!-- config.xml中进行配置 -->
<plugins>
    <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>
3. 测试分页
@Test
public void paginationTest(){
    SqlSession sqlSession = MybatisUtil.openSession();
    //从Sql会话中获取Mapper接口的代理实例
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    Map<String,Object> params = new HashMap<>();
    params.put("sex", 1);
    params.put("name", "理");
    params.put("address", "千");
    //设置分页
    PageHelper.startPage(1, 5);
    List<User> users = userMapper.retrieveUsers(params);
    PageInfo<User> pageInfo = new PageInfo<>(users);//将分页查询的结果集保存在PageInfo对象中
    System.out.println("总条数:" + pageInfo.getTotal());
    System.out.println("总页数:" + pageInfo.getPages());
    //当前页数据展示
    pageInfo.getList().forEach(System.out::println);
}
6.配置数据源 Druid

Druid 是阿里巴巴开源平台上的一个项目,是性能最好的数据库连接池,如何在Mybatis中配置该数据源呢?

<dependency>
  <groupId>com.alibaba</groupId>
  <artifactId>druid</artifactId>
  <version>1.2.8</version>
</dependency>

创建 DruidDataSourceFactory, 并继承 PooledDataSourceFactory,并替换数据源

public class DruidDataSourceFactory extends PooledDataSourceFactory {
    public DruidDataSourceFactory() {
        this.dataSource = new DruidDataSource();//替换数据源
    }
}
<!--config.xml-->
<dataSource type="com.qf.mybatis.datasource.DruidDataSourceFactory"><!--数据源工厂-->
...
</dataSource>

最后,再附上一个mybatis的测试工具类和测试案例(注:一般在开发项目时使用ssm整合mybatis,放入ioc容器,不需要单独管理。)

/**
 * Mybatis的工具类
 */
public class MybatisUtil {
    //构造器私有化
    private MybatisUtil(){}

    //生产SQL会话的工厂
    private static SqlSessionFactory factory;

    //静态代码块初始化
    static {
        //创建SQL会话工厂构建者 SqlSessionFactoryBuilder
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        try{
            //读取配置文件
            InputStream is = Resources.getResourceAsStream("config.xml");
            //构建者根据配置文件来构建SqlSessionFactory
            factory = builder.build(is);
        } catch (IOException e){
            throw new RuntimeException("配置文件读取错误");
        }
    }

    public static SqlSession openSession(){
        SqlSession session = factory.openSession();
        //这下面是对session的代理模式
        //获取SqlSession的字节码文件对象
        Class<SqlSession> aClass = SqlSession.class;
        //获取上下文类加载器
        ClassLoader loader = aClass.getClassLoader();
        //将字节码文件对象放入数组
        Class[] interfaces = { aClass };
        //
        InvocationHandler handler = (proxy,method,args)-> {
            //获取方法名
            String name = method.getName();
            if (name.equals("close")){
                //如果是调用close方法,先提交事务
                try {
                    session.commit();
                } catch (Exception e){
                    //提交事物出错,回滚事务
                    session.rollback();
                }
            }
            //执行方法,返回方法执行的结果
            return method.invoke(session,args);
        };
        //此时返回一个SqlSession的代理
        return (SqlSession) Proxy.newProxyInstance(loader,interfaces,handler);
    }
}
 @Test
    public void searchStudentTest(){

        //获取SqlSession的代理对象
        SqlSession sqlSession = MybatisUtil.openSession();
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
        //执行查询
        StudentCondition studentCondition = new StudentCondition("川", 24);
        Student student = mapper.searchStudent(studentCondition);
        sqlSession.close();
        System.out.println(student);

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值