mybatis框架学习一(入门程序,以及配置文件)

本文详细介绍了MyBatis框架的起源、配置、测试方法及入门程序。MyBatis原为Apache项目iBatis,后迁移至Google Code并更名为MyBatis,现托管于Github。文章涵盖MyBatis与Hibernate的对比,配置文件解析,动态SQL应用,以及如何通过测试确保SQL语句正确执行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一,mybatis介绍

1,MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAOs)
2,MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Ordinary Java Object,普通的 Java对象)映射成数据库中的记录。
3,mabatis和hibernate的比较:mybatis是轻量级的半orm的持久层框架,hibernate是重量级的全orm框架;hibernate适用于需求变更不频繁的中小型框架,如后台管理系统等等,mybatis适用于需求变化较大的项目,如互联网项目

二,mybatis的配置文件:mybatis.xml,需要在这里加载mybatis运行环境,创建sqlsessionfactory(线程安全的,实际使用时用单例管理)工厂,用sqlsessionfactory创建的sqlsession是线程不安全的,一般在方法体中使用

1,properties(在mybatis.xml中加载属性文件)

注意: MyBatis 将按照下面的顺序来加载属性:
Ⅰ 在 properties 元素体内定义的属性首先被读取。
Ⅰ 然后会读取properties 元素中resource或 url 加载的属性,它会覆盖已读取的同名属性。
Ⅰ 最后读取parameterType传递的属性,它会覆盖已读取的同名属性。
因此,通过parameterType传递的属性具有最高优先级,resource或 url 加载的属性次之,最低优先级的是 properties 元素体内定义的属性。
Ⅰ 所以不建议在propertie标签下定义属性,在properties属性文件中的属性一定具有特殊性,如XXXXXXX.XXXXX

<!--加载属性文件-->
	<properties resource="db/db.properties">
	<!--在这里也可以配置属性-->
		<property name="" value=""></property>
	</properties>
	<environments default="development">
		<environment id="development">
			<transactionManager type="JDBC" />
			<!--数据源-->
			<dataSource type="POOLED">
				<property name="driver" value="${jdbc.driver}"/>
				<property name="url" value="${jdbc.url}" />
				<property name="username" value="${jdbc.username}" />
				<property name="password" value="${jdbc.password}" />
			</dataSource>
		</environment>
	</environments>
2,全局参数配置,会影响mybatis的运行行为
3,typeAliases(类型别名,mybatis默认支持一些别名)

Ⅰ在mapper的xml文件中有好多paramterType和resultType,每次要输入全名,不方便开发

<!--别名定义-->
	<typeAliases>
		<!--单个别名定义-->
		<!--<typeAlias type="com.study.bean.Goods" alias="goods"></typeAlias>-->
		<!--批量别名定义
		指定一个包名:mybatis就会自动扫描包名下的pojo,定义别名,别名就是类名,首字母可大写可小写
		-->
		<package name="com.study.bean"></package>
	</typeAliases>

使用:

<select id="selectGoodsById" parameterType="int" resultType="goods">
        SELECT * FROM goods WHERE id=#{id}
    </select>
4,typeHandlers(类型处理器)

mybatis通过typeHandlers类型处理器用于java类型和jdbc类型映射
通常mybatis所自带的类型处理器已经满足日常需要,不需要再额外定义

4,mappers(映射配置)

Mapper配置的几种方法:
1

<mapper resource=" " />

使用相对于类路径的资源
如:<mapper resource="sqlmap/User.xml" />

2

<mapper url=" " />

使用完全限定路径
如:<mapper url="file:///D:\workspace_spingmvc\mybatis_01\config\sqlmap\User.xml" />

3

<mapper class=" " />

使用mapper接口类路径
如:<mapper class="com.study.mapper.UsersMapper"/>
注意:此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。
4

<package name=""/>

注册指定包下的所有mapper接口(批量加载)
如:
注意:此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。

三,mybatis测试需要根据log4j在后台打印sql语句去测试(log4j.properties)

log4j.properties

#开发环境设置成debug
log4j.rootLogger=debug,stdout
log4j.additivity.org.apache=true
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
log4j.appender.Console.Threshold=trace
#log4j.logger.org.hibernate.hql.ast.AST=debug
###log just the SQL
log4j.logger.org.hibernate.SQL=info
###log JDBC bind parameters ###
log4j.logger.org.hibernate.type=trace
#log4j.logger.org.hibernate.type=debug
###log schema export/update ###
log4j.logger.org.hibernate.tool.hbm2ddl=debug

三,mybatis入门程序以及测试(这里直接上mapper代理的方式,原始dao的开发方法就不写了)

1,实体类

package com.study.bean;
import java.io.Serializable;
public class Goods implements Serializable{
    private Integer id;
    private String goodsname;
    private String godsfullname;
    private Integer num;
    private Integer typeid;

    public Goods() {
        super();
    }

    public Goods(Integer id, String goodsname, String godsfullname, Integer num, Integer typeid) {
        this.id = id;
        this.goodsname = goodsname;
        this.godsfullname = godsfullname;
        this.num = num;
        this.typeid = typeid;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getGoodsname() {
        return goodsname;
    }

    public void setGoodsname(String goodsname) {
        this.goodsname = goodsname;
    }

    public String getGodsfullname() {
        return godsfullname;
    }

    public void setGodsfullname(String godsfullname) {
        this.godsfullname = godsfullname;
    }

    public Integer getNum() {
        return num;
    }

    public void setNum(Integer num) {
        this.num = num;
    }

    public Integer getTypeid() {
        return typeid;
    }

    public void setTypeid(Integer typeid) {
        this.typeid = typeid;
    }
}

2,mapper接口

package com.study.mapper;
import com.study.bean.Goods;
import java.util.List;
public interface GoodsMapper {
//    提供调用方法,在xml中实现
    /**
     * mybatis中查询一般select开头,其他的update,insert,delete开头
     *但是不是必须的
     * mapper接口中方法参数只能为一个,可以使用包装类型
     *
     * */
    public Goods selectGoodsById(Integer id);
    public List<Goods> selectGoodsByName(String name);
    public void insertGoods(Goods goods);
    public void deleteGoods(Integer id);
    public void updateGoods(Goods goods);
}

3,实现在mapper的xml文件(GoodsMapper.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">
<!-- <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd"> -->

<!--通过接口调用xml中的方法
-->
<mapper namespace="com.study.mapper.GoodsMapper">
    <!--select查询标签,id为实现方法,将sql语句封装到mappedStatement对象中,所以id称为Statement的id
    parameterType为参数名称,resultType指定输出结果单挑记录映射的java类型(单挑多条都可以写com.study.bean.Goods)-->
    <!--
        里面写sql语句
        #{}代表一个占位,防止sql注入
        ${} 表示拼接字符串,将字符串不加任何修饰的拼接在sql中,可能会有sql注入
        ${value}:接收输入参数的名称,若传入类型为简单类型则只能使用value
        -->
    <select id="selectGoodsById" parameterType="int" resultType="com.study.bean.Goods">
        SELECT * FROM goods WHERE id=#{id}
    </select>
    <select id="selectGoodsByName" parameterType="java.lang.String" resultType="com.study.bean.Goods">
        SELECT * FROM goods WHERE goodsname LIKE '%${value}%';
    </select>
    <!--添加用户
    参数类型parameterType为pojo
    #{}指定pojo的属性名,接受到pojo对象的属性值,mybatis也是ognl获取对象的属性值
    -->
    <!--selectKey将插入的主键返回到goods对象中
        SELECT LAST_INSERT_ID()获取刚刚插入数据的主键,只适用于自增主键
        keyProperty:将查询到的主键值设置在parameterType的哪个属性
        order:SELECT LAST_INSERT_ID()相对于insert语句的执行顺序
    -->
    <insert id="insertGoods" parameterType="com.study.bean.Goods" >
        <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
            SELECT LAST_INSERT_ID()
        </selectKey>
        INSERT INTO goods (goodsname,godsfullname,num,typeid) VALUES (#{goodsname},#{godsfullname},#{num},#{typeid})
    </insert>
    <!--非自增主键的获取方法
    使用mysql的uuid()来生成主键
    执行过程:首先通过uuid生成主键,将主键放在对象的id中
    在select语句执行时,通过getId获取对象中的id
    -->
    <!--<insert id="insertGoods" parameterType="com.study.bean.Goods" >
        <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
            SELECT uuid()
        </selectKey>
        INSERT INTO goods (id,goodsname,godsfullname,num,typeid) VALUES (#{id},#{goodsname},#{godsfullname},#{num},#{typeid})
    </insert>-->
    <!--删除-->
	<delete id="deleteGoods" parameterType="int">
        DELETE FROM goods WHERE id=#{id}
    </delete>
    <!--根据id更新
    id值必须存在
    -->
    <update id="updateGoods" parameterType="com.study.bean.Goods">
        UPDATE goods SET godsfullname=#{godsfullname},num=#{num},typeid=#{typeid},goodsname=#{goodsname} WHERE id=#{id}
    </update>
</mapper>

4,测试

package com.study.test;
import com.study.bean.Goods;
import com.study.mapper.GoodsMapper;
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 java.io.IOException;
import java.io.Reader;
import java.util.List;
/**
 * @author: Demon
 * @date: 2019/2/11
 * @time: 21:04
 * Description:
 */
public class RunTest {
    public static void main(String[] args) throws IOException{
//        手动加载mybatis配置
        String resource = "mybatis.xml";
        Reader reader = Resources.getResourceAsReader(resource);
//        创建会话工厂SqlSessionFactory,传入mybatis的配置问价信息
        SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(reader);
//        获取sqlSession
        SqlSession sqlSession = ssf.openSession();
//        获得接口对象实例
        GoodsMapper goodsMapper=sqlSession.getMapper(GoodsMapper.class);
        /*Goods goods=goodsMapper.selectGoodsById(1);
        System.out.println(goods.getGodsfullname());*/
        /*List<Goods> list=goodsMapper.selectGoodsByName("包");
        for (Goods goods:list){
            System.out.println(goods.getGoodsname());
        }*/
//      添加
       /* Goods goods=new Goods();
        goods.setGoodsname("卫龙");
        goods.setGodsfullname("中国卫龙");
        goods.setNum(13);
        goods.setTypeid(1);
        goodsMapper.insertGoods(goods);
        System.out.println(goods.getId());*/
//       删除
        /*goodsMapper.deleteGoods(10);*/
//        更新
        Goods goods=new Goods();
        goods.setId(5);
        goods.setGoodsname("卫龙");
        goods.setGodsfullname("中国卫龙");
        goods.setNum(13);
        goods.setTypeid(1);
        goodsMapper.updateGoods(goods);
        sqlSession.commit();
        sqlSession.close();
    }
}

四,parameterType和resultType

1,parameterType

开发中有时会用到pojo传递查询条件,查询条件是综合的,不仅包括闪商品查询条件,还包括其他查询条件,这是可以使用包装pojo传递参数
1,定义包装对象
goods:

package com.study.bean;
import java.io.Serializable;
public class Goods implements Serializable{
    private Integer id;
    private String goodsname;
    private String godsfullname;
    private Integer num;
    private Integer typeid;

    public Goods() {
        super();
    }

    public Goods(Integer id, String goodsname, String godsfullname, Integer num, Integer typeid) {
        this.id = id;
        this.goodsname = goodsname;
        this.godsfullname = godsfullname;
        this.num = num;
        this.typeid = typeid;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getGoodsname() {
        return goodsname;
    }

    public void setGoodsname(String goodsname) {
        this.goodsname = goodsname;
    }

    public String getGodsfullname() {
        return godsfullname;
    }

    public void setGodsfullname(String godsfullname) {
        this.godsfullname = godsfullname;
    }

    public Integer getNum() {
        return num;
    }

    public void setNum(Integer num) {
        this.num = num;
    }

    public Integer getTypeid() {
        return typeid;
    }

    public void setTypeid(Integer typeid) {
        this.typeid = typeid;
    }
}

GoodsUser

package com.study.bean;
public class GoodsUser extends Goods{
}

GoodsQueryVo(包装类型)

package com.study.bean;
public class GoodsQueryVo {
//    包装类型,里面写查询条件
    private GoodsUser goodsUser;

    public GoodsUser getGoodsUser() {
        return goodsUser;
    }

    public void setGoodsUser(GoodsUser goodsUser) {
        this.goodsUser = goodsUser;
    }
}

2,mapper文件和mapper.xml映射文件中:

public List<GoodsUser> selectGoodsList(GoodsQueryVo goodsQueryVo);
<!--用户综合查询-->
    <select id="selectGoodsList" parameterType="GoodsQueryVo" resultType="GoodsUser">
        SELECT * FROM goods where goodsname= #{goodsUser.goodsname} and godsfullname like '%${goodsUser.godsfullname}%'
    </select>

说明:mybatis底层通过ognl从pojo中获取属性值:#{goodsUser.goodsname},goodsUser即是传入的包装对象的属性。queryVo是别名,即上边定义的包装对象类型。

2,resultType和resultMap
resultType:

使用resultType进行输出映射,只有查询出来的列名和pojo中的属性名一致,该列才可以映射成功。
如果查询出来的列名和pojo中的属性名全部不一致,没有创建pojo对象。
只要查询出来的列名和pojo中的属性有一个一致,就会创建pojo对象。

1,输出简单类型:查询出来的结果集只有一行且一列,可以使用简单类型进行输出映射。
2,pojo对象或pojo列表
不管是输出的pojo单个对象还是一个列表(list中包括pojo),在mapper.xml中resultType指定的类型是一样的。
生成的动态代理对象中是根据mapper方法的返回值类型确定是调用selectOne(返回单个对象调用)还是selectList (返回集合对象调用 ).

resultMap:

mybatis中使用resultMap完成高级输出结果映射。
如果查询出来的列名和pojo的属性名不一致,通过定义一个resultMap对列名和pojo属性名之间作一个映射关系。
1、定义resultMap

<!--定义resultMap,输出的结果和对象中的属性名不一致的时候使用
    如果此resulMap在其他的xml中,需要加namespace
    type:resultMap最终映射的java对象类型,可以使用别名
    id:唯一标识
    -->
    <resultMap id="goodsResultMap" type="Goods">
        <!--
        id:查询结果集中的唯一标识
        column:查询出来的列名
        property:type指定pojo类型的最终属性名
        -->
        <id column="id_" property="id"/>
        <!--
        result:对普通列的定义
        -->
        <result column="goodsname_" property="goodsname"/>
    </resultMap>

2、使用resultMap作为statement的输出映射类型

<!--resultMap使用:-->
    <select id="findResultMap" parameterType="int" resultMap="goodsResultMap">
        SELECT id id_,goodsname goodsname_ from goods WHERE id=#{id}
    </select>

五,动态sql和sql片段

mybatis核心 对sql语句进行灵活操作,通过表达式进行判断,对sql进行灵活拼接、组装。

1,动态sql(用类似if的标签可以判断是否为空,若为空不进行拼接)
<!--用户综合查询-->
    <select id="selectGoodsList" parameterType="GoodsQueryVo" resultType="GoodsUser">
        SELECT * FROM goods
        <!--where可以自动去掉第一个查询语句中的and-->
        <where>
            <if test="goodsUser!=null">
                <if test="goodsUser.goodsname!=null and goodsUser.goodsname!=''">
                    and goodsname= #{goodsUser.goodsname}
                </if>
                <if test="goodsUser.godsfullname!=null and goodsUser.godsfullname!=''">
                    and godsfullname like '%${goodsUser.godsfullname}%'
                </if>
            </if>
        </where>
    </select>
2,sql片段

将上边实现的动态sql判断代码块抽取出来,组成一个sql片段。其它的statement中就可以引用sql片段。
方便程序员进行开发。

<!--定义sql片段
    id:为sql片段的唯一标识
    基于单表来定义sql片段,这样sql片段的可重用行才高-->
    <sql id="query_goods_where">
        <if test="goodsUser!=null">
            <if test="goodsUser.goodsname!=null and goodsUser.goodsname!=''">
                and goodsname= #{goodsUser.goodsname}
            </if>
            <if test="goodsUser.godsfullname!=null and goodsUser.godsfullname!=''">
                and godsfullname like '%${goodsUser.godsfullname}%'
            </if>
        </if>
    </sql>
    <!--sql片段使用-->
    <select id="selectGoodsList" parameterType="GoodsQueryVo" resultType="GoodsUser">
        SELECT * FROM goods
        <where>
            <!--引用sql 片段,如果sql片段不在本mapper中,则加入namespace-->
            <include refid="query_goods_where"></include>
            <!--这里可以加入其他的引用-->
        </where>
    </select>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值