ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

MyBatis

2022-01-04 15:02:55  阅读:148  来源: 互联网

标签:语句 category goods 映射 MyBatis id select


MyBatis

MyBatis环境配置

maven配置

pom.xml:

<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis</artifactId>
  <version>x.x.x</version>
</dependency>

mybatis-congig.xml

XML 配置文件中包含了对 MyBatis 系统的核心设置,包括获取数据库连接实例的数据源(DataSource)以及决定事务作用域和控制方式的事务管理器(TransactionManager)。

image-20211224200647982

mybatis-config.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>
    <!--驼峰命名转换-->
    <settings>
        <!--goods_id ==> goodsId-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
    <!--设置默认指向的数据库-->
  <environments default="development">
      <!--配置环境,不同的环境不同的id名字-->
    <environment id="development">
        <!--采用JDBC方式对数据库事务进行commit/roolback-->
      <transactionManager type="JDBC"/>
        <!--采用连接池方式管理数据库连接-->
      <dataSource type="POOLED">
          <!--配置数据库连接驱动-->
        <property name="driver" value="${driver}"/>
          <!--配置数据库地址-->
        <property name="url" value="${url}"/>
          <!--数据库用户名-->
        <property name="username" value="${username}"/>
          <!--数据库密码-->
        <property name="password" value="${password}"/>
      </dataSource>
    </environment>
  </environments>
    <mappers>
        <mapper resource="{映射sql语句的xml文件路径}"/>
    </mappers>
</configuration>

SqlSessionFactory

SqlSessionFactory

SqlSessionFactory是MyBatis的核心对象

用于初始化MyBatis,创建SqlSession对象

保证SqlSessionFactory在应用中全局唯一

SqlSession

SqlSession是MyBatis操作数据库的核心对象

SqlSession使用JDBC方式与数据库交互

SqlSession对象提供了数据表CRUD对应方法

MyBatisUtils包装类

package com.imooc.mybatis.utils;

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;

/**
 * MyBatisUtils工具类,创建全局唯一的SqlSessionFactory对象
 */
public class MyBatisUtils {
    //利用static属性类不属于对象,且全局唯一
    private static SqlSessionFactory sqlSessionFactory=null;
    //利用静态块在初始类时实例化sqlSessionFactory
    static{
        try {
            Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
            sqlSessionFactory=new SqlSessionFactoryBuilder().build(reader);
        } catch (IOException e) {
            e.printStackTrace();
            //初始化错误时,通过抛出异常通知调用者
            throw new ExceptionInInitializerError(e);
        }
    }

    /**
     * openSession创建一个新的SqlSession对象
     * @return SqlSession对象
     */
    public static SqlSession openSession(){
        return sqlSessionFactory.openSession();
    }

    /**
     * 释放一个有效的SqlSession对象
     * @param session 准备释放SqlSession对象
     */
    public static void closeSession(SqlSession session){
        if(session!=null){
            session.close();
        }
    }
}

SQL语句的映射

<?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="org.mybatis.example.BlogMapper">
  <select id="selectBlog" resultType="Blog">
    select * from Blog where id = #{id}
  </select>
</mapper>

在一个 XML 映射文件中,可以定义无数个映射语句,这样一来,XML 头部和文档类型声明部分就显得微不足道了。文档的其它部分很直白,容易理解。 它在命名空间 “org.mybatis.example.BlogMapper” 中定义了一个名为 “selectBlog” 的映射语句,这样你就可以用全限定名 “org.mybatis.example.BlogMapper.selectBlog” 来调用映射语句了,就像上面例子中那样:

Blog blog =(Blog)session.selectOne("org.mybatis.example.BlogMapper.selectBlog", 101);

名字空间

命名空间的作用有两个,一个是利用更长的全限定名来将不同的语句隔离开来,同时也实现了你上面见到的接口绑定。就算你觉得暂时用不到接口绑定,你也应该遵循这里的规定,以防哪天你改变了主意。 长远来看,只要将命名空间置于合适的 Java 包命名空间之中,你的代码会变得更加整洁,也有利于你更方便地使用 MyBatis。

命名解析:为了减少输入量,MyBatis 对所有具有名称的配置元素(包括语句,结果映射,缓存等)使用了如下的命名解析规则。

  • 全限定名(比如 “com.mypackage.MyMapper.selectAllThings)将被直接用于查找及使用。
  • 短名称(比如 “selectAllThings”)如果全局唯一也可以作为一个单独的引用。 如果不唯一,有两个或两个以上的相同名称(比如 “com.foo.selectAllThings” 和 “com.bar.selectAllThings”),那么使用时就会产生“短名称不唯一”的错误,这种情况下就必须使用全限定名。

作用域和生命周期

SqlSessionFactoryBuilder

这个类可以被实例化、使用和丢弃,一旦创建了 SqlSessionFactory,就不再需要它了。 因此 SqlSessionFactoryBuilder 实例的最佳作用域是方法作用域(也就是局部方法变量)。 你可以重用 SqlSessionFactoryBuilder 来创建多个 SqlSessionFactory 实例,但最好还是不要一直保留着它,以保证所有的 XML 解析资源可以被释放给更重要的事情。

SqlSessionFactory

SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例。 使用 SqlSessionFactory 的最佳实践是在应用运行期间不要重复创建多次,多次重建 SqlSessionFactory 被视为一种代码“坏习惯”。因此 SqlSessionFactory 的最佳作用域是应用作用域。 有很多方法可以做到,最简单的就是使用单例模式或者静态单例模式。

SqlSession

每个线程都应该有它自己的 SqlSession 实例。SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。 绝对不能将 SqlSession 实例的引用放在一个类的静态域,甚至一个类的实例变量也不行。 也绝不能将 SqlSession 实例的引用放在任何类型的托管作用域中,比如 Servlet 框架中的 HttpSession。 如果你现在正在使用一种 Web 框架,考虑将 SqlSession 放在一个和 HTTP 请求相似的作用域中。 换句话说,每次收到 HTTP 请求,就可以打开一个 SqlSession,返回一个响应后,就关闭它。 这个关闭操作很重要,为了确保每次都能执行关闭操作,你应该把这个关闭操作放到 finally 块中。

try{
	//逻辑代码
}catch(){
}finally{
	关闭SqlSession连接
}

映射器

mybatis-config.xml

mappers标签里面保存映射的xml文件

<!-- 使用相对于类路径的资源引用 -->
<mappers>
        <mapper resource="文件.xml"/>
</mappers>

这些配置会告诉 MyBatis 去哪里找映射文件,剩下的细节就应该是每个 SQL 映射文件了

映射文件

在mapper标签里面写要处理的sql语句

分别由select、insert、update、delete标签

<?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="goods">
    <select id="selectAll" resultType="com.imooc.mybatis.entity.Goods">
        select * from t_goods order by goods_id desc limit 10
    </select>
    <!--单参数传参,使用parameterType指定参数的数据类型即可,SQL中#{value}提取参数-->
    <select id="selectById" parameterType="Integer" resultType="com.imooc.mybatis.entity.Goods">
        select * from t_goods where goods_id=#{value}
    </select>
    <!--多参数传参时,使用parameterType指定Map接口,SQL中#{key}提取参数-->
    <select id="selectByPriceRange" parameterType="java.util.Map" resultType="com.imooc.mybatis.entity.Goods">
        select * from t_goods where current_price between #{min} and #{max} order by current_price limit 0,#{limit}
    </select>
<!--    利用LinkedHashMap保存多表关联结果
        MyBatis会将每一条记录包装为LinkedHashMap对象
        key是字段名 value是字段对应的值,字段类型根据表结构进行自动判断
        优点:易于扩展,易于使用
        缺点:太过灵活,无法进行编译时检查
-->
    <select id="selectGoodsMap" resultType="java.util.LinkedHashMap">
        select g.*,c.category_name,'1' as test from t_goods g,t_category c where g.category_id=c.category_id
    </select>
<!--    结果映射-->
    <resultMap id="rmGoods" type="com.imooc.mybatis.dto.GoodsDTO">
<!--        设置主键字段与属性映射-->
        <id property="goods.goodsId" column="goods_id"></id>
<!--        设置非主键字段与属性映射-->
        <result property="goods.title" column="title"></result>
        <result property="goods.originalCost" column="original_cost"></result>
        <result property="goods.currentPrice" column="current_price"></result>
        <result property="goods.discount" column="discount"></result>
        <result property="goods.isFreeDelivery" column="is_free_delivery"></result>
        <result property="goods.categoryId" column="category_id"></result>
        <result property="categoryName" column="category_name"></result>
        <result property="test" column="test"></result>
    </resultMap>
    <select id="selectGoodsDTO" resultMap="rmGoods">
        select g.*,c.category_name,'1' as test from t_goods g,t_category c where g.category_id=c.category_id
    </select>
    <insert id="insert" parameterType="com.imooc.mybatis.entity.Goods">
        insert into t_goods (title,sub_title,original_cost,current_price,discount,is_free_delivery,category_id)
        values(#{title},#{subTitle},#{originalCost},#{currentPrice},#{discount},#{isFreeDelivery},#{categoryId})
        <!--帮助主键回添-->
        <selectKey resultType="Integer" keyProperty="goodsId" order="AFTER">
            select last_insert_id()
        </selectKey>
    </insert>
    <update id="update" parameterType="com.imooc.mybatis.entity.Goods">
        update t_goods set title=#{title},
                           sub_title=#{subTitle},
                           original_cost=#{originalCost},
                           current_price=#{currentPrice},
                           discount=#{discount},
                           is_free_delivery=#{isFreeDelivery},
                           category_id=#{goodsId}
        where goods_id=#{goodsId}
    </update>
    <delete id="delete" parameterType="Integer">
        delete from t_goods where goods_id=#{value}
    </delete>
</mapper>

XML映射器

SQL 映射文件只有很少的几个顶级元素(按照应被定义的顺序列出):

  • cache – 该命名空间的缓存配置。
  • cache-ref – 引用其它命名空间的缓存配置。
  • resultMap – 描述如何从数据库结果集中加载对象,是最复杂也是最强大的元素。
  • parameterMap – 老式风格的参数映射。此元素已被废弃,并可能在将来被移除!请使用行内参数映射。文档中不会介绍此元素。
  • sql – 可被其它语句引用的可重用语句块。
  • insert – 映射插入语句。
  • update – 映射更新语句。
  • delete – 映射删除语句。
  • select – 映射查询语句。

select

查询语句是 MyBatis 中最常用的元素之一——光能把数据存到数据库中价值并不大,还要能重新取出来才有用,多数应用也都是查询比修改要频繁。 MyBatis 的基本原则之一是:在每个插入、更新或删除操作之间,通常会执行多个查询操作。因此,MyBatis 在查询和结果映射做了相当多的改进。

无参数形式的select映射语句:
<mapper namespace="goods">
	 <!--无参数形式的select语句映射-->
    <select id="selectAll" resultType="com.imooc.mybatis.entity.Goods">
        select * from t_goods order by goods_id desc limit 10
    </select>
</mapper>
单参数形式的select语句:
<mapper namespace="goods">
	 <select id="selectById" parameterType="Integer" resultType="com.imooc.mybatis.entity.Goods">
    	select * from t_goods where goods_id=#{value}
    </select>
</mapper>

单参数传参,使用parameterType指定参数的数据类型即可,SQL中#{value}提取参数,其中#{value}是固定的写法

多参数形式的select映射语句
<mapper namespace="goods">
	 <select id="selectById" parameterType="java.util.Map" resultType="com.imooc.mybatis.entity.Goods">
    	select * from t_goods where current_price between #{min} and #{max} 
         order by current_price limit 0,#{limit}
    </select>
</mapper>

多参数传参时,使用parameterType指定Map接口,SQL中#{key}提取参数 ,此案例中Map容器中存有max和min两个键值对,sql中提取参数分别使用#{max}和#{min}来分别提取响应的参数

多表关联查询结果
<mapper namespace="goods">
	 <select id="selectGoodsMap" resultType="java.util.LinkedHashMap">
        select g.*,c.category_name,'1' as test from t_goods g,t_category c where g.category_id=c.category_id
    </select>
</mapper>

​ 利用LinkedHashMap保存多表关联结果
​ MyBatis会将每一条记录包装为LinkedHashMap对象
​ key是字段名 value是字段对应的值,字段类型根据表结构进行自动判断
​ 优点:易于扩展,易于使用
​ 缺点:太过灵活,无法进行编译时检查

select标签的参数以及含义

id:名字空间中唯一的标识符,可以被用来引用这条语句。

resultType:期望从这条语句中返回结果的类全限定名或别名。 注意,如果返回的是集合,那应该设置为集合包含的类型,而不是集合本身的类型。 resultType 和 resultMap 之间只能同时使用一个。

parameterType:将会传入这条语句的参数的类全限定名或别名。这个属性是可选的,因为 MyBatis 可以通过类型处理器(TypeHandler)推断出具体传入语句的参数,默认值为未设置(unset)。

resultMap:对外部 resultMap 的命名引用。结果映射是 MyBatis 最强大的特性,如果你对其理解透彻,许多复杂的映射问题都能迎刃而解。 resultType 和 resultMap 之间只能同时使用一个。

结果映射

resultMap 元素是 MyBatis 中最重要最强大的元素。它可以让你从 90% 的 JDBC ResultSets 数据提取代码中解放出来,并在一些情形下允许你进行一些 JDBC 不支持的操作。实际上,在为一些比如连接的复杂语句编写映射代码的时候,一份 resultMap 能够代替实现同等功能的数千行代码。ResultMap 的设计思想是,对简单的语句做到零配置,对于复杂一点的语句,只需要描述语句之间的关系就行了。

<mapper namespcae="goods">
<!--    结果映射-->
    <resultMap id="rmGoods" type="com.imooc.mybatis.dto.GoodsDTO">
<!--        设置主键字段与属性映射-->
        <id property="goods.goodsId" column="goods_id"></id>
<!--        设置非主键字段与属性映射-->
        <result property="goods.title" column="title"></result>
        <result property="goods.originalCost" column="original_cost"></result>
        <result property="goods.currentPrice" column="current_price"></result>
        <result property="goods.discount" column="discount"></result>
        <result property="goods.isFreeDelivery" column="is_free_delivery"></result>
        <result property="goods.categoryId" column="category_id"></result>
        <result property="categoryName" column="category_name"></result>
        <result property="test" column="test"></result>
    </resultMap>
    <select id="selectGoodsDTO" resultMap="rmGoods">
        select g.*,c.category_name,'1' as test from t_goods g,t_category c where g.category_id=c.category_id
    </select>
</mapper>
resultMap的属性:

id:当前命名空间中的一个唯一标识,用于标识一个结果映射。

type:类的完全限定名, 或者一个类型别名(关于内置的类型别名,可以参考上面的表格)。

id&result

这些元素是结果映射的基础。idresult 元素都将一个列的值映射到一个简单数据类型(String, int, double, Date 等)的属性或字段。

这两者之间的唯一不同是,id 元素对应的属性会被标记为对象的标识符,在比较对象实例时使用。 这样可以提高整体的性能,尤其是进行缓存和嵌套结果映射(也就是连接映射)的时候。

id和result的属性:

property:映射到列结果的字段或属性。如果 JavaBean 有这个名字的属性(property),会先使用该属性。否则 MyBatis 将会寻找给定名称的字段(field)。 无论是哪一种情形,你都可以使用常见的点式分隔形式进行复杂属性导航。 比如,你可以这样映射一些简单的东西:“username”,或者映射到一些复杂的东西上:“address.street.number”。

column:数据库中的列名,或者是列的别名。一般情况下,这和传递给 resultSet.getString(columnName) 方法的参数一样。

insert、update、delete

数据变更语句 insert,update 和 delete 的实现非常接近

<mapper namespcae="goods">
	 <insert id="insert" parameterType="com.imooc.mybatis.entity.Goods">
        insert into t_goods (title,sub_title,original_cost,current_price,discount,is_free_delivery,category_id)
        values(#{title},#{subTitle},#{originalCost},#{currentPrice},#{discount},#{isFreeDelivery},#{categoryId})
        <!--帮助主键回添-->
        <selectKey resultType="Integer" keyProperty="goodsId" order="AFTER">
            select last_insert_id()
        </selectKey>
    </insert>
    <update id="update" parameterType="com.imooc.mybatis.entity.Goods">
        update t_goods set title=#{title},
                           sub_title=#{subTitle},
                           original_cost=#{originalCost},
                           current_price=#{currentPrice},
                           discount=#{discount},
                           is_free_delivery=#{isFreeDelivery},
                           category_id=#{goodsId}
        where goods_id=#{goodsId}
    </update>
    <delete id="delete" parameterType="Integer">
        delete from t_goods where goods_id=#{value}
    </delete>
</mapper>
insert、update、delete元素的属性:

id:名字空间中唯一的标识符,可以被用来引用这条语句。

parameterType:将会传入这条语句的参数的类全限定名或别名。这个属性是可选的,因为 MyBatis 可以通过类型处理器(TypeHandler)推断出具体传入语句的参数,默认值为未设置(unset)。

useGeneratedKeys:(仅适用于 insert 和 update)这会令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法来取出由数据库内部生成的主键(比如:像 MySQL 和 SQL Server 这样的关系型数据库管理系统的自动递增字段),默认值:false。

keyProperty:(仅适用于 insert 和 update)指定能够唯一识别对象的属性,MyBatis 会使用 getGeneratedKeys 的返回值或 insert 语句的 selectKey 子元素设置它的值,默认值:未设置(unset)。如果生成列不止一个,可以用逗号分隔多个属性名称。

keyColumn:(仅适用于 insert 和 update)设置生成键值在表中的列名,在某些数据库(像 PostgreSQL)中,当主键列不是表中的第一列的时候,是必须设置的。如果生成列不止一个,可以用逗号分隔多个属性名称。

自动生成主键的字段

如果你的数据库支持自动生成主键的字段(比如 MySQL 和 SQL Server),那么你可以设置 useGeneratedKeys=”true”,然后再把 keyProperty 设置为目标属性就 OK 了,例如, Author 表已经在 id 列上使用了自动生成,那么语句可以修改为:

<insert id="insertAuthor" useGeneratedKeys="true"
    keyProperty="id">
  insert into Author (username,password,email,bio)
  values (#{username},#{password},#{email},#{bio})
</insert>

如果你的数据库还支持多行插入, 你也可以传入一个 Author 数组或集合,并返回自动生成的主键。

<insert id="insertAuthor" useGeneratedKeys="true"
    keyProperty="id">
  insert into Author (username, password, email, bio) values
  <foreach item="item" collection="list" separator=",">
    (#{item.username}, #{item.password}, #{item.email}, #{item.bio})
  </foreach>
</insert>

或下面这种方法,

<insert id="insert" parameterType="com.imooc.mybatis.entity.Goods">
        insert into t_goods (title,sub_title,original_cost,current_price,discount,is_free_delivery,category_id)
        values(#{title},#{subTitle},#{originalCost},#{currentPrice},#{discount},#{isFreeDelivery},#{categoryId})
        <!--帮助主键回添-->
        <selectKey resultType="Integer" keyProperty="goodsId" order="AFTER">
            select last_insert_id()
        </selectKey>
    </insert>

在进行sql语句执行完成之后,执行selectkey,把主键添加到Goods类的goodsId属性中

此方法还可以用于不支持自动生成主键列的数据库和可能不支持自动生成主键的 JDBC 驱动。

标签:语句,category,goods,映射,MyBatis,id,select
来源: https://www.cnblogs.com/Anesthesi/p/15762503.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有