MyBatis框架使用笔记-1(环境搭建与基本使用)

1.概述

MyBatis是一个数据库访问框架,对jdbc进行了封装。

2.环境搭建与使用

2.1.导入相关依赖

在这里插入图片描述

2.2.新建全局配置文件

MyBatis的全局配置文件是一个xml文件,该文件没有名称和路径要求,需要我们在使用的时候手动导入。configuration标签下有多个配置标签:

  • settings:设置,可以用于配置所使用的日志输出依赖
  • typeAliases:别名,可以对类和包起别名,方便使用
  • environment:环境,这是myBatis全局配置文件中最重要的一个标签,其定义了与数据库连接的相关信息,如数据库驱动、数据库的url,用户名,密码等。
  • mapper:包含了SQL命令的xml配置文件的路径。

DOCTYPE中所引用的.dtd(Document Type Definition)为文档类型定义,能对当前.xml文件进行规定和约束。通过它.xml文件可以使用相应的标签。(不同类型的.xml文件会引用到不同的.dtd文件)

<?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>
    <settings>
        <!--配置使用的日志输出依赖-->
        <setting name="logImpl" value="LOG4J"/>
    </settings>
    <typeAliases>
        <!--给某个类起别名,可以在Mapper.xml的select标签的参数类型和返回类型中使用该别名-->
        <!--<typeAlias type="com.bear.sxt.pojo.Emp" alias="emp"></typeAlias>-->
        <!--给某个包里面的所有类起别名,使用这些类时可以省略包名直接用类名-->
        <package name="com.bear.sxt.pojo"></package>
    </typeAliases>
    <environments default="test1">
        <!--environment中包含了连接数据库的基本信息-->
        <environment id="test1">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/user_infos?useUnicode=true&amp;characterEncoding=utf8&amp;useSSL=false&amp;serverTimezone=Hongkong"/>
                <property name="username" value="root"/>
                <property name="password" value="password"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <!--这里包含了定义了数据库操作的.xml配置文件-->
        <mapper resource="com/bear/sxt/mapper/empMapper.xml"></mapper>
        <!--使用getMapper形式的话需要写接口与mapper.xml文件所在的包-->
        <package name="com.bear.sxt.mapper"></package>
    </mappers>
</configuration>

2.3.编写Mapper.xml文件

使用MyBatis框架后,SQL语句并不是直接写在DAO层中的,而是写在“实体类名+Mapper.xml”文件中的,DAO层可以调用Mapper.xml中的SQL实现来进行数据库操作(通过namespace.id来调用)。

2.3.1.标签

  • select:查询
  • update:更新
  • insert:插入
  • delete:删除

P.S.MyBatis默认不会自动提交事务,所以更新、插入、删除操作需要手动提交事务。

2.3.2.标签中的属性

ResultType:返回值类型

可以是pojo对象、基本数据类型或者是map对象等。(更新、插入和删除三个标签由于返回值固定为所影响的行数,所以这些标签不用定义ResultType参数)

parameterType:参数类型

调用SQL语句的时候有时需要传入的参数,有两种使用传入参数的格式:#{}和${}。

  • #{},使用了占位符的方式(其底层为prepareStatement)

    • #{属性名}:如传入的是一个pojo对象,则会调用成员变量的get方法来获取值。
    • #{key}:如果传入的是一个map对象,则会通过key值获取相应的值。
    • #{index}:如果传入的是一个数组(或使用接口绑定的形式传入一系列的采参数),则可以通过索引值来表示调用第几个数。(index从0开始起算)
    • #{param1}:与#{index}类似,但采用param1、param2…来当作索引值。
    • #{whatever}:如果传入的是一个基本数据类型或者是一个String对象,则{}内写什么都行。
  • ${},使用了字符串拼接(其底层为Statement)

    • ${属性名}:同#{属性名}。
    • ${number}:若{}中为一个数字,则值为该数字本身。
<?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">
<!--namespace:实现类的全路径(调用SQL语句时,会使用com.bear.sxt.log.selectId进行调用)-->
<mapper namespace="com.bear.sxt.empMapper">
    <!--
    id:方法名
    parameterType:参数类型
    resultType:返回值类型(通过auto mapping的方式,匹配实体类中的set方法(字段名需要和实体类对应的属性名一致)或直接给属性赋值)
    -->
    <!--查询-->
    <select id="selectAll" resultType="com.bear.sxt.pojo.Emp">
        select * from emp
    </select>

    <!--插入,#{salary}会调用具体的get方法获取传入对象的成员变量-->
    <insert id="insertEmp" parameterType="com.bear.sxt.pojo.Emp">
        insert into emp (empname, salary, birthday, deptId, age)
        values (#{empname}, #{salary}, #{birthday}, #{deptId}, #{age});
    </insert>

    <!--更新-->
    <update id="updateEmpSalary" parameterType="map" >
        update emp set salary=#{salary} where id=#{id}
    </update>

    <!--删除-->
    <delete id="deleteEmp" parameterType="int">
        delete from emp where id=#{id}
    </delete>
</mapper>

2.4.编写相关业务逻辑

编写完mapper中的sql语句后即可编写相关的业务逻辑。因为mapper中只有sql语句,而与数据库连接,关闭数据库连接等操作是没有的,所以这写操作我都写在了dao层中。

2.4.1.编写工具类

public class MyBatisUtil {

    /*factory在实例化过程中是一个比较耗时的过程,所以在程序中保证只有一个factory*/
    private static SqlSessionFactory factory = null;
    /*采用threadLocal存储session-由于servlet->service->dao都是同一个线程的,所以采用ThreadLocal可以获取同一个session*/
    private static ThreadLocal<SqlSession> tl = new ThreadLocal<>();

    static {
        InputStream is = null;
        try {
            URL url = getClassLoader().getResource("myBatis.xml");
            if (null != url) {
                is = new FileInputStream(new File(url.getPath()));
                factory = new SqlSessionFactoryBuilder().build(is);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }finally {
            close(is);
        }
    }

    /**
     * 获取session
     * @return
     */
    public static SqlSession getSession() {
        SqlSession session = tl.get();
        if (null == session) {
            tl.set(factory.openSession());
        }
        return tl.get();
    }

    /**
     * 关闭session
     */
    public static void closeSession() {
        close(tl.get());
        tl.set(null);
    }

    /**
     * 关闭与数据库相关的资源
     * @param closeables    资源列表
     */
    public static void close(AutoCloseable... closeables) {
        try {
            for (AutoCloseable c : closeables) {
                if (null != c) {
                    c.close();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

2.4.2.调用Mapper中的sql语句

方法1
  • 通过“namespace.id”的方式调用Mapper中的sql语句。格式一般为:session.[select][delete][update][insert](“namespace.id”, parameter)。
  • 这种方式由于只能接收基本数据类型、pojo、map三种形式的参数,所以传递多个参数时要不用pojo,要不构建一个map放入多个参数。而且每次都要写“namespace.id”字符串,比较容易出错。
public List<Emp> selectPage(int pageNum, int pageSize) {
    SqlSession session = MyBatisUtil.getSession();
    List<Emp> list = new ArrayList<>();
    if (null != session) {
    	//构建参数map
        Map<String, Integer> map = new HashMap<>();
        map.put("pageStart", (pageNum - 1) * pageSize);
        map.put("pageSize", pageSize);
        //使用namespace.id调用mapper.xml中的sql语句
        list = session.selectList("com.bear.sxt.empMapper.selectPage", map);
        MyBatisUtil.closeSession();
    }
    return list;
}
方法2

为了解决方法一的弊端,可通过接口绑定的方式实现多参数传递。

  • 优点为:
    • 可使用“接口名.方法名”的方式来待用Mapper.xml中的sql语句。
    • 之前.xml文件中的标签只能定义一个参数(基本数据类型、pojo、map),当有多参数时需要构建pojo、map。现在可以直接在接口中定义多参数的方法,框架会自动构建map对象映射到.xml的sql语句中。所以.xml的标签中可以不写parameterType属性了。

  • 操作为:
  1. 在Mapper.xml所在的包中定义一个同名的接口,定义相应的抽象方法。
    mybatis的接口绑定
public interface TransferLogMapper {

    //使用这个模式时,.xml文件中引用参数需要用:#{0} #{1}...或#{param1} #{param2}...
    //List<TransferLog> selectPage(int pageStart, int pageSize);

    //使用这种模式时,.xml文件中引用参数需要用:#{自定义的参数名}
    //@Param("pageStart")中的字符串相当于key,形参相当于value
    List<TransferLog> selectPage(@Param("pageStart") int pageStart, @Param("pageSize") int pageSize);

    int count();

    int insertLog(TransferLog log);
}

2.在全局配置文件的mappers标签中使用package标签指明Mapper.xml与接口所在的包

<mappers>
    <!--使用getMapper形式的话需要写接口与mapper.xml文件所在的包-->
    <package name="com.bear.sxt.mapper"></package>
</mappers>

3.编写Mapper.xml文件
1)mapper标签中的namespace必须为同名接口的全限定路径(包名.类名)。
2)select、update、delete和insert标签中的id必须与同名接口中所定义的相应方法一一对应。

4.使用
使用session.getMapper(interface.class)方法获取接口的实现对象,然后调用其中的方法。

public int insertLog(TransferLog log) {
    SqlSession session = MyBatisUtil.getSession();
    int result = 0;
    if (null != session) {
        TransferLogMapper tlm = session.getMapper(TransferLogMapper.class);
        result = tlm.insertLog(log);
        session.commit();
        MyBatisUtil.closeSession();
    }
    return result;
}

2.4.3.关闭资源

session、io等用完了需要关闭,避免内存泄露。由于这些资源都实现了AutoCloseable接口,所以可以编写如下一个统一的方法进行关闭。

public static void close(AutoCloseable... closeables) {
    try {
        for (AutoCloseable c : closeables) {
            if (null != c) {
                c.close();
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

3.统一session的获取与关闭

  • 在上述代码中每次用完session都需要调用MyBatisUtil.closeSession()来进行关闭,为了简化该操作,可以在过滤器中统一session的关闭与获取。
  • 采用拦截器对所需请求进行拦截,拦截后自动获取session,完成了servlet中的逻辑后,再关闭session。由于MyBatisUtil中使用了ThreadLocal,而同一组的servlet、service和dao都是处于同一线程的,所以能获取到的session是一样的。
package com.bear.sxt.filter;

import com.bear.sxt.util.MyBatisUtil;
import org.apache.ibatis.session.SqlSession;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

@WebFilter("/*")
public class OpenSessionInView implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        SqlSession session = MyBatisUtil.getSession();
        try {
            //运行servlet中的内容
            filterChain.doFilter(servletRequest, servletResponse);
            session.commit();
        } catch (Exception e) {
            e.printStackTrace();
            session.rollback();
        }finally {
            MyBatisUtil.closeSession();
        }

    }

    @Override
    public void destroy() {

    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值