MyBatis框架_学习笔记

MyBatis框架

  • 早期叫做 ibatis,代理在 Github
  • MyBatis 全称为 MyBatis SQL Mapper Framework for Java(基于Java 的 SQL 映射框架)

MyBatis 提供的功能

  • 提供了创建Connection,Statement,ResultSet等对象的能力,不需要开发人员重复创建

  • 提供了执行 SQL 语句的功能

  • 提供了循环 SQL,将结果转换为List对象的能力,不再需要开发人员进行迭代

  • 提供了关闭资源的能力

MyBatis 的使用

XXXMapper.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="name">

    <!--parameterType可以是简单类型、引用类型、Map类型-->
    <!--resultType可以是简单类型、引用类型、Map类型-->
    <select id="" parameterType="" resultType=""></select>
    
    <!--模糊查询-->
    <select id="" parameterType="" resultType="">
        select * from table where id like '%' #{id} '%';
        <!--'%'和#{}中的空格不能省去,相当于加号,拼接作用-->
    </select>    
</mapper>

文件解读

  1. 1.指定的约束文件
    <?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">
  2. 约束文件作用:用于限制和检查当前文件中出现的标签、属性是否符合语法规范
  3. namespace 应该使用 dao 接口的全限定名称(包名 + 类名)
  4. resultType 应该使用 domian 中的类全限定名称

mybatis.xml 主配置文件(用于连接数据库,放于src目录下)

<?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="db.properties"/><!--加载配置文件-->
    <!--
        设置与数据库交互环境,例如二级缓存
        在实际开发中,基本没用,因为优化效率太低
    -->
    <settings>
        <setting name="cacheEnabled" value="true"/><!--二级缓存-->
        <setting name="lazyLoadingEnabled" value="true"/><!--延迟加载-->
        <setting name="logImpl" value="STDOUT_LOGGING"/><!--开启日志-->
    </settings>

    <!--为domain起别名-->
    <typeAliases>
        <!--方式1-->
        <typeAlias type="全路径名称" alias="别名"/>

        <!--方式2-->
        <!--为一个包下所有domain起好了别名,别名为类名且不区分大小写-->
        <package name="包路径名">
    </typeAliases>

    <!--环境配置-->
    <environments default="development"> <!-- default必须与下列某一个id相同,表示当前使用的配置信息-->
        <environment id="development">  <!-- id为配置名称,可以随便取-->
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/framework?useSSL=false&amp;serverTimezone=UTC"/>
    <!-- MySQL是8.0以上的版本,driver 和 url 的value 和以前不同,&amp; 等同于 &符号-->
                <property name="username" value="root"/>
                <property name="password" value="feifei123"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <!--适用于xml文件和dao文件不在一个目录下-->
        <mapper resource="xxx.Xxx.xml"/>
        <!--适用于xml文件和dao文件在一个目录下-->
        <package name="xxx"/>
    </mappers>
</configuration>

各标签的先后顺序:

properties,settings,typeAliases,typeHandlers,objectFactory,objectWrapperFactory,

reflectorFactory,plugins,environments,databaseIdProvider,mappers

属性配置文件

  • 把数据库连接信息单独放置在一个文件中,和主配置文件分开

格式key=value
key和=和value之间不可用有空格隔开
key一般使用 . 做多级目录,例:java.driver

利用<properties resource=" ">在主配置文件中指定相关的配置文件
而在主配置文件中只用使用 ${key} 来获取相关的配置信息即可

关于transactionManager : 负责MyBatis的事物提交
type 的两种类型

  1. JDBC : 表示MyBatis底层调用JDBC的Connection对象进行commit 和 rollback
  2. MANAGED : 把MyBatis事物处理委托给其他容器(可以是一个服务器,也可以是一个框架(Spring框架))

关于dataSource :表示数据源
type的两种类型

  1. POOLED : 使用连接池
  2. UPOOLED : 不使用连接池
  3. JNDI:java命名和目录服务(类似Windows注册表)

由于XXXMapper文件与 dao 文件一同放在了 java 文件夹下,而不在resources 文件夹下,Maven在进行编译时是会自动跳过java文件夹下的资源文件的,因此我们需要手动的进行调整,让Maven将java文件夹下的资源文件也打包如target/classes中
解决方法  在pom.xml 中加入如下代码:

<build>
    <resources>
         <resource>
             <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
             <filtering>false</filtering>
         </resource>
     </resources>
</build>

MyBatis 使用方法

public static void main(String[] args) throws Exception{
        InputStream in = Resources.getResourceAsStream("mybatis.xml");
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(in);
        SqlSession  sqlSession = factory.openSession();
        String sqlId = "dao.StudentDao.selectAll";
        List<Student> students = sqlSession.selectList(sqlId);
        students.forEach(student -> System.out.println(student));
        sqlSession.close();
}

代码解读:

Resources: 负责读取主配置文件

Inputstream in = Resources.getResourceAsstrean ( "mybatis.xml");

SqlSessionFactoryBuilder :创建SqlSessionFactory对象

SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder (); //创建sqlsessionFactory对象
SqlSessionFactory factory = builder. build(in) ;

SqlSessionFactory :重量级对象,程序创建该对象耗时比较长,使用资源比较多。在整个项目中,有一个就够用了。(单例模式)

SqlSession sqlSession = factory.openSession() ;

openSession()方法说明:

  1. openSession() :无参数的,获取是非自动提交事务的sqlsession对象
  2. openSession (boolean): openSession (true)获取自动提交事务的sqlsession.

SqlSession :
SqlSession接口∶定义了操作数据的方法例如selectone(),selectList() ,insert () , update ()
注意:SqlSession 对象不是线程安全的,因此执行sql语句之前,和使用之后要分别开启和关闭保证其线程安全性。

Mybatis 默认手动提交事务

sqlSession.commit(); 

在IDEA中添加模板文件

  • 选中 File --> Settings --> Editor --> File and Code Templates在其中添加一个文件并命名

MyBatis 动态代理

  • MyBatis 中为我们提供了一套动态代理机制

public static void main(String[] args){
        SqlSession sqlSession = MyBatis.getSqlSession();
        StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
        Student student = new Student("024","花木兰",22,"女");
        int num = studentDao.insertStudent(student);
        sqlSession.commit();
        System.out.println("影响行数:"+num);
}

sqlSession.getMapper(StudentDao.class) 通过反射机制获取到StudentDao接口的动态代理类
而在 studentDao.insertStudent(student) 直接使用动态代理接口的方法即可
方法的名字应该与 XXXMapper.xml 文件中的某个 id 相同

参数传递

  • parameterType:传入SQL语句的数据类型因为 MyBatis 具有反射机制,能够识别出数据类型,因此开发中一般不写

MyBatis 四种传值方式

使用@Param传值
接口方法:

List<Student> select(@Param("myid") String id)

sql 语句:

select * from table where id = #{myid};

不推荐使用,参数多时,一个一个命名困难

使用对象传值

select * from table where id = #{id} and name = #{name};

推荐使用,但是{ }中的名字必须是 domain 对象的属性名

按位置传值
按接口中的参数列表中参数的位置进行传输

select * from table where id = #{arg0} and name = #{arg1}

不推荐使用,可读性低,难以维护

Map传值
接口方法:

List<Student> select(Map<String,Object> map)

sql语句:

select * from table where id = #{id} and name = #{name};

推荐使用,但是{ }中的名字必须是 Map 中已有的 key

缺点:光看接口方法难以看出map中有几个参数,参数类型又是什么,并且保证key的正确性

# 和 $ 的区别

  • # 相当于 sql语句中的 ?,使用的是PrepareStatement对象,可以防止sql注入
  • $ 使用的是字符串拼接,一般用于替换列名或表名(即便如此也有可能被注入)

例如:select * from table order by ${colName}; 
select * from ${tableName};

简单类型 (String + 基本数据类型) 可以直接写简写,不需要包名,不区分大小写
Map类型无法迭代,可以先使用 map.keySet() 获取 map集合的关键字集合,再对关键字集合进行迭代获取 value
当使用分组查询的时候,只能使用map来封装查询结果,而不能用domain,因为domain没有count属性

resultMap

  • 用于指定列名与java对象的属性对应的关系(支持复用)

使用情况:

  1. 自定义赋值给某个属性时
  2. SQL列名与对象属性名不相同时
<resultMap id="mapName" type="java全限定名">
    <id column="id" property="id"/>            <!--主键列-->
    <result column="age" property="peopleAge"/>        <!--非主键列-->
</resultMap>
<select id="selectCount" resultMap="mapName">
    select * from student;
</select>

PS:在sql 语句中用 as 来调整列名,也可以解决SQL列名与对象属性名不相同的问题

模糊查询

方法一

select * from table where name like #{name};

需要在接口方法中传入一个name的字符串,推荐使用

方法二

select * from table where name like "%" #{name} "%";

还是需要在接口方法中传入一个name的字符串,只是内容不同

动态 SQL

sql 的内容是变化的,可以根据条件不同获取到不同的sql语句
主要是where部分的变化
使用的是MyBatis提供的标签,<if> <where> <foreach>

<if> 标签

<if test="name != null and name != '' ">
    and name = #{name}
</if>

当一个条件满足时,但是前面又没有其他条件时,多出来的and会导致sql语句报错(where and name = #{name})
因此我们会在where后面加入一个无关紧要的条件例如 1=1 这样来改善代码

where 1=1 and name = #{name}; 

这样代码自然就不会报错了

<where> 标签

<where>
    <if test="name != null and name != '' ">
        and name = #{name}
    </if>
</where>

where 会将第一个多余的无效字符去除<foreach>标签

<froeach collection="" item="" open="" close="" separator="">
</foreach>

collection:表示接口方法中参数类型,如果是数组用array,如果是List用list
item:是自定义的集合成员变量(如果成员变量是对象,则用#{对象.属性}即可)
open:循环开始字符
close:循环结束字符
separator:集合成员之间的分隔符

open,close,separator 可以直接写在sql语句内,因此可以省去不写

代码片段

定义片段

<sql id="sql_1">
    select * from table_1
</sql>

调用片段

<include refid="sql_1"> where id=#{id}

不推荐使用,可读性低

PageHelper(不属于MyBatis框架,国内作者创作)

maven

<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artiactId>pagehelper</artiactId>
    <version>5.1.10</version>
</dependency>

主配置文件

<plugins>
    <plugin interceptor="com.github.pagehelper.PageInterceptor"/>
</plugins>

在进行查询前使用

PageHelper.startPage(页数,行数);
List<Student> students = dao.selectAll();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值