Mybatis入门详解

Mybatis

入门

Mybatis的基本使用

1.导入依赖

可以在https://mvnrepository.com/中复制导入pom.xml中相应的依赖

在这里插入图片描述

<dependencies>
   	<!--导入Mybatis依赖-->
    <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.4.6</version>
    </dependency>
    <!--导入mysql依赖-->
    <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.47</version>
    </dependency>

  </dependencies>
2.编写实体类

根据所要执行操作的数据库的内容进行编写,定义表中成员变量,定义get set方法,定义tostring方法便于数据查看

在这里插入图片描述

3.编写持久层接口

根据所要执行的数据库操作来定义一个接口,提供可以完成需求的抽象方法
在这里插入图片描述

4.新建resourses资源文件夹
  • resourses资源文件夹用来存放映射文件和配置文件
  • 配置文件的路径要求和其对应的持久层接口位置相同,所以要在resourses资源文件夹下创建同样路径的文件夹
  • 创建方式与建包不同,用/ 或者 \ 来分隔各级文件夹

在这里插入图片描述

5.编写持久层接口对应的映射文件

映射文件编写要求

命名要与持久层接口名相同,拓展名为xml,创建xml文件用new File

在这里插入图片描述

映射文件的创建位置必须要与持久层接口的创建位置相同,即对应的路径一致
在这里插入图片描述

映射文件的内容为:

<?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.kaifamiao.dao.IUserinfo">
    <!--找到之后要用来使用,映射接口中的方法,接口提供一个selectAll查询方法,所以下面开始实现查询操作-->
    <select id="selectAll" resultType="com.kaifamiao.model.IUserDemo">
        select * from student
    </select>
    <!--这里id的值是映射的方法名,resultType结果类型是方法的参数类型-->
</mapper>
6.编写配置文件

创建配置文件要把配置文件的路径放在resourses资源文件夹的最外层路径
在这里插入图片描述

配置文件的内容为:

<?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>
    <!--默认情况下启动的数据源-->
    <environments default="mysql">
        <!--属性id用来标识数据源-->
        <environment id="mysql">
            <!--配置事物的类型-->
            <transactionManager type="JDBC"></transactionManager>
            <!--数据库连接方式-->
            <dataSource type="POOLED">
                <!--配置JDBC-->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/guojinhao"/>
                <property name="username" value="root"/>
                <property name="password" value="12345"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <!--配置映射文件的位置(/相对路径)-->
        <mapper resource="com/kaifamiao/dao/IUserinfo.xml"/>
    </mappers>
</configuration>

这里发现映射文件和配置文件的头很相似

<!--映射文件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">
<!--配置文件config——>
<?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">

改变了关键字

7.编写测试类

先在持久层接口的方法上生成test测试类

在这里插入图片描述

在这里插入图片描述

单元测试JUit4 的方法需要添加@Test注解

在这里插入图片描述

测试类的内容为:

package com.kaifamiao.dao;

import com.kaifamiao.model.IUserDemo;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

import static org.junit.Assert.*;

public class IUserinfoTest {
    @Test
    public void test() throws IOException {
        //1读取配置文件
        InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
        //2创建SqlsessionFactory的构建者对象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        //3创建创建SqlsessionFactory对象,通过构建者对象来创建
        SqlSessionFactory factory = builder.build(in);
        //4SqlsessionFactory工厂生产创建Sqlsession对象
        SqlSession session = factory.openSession();
        //5通过Sqlsession创建dao接口的代理对象
        IUserinfo userinfo = session.getMapper(IUserinfo.class);
        //6通过代理对象来执行查询方法
        List<IUserDemo> users = userinfo.selectAll();
        for (IUserDemo user : users){
            System.out.println(user);
        }
        //7释放资源
        session.close();
        in.close();
    }
}

优化

作用域和生命周期

SqlsessionFactoryBuilder

创建SqlsessionFactory之后就不再需要

可以在static静态代码块内使用——初始化之后就不再使用(用完即弃)

SqlsessionFactory

被创建之后要一直存在,可以把他看做池的概念,而Session可以视为池中的内容

可以声明为静态成员,实例完成就一直存在

Sqlsession

他的实例不是线程安全的,不能被共享

可以在方法内部进行实例,随用随取

并且用完之后记得关闭,防止占用资源

sqlsession.close()

优化后项目结构

在这里插入图片描述

main文件夹

在持久层dao层和实体类层pojo层同级增加工具类层utils层,并且新建工具类MybatisUtils

在工具类中对Sqlsession提供实例化方法

public class MybatisUtils {
   	//由于他们的作用域与生命周期
    //SqlSessionFactory定义为成员,一直都要存在
    private static SqlSessionFactory sqlSessionFactory; 
    static {
        try {
            String resourse = "mybatis-config.xml";
            InputStream stream = Resources.getResourceAsStream(resourse);
           //SqlSessionFactoryBuilder在静态代码块内,实例完就不需要了
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(stream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
   	//把SqlSession的实例放在方法内,需要的时候就引用,防止占用资源
    public static SqlSession getSqlSession(){
        return sqlSessionFactory.openSession();
    }
}

补充:提升变量作用域

在实例化SqlSession的方法中需要用到代码块内的sqlSessionFactory ,需要提升sqlSessionFactory 作用域

把sqlSessionFactory 在类中定义为静态成员,方法内就可以调用

这里需要注意静态代码块内对sqlSessionFactory 的实例时,直接用对象就可以, sqlSessionFactory = new SqlSessionFactoryBuilder().build(stream);

加上他的类型会导致空指针异常,因为在成员变量中定义的sqlSessionFactory默认为null

test文件夹

Junit4生成测试类时勾选before after,sqlsession的实例引用可以写在before中,sqlsession的关闭可以写在after中

在这里插入图片描述

public class StudentDaoTest {
    private static SqlSession sqlSession;
    @Before
    public void setUp() throws Exception {
        sqlSession = MybatisUtils.getSqlsession();
    }

    @After
    public void tearDown() throws Exception {
        sqlSession.close();
    }

    @Test
    public void selectAll() {
        StudentDao mapper = sqlSession.getMapper(StudentDao.class);
        List<Student> students = mapper.selectAll();
        for (Student student : students) {
            System.out.println(student);
        }
    }
}

配置

属性优化

在mybatis的核心配置文件mybatis-config.xml中,可以对property属性进行配置

比如

	<property name="driver" value="com.mysql.jdbc.Driver"/>
	<property name="url" value="jdbc:mysql://localhost:3306/guojinhao"/>
	<property name="username" value="root"/>
	<property name="password" value="12345"/>
	//****************************************************
	<property name="driver" value="${driver}"/>
	<property name="url" value="${url}"/>
	<property name="username" value="${username}"/>
	<property name="password" value="${password}"/>

他们的区别在于值的别名,可以把属性值的配置看做修改别名,配置完成之后,只需要引用就可以

需要在resources文件夹下新建db.properties文件并添加对所需属性的描述

在这里插入图片描述

然后在核心配置文件mybatis-config.xml中添加<properties>标签,引入外部文件db.properties即可

别名优化

在mapper文件中的CURD方法内需要进行传参或返回值,返回值resultType或参数parameterType的值如果不进行别名优化需要写入实体类的全限定类名

如果在核心xml配置文件内对别名进行配置,就可以直接使用别名

 	<properties resource="db.properties"/>
    <settings>
        <setting name="logImpl" value="LOG4J"/>
    </settings>
    //对student和teacher类型改别名
    <typeAliases>
        <typeAlias type="com.kaifamiao.pojo.Student" alias="Student"/>
        <typeAlias type="com.kaifamiao.pojo.Teacher" alias="Teacher"/>
    </typeAliases>

也可以通过package来对整个包下的实体类进行系统别名,默认为实体类类名的大/小写

全局配置优化

在核心配置文件中,setting标签内可以定义全局配置,对整个项目做一定的公共设置

比如开启驼峰命名

开启延迟加载(懒加载)

禁用一级缓存

开启二级缓存

注意

在核心配置文件中,配置有规定的顺序,如果没有按照规定顺序进行配置会报错,正确的顺序为

<properties> 属性

<settings> 全局

<typeAliases> 别名

Mappers映射器

在核心xml配置文件中要对mapper文件进行映射才能获取,每一个mapper.xml文件都需要在核心配置中注册

类路径资源引用
    <mappers>
        <mapper resource="com/kaifamiao/dao/StudentMapper.xml"/>
        <mapper resource="com/kaifamiao/dao/TeacherMapper.xml"/>
    </mappers>
class文件(全限定类名方式)
	<mappers>
        <mapper class="com.kaifamiao.dao.TeacherMapper"/>
    </mappers>
package包路径
	<mappers>
        <package name="com.kaifamiao.dao"/>
    </mappers>

ResultMap结果集映射

当数据库中字段与实体类中对应的属性命名不能一一对应时,把实体类作为返回值会导致不匹配的字段的值为null

引入ResultMap,对不一致的值进行具体描述

或者在关系数据库多表联查的时候需要使用

在这里插入图片描述

这里的teacher表有tid,tname两个字段,而teacher实体类中的属性是tid和name,name不一致

在这里插入图片描述

在mapper.xml映射文件中要对SQL语句做一定的修改

	<select id="selectByMap" resultMap="ByMap">
        select * from teacher
    </select>
    <resultMap id="ByMap" type="Teacher">
        <id property="tid" column="tid"/>
        <result property="name" column="tname"/>
    </resultMap>

<id> 指对数据库内主键的描述

<result>指对数据库内其他键的描述

还有<association> 对对象进行描述(多对一)

<collection> 对集合类型的属性进行描述(一对多)

property 指实体类的属性名

column 指数据库字段名

重点注意

对照关系数据库联查,对于单表查询,如果个别实体类属性与数据库字段不对应,在ResultMap结果集映射中只对不对应字段描述即可

而关系型数据库的联查,必须每一条对应语句都写出来,这是规定,否则无对应表示查询出来

动态SQL

复杂的CURD操作,简单的SQL语句不能完成功能,引入动态SQL便于进行

if

当CURD操作有多个条件,通过if标签来添加条件,必须同时满足才能完成CURD操作

	<select id="selectByMap" resultType="Teacher">
        select * from teacher
        <where>
        	//每一个条件必须都走一遍
            <if test="tname!=null">
                tname = #{tname}
            </if>
            <if test="tid!=null">
                and tid = #{tid}
            </if>
        </where>
    </select>

choose(when,otherwise)

当CURD操作有多个条件,满足最靠前的条件即可跳出来执行CURD操作

 	<select id="selectByMap" resultType="Teacher">
        select * from teacher
        <where>
            <choose>
        		//条件一
                <when test="uid!=null">
                    uid = #{uid}
                </when>
                //条件二
                <when test="uname!=null">
                    and uname = #{uname}
                </when>
                //如果条件一条件二不满足就走otherwise 参考java switch default
                <otherwise>
                    and ugrade = #{ugrade}
                </otherwise>
            </choose>
        </where>
    </select>

对if和choose中的test值的特别注意

	<when test="uname!=null">
        and uname = #{uname}
    </when>

1.首先test的值 uname!= null 这里的uname不是数据库字段中的uname,而是指传入的参数名,与下边#{uname}是相同的

2.下边uname = #{uname} 前边的uname指数据库中字段uname

3.如果传入的参数不为空,就把这个参数的值添加到条件中

案例:

	<select id="selectByMap" resultMap="ByMap" parameterType="Teacher">
        select * from teacher
        <where>
            <if test="name!=null">
                tname = #{name}
            </if>
            <if test="tid!=null">
                and tid = #{tid}
            </if>
        </where>
    </select>
    <resultMap id="ByMap" type="Teacher">
        <id property="tid" column="tid"/>
        <result property="name" column="tname"/>
    </resultMap>

这里的方法返回值类型为Teacher类型,参数也为Teacher类型,且Teacher类中的name属性对应数据库Tname,不一致

传入的student默认set方法传进去的参数名为实体类中的name,所以if中写的参数不能为uname,需要改成实体类对应的name,并且test的值也要对应为name

trim格式化输出(where,set)

在CURD操作时,多个条件的sql操作需要中间使用连接符

where对应and

因为sql查询条件语句中,where后不能直接接and

定义where标签可以自动剔除他之后的and

set对应,

因为sql更新语句中,set语句最后后不能是逗号,

定义set标签可以自动剔除最后的,

 	<update id="updateByTea" parameterType="Teacher">
        update teacher
        <set>
            <if test="tgrade!=null">
                tgrade = #{tgrade},
            </if>
            <if test="tname!=null">
                tname = #{tname}
            </if>
        </set>
        where tid = #{tid}
    </update>

foreach

关系数据库的查询

多对一

一对多

延迟加载(懒加载)

多对一

一对多

缓存

一级缓存

二级缓存

补充

log4j日志

lombok插件

mybatisX插件

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值