Intro to Mybatis

motivation for using mybatis

前几天刚学完 JDBC, JDBC 允许我们使用 Java 代码来对数据库进行操作, 然而使用的时候数据库连接信息和 SQL 语句都是硬编码在 Java 代码中的,比较死板,同时要手动设置参数,用 ResultSet 接受返回结果后再自己处理,封装对象,当属性多的时候非常繁琐。使用 MyBatis 解决了上面的这两个问题,MyBatis 将数据库连接信息和 SQL 语句放在了配置文件中,同时可以自动完成结果封装的工作。

sqlSession

每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为核心的。SqlSessionFactory 的实例可以通过 SqlSessionFactoryBuilder 获得。而 SqlSessionFactoryBuilder 则可以从 XML 配置文件或一个预先配置的 Configuration 实例来构建出 SqlSessionFactory 实例。
下面是示例代码,从 xml 配置文件中构建一个 sqlSessionFactory.

String resource = "path/to/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

要用 sqlSessionFactory 开启一个 sqlSession:

try (SqlSession session = sqlSessionFactory.openSession()) {
  //using the session
}

mybatis xml 配置文件

上面提到了要使用 sqlSession 需要先编写一个 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>
  <environments default="development">
    <environment id="development">
      <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="org/mybatis/example/BlogMapper.xml"/>
  </mappers>
</configuration>

给出了一些比较常用的信息的填写, environments 里面配置了环境信息,之前再 JDBC 中使用的数据库连接信息就填写在这里,而 mappers 给出了 sql 语句映射文件的信息。
其中 mappers 除了可以以这种方式,即文件路径来指明,也可以使用其对应的 Mapper 接口的全限定名(如果使用 Mapper 代理的方式的话)。
另一个比较常用的是 typeAliases, 用来定义别名。类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写。例如:

<typeAliases>
  <typeAlias alias="Author" type="domain.blog.Author"/>
  <typeAlias alias="Blog" type="domain.blog.Blog"/>
  <typeAlias alias="Comment" type="domain.blog.Comment"/>
  <typeAlias alias="Post" type="domain.blog.Post"/>
  <typeAlias alias="Section" type="domain.blog.Section"/>
  <typeAlias alias="Tag" type="domain.blog.Tag"/>
</typeAliases>

当这样配置时,Blog 可以用在任何使用 domain.blog.Blog 的地方。

也可以指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean,比如

<typeAliases>
  <package name="domain.blog"/>
</typeAliases>

xml 映射文件

MyBatis 的真正强大在于它的语句映射,这是它的魔力所在。由于它的异常强大,映射器的 XML 文件就显得相对简单。如果拿它跟具有相同功能的 JDBC 代码进行对比,你会立即发现省掉了将近 95% 的代码。MyBatis 致力于减少使用成本,让用户能更专注于 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 映射文件的编写例子。其中 mapper namespace 指明了这个 mapper 的名空间,在使用 mapper 代理开发的时候需要和对应接口的全限定名称相同。下面的 select 标签将 id 和 sql 语句之间建立映射,可以在 Java 代码中通过这个 id 来调用这个 sql 语句。就像下面这样

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

你可能会注意到,这种方式和用全限定名调用 Java 对象的方法类似。这样,该命名就可以直接映射到在命名空间中同名的映射器接口,并将已映射的 select 语句匹配到对应名称、参数和返回类型的方法。因此你就可以像上面那样,轻松地在对应的映射器接口调用方法,就像下面这样:

BlogMapper mapper = session.getMapper(BlogMapper.class);
Blog blog = mapper.selectBlog(101);

使用Mapper代理方式,必须满足以下要求:

  • 定义与SQL映射文件同名的Mapper接口,并且将Mapper接口和SQL映射文件放置在同一目录下。
  • 设置SQL映射文件的namespace属性为Mapper接口全限定名
  • 在 Mapper 接口中定义方法,方法名就是SQL映射文件中sql语句的id,并保持参数类型和返回值类型一致

编写配置文件实现增删改查

增删改查都可以通过在 xml 映射文件中编写这样的语句来实现:

查询

查询所有

<select id="selectAll" resultType="Brand">
  SELECT * FROM tb_brand;
</select>

其中 resultType 是返回类型。
在使用时,常常我们需要将查询的结果封装到一个实体类中,如这里的 brand。
mybatis 会帮我们完成这个封装,然而当实体类的属性名和表中的列名不同时,这些属性无法封装(mysql 中用 _ 分隔,Java 中用驼峰命名)。
这时我们可以使用 resultMap 映射来解决这个问题:

    <resultMap id="brandResultMap" type="Brand">
        <result column="brand_name" property="brandName"></result>
        <result column="company_name" property="companyName"></result>
    </resultMap>

然后把之前的 resultType 替换成 resultMap,并填写相关字段。

    <select id="selectById" resultMap="brandResultMap">
        select * from tb_brand where id = #{id};
    </select>

条件查询

    <select id="selectById" resultMap="brandResultMap">
        select * from tb_brand where id = #{id};
    </select>

我们可以看到这里的参数传递的方式是使用 #{}
使用这种方式相当于 JDBC 中使用 PreparedStatement
有时我们需要使用多条件查询,条件的书写可能比较灵活,这时需要用到动态 sql,下面是一个例子。

  <select id="selectByDynamicCondition" resultMap="brandResultMap">
        select * from tb_brand
        <where>
            <if test="status != null">
                and status = #{status}
            </if>
            <if test="brandName != null and brandName != ''">
                and brand_name like #{brandName}
            </if>
            <if test="companyName != null and companyName != ''">
                and company_name like #{companyName};
            </if>
        </where>
    </select>

这里的 if 子句会根据条件决定是否拼接,where 子句会根据里面的拼接情况动态调整一些语法。
if 标签:条件判断
test 属性:逻辑表达式
where 标签
作用:
替换where关键字
会动态的去掉第一个条件前的 and
如果所有的参数没有值则不加where关键字
choose 标签
根据条件选择其中一个,相当于 switch
同时常用的还有 set 标签
set 标签可以用于动态包含需要更新的列,忽略其它不更新的列
同时需要注意的是修改表之后要手动提交事务。

mybatis 参数传递方式

通过阅读源码可以发现 mybatis 在底层使用 hashMap 来进行参数传递,会有一些默认的 key 值,但是更加方便的做法是使用 @Param()注解,这样可以提高可读性。
在我们使用时,除了通过注解辅助直接传递多个参数,也可以直接传递一个 hashmap,或者设置参数之后传递一个实体类(要有相应的 getter 和 setter)。

使用注解开发

除了在配置文件中编写映射,也可以使用注解的方式,比如

@Select("select * from tb_brand")
    List<Brand> selectAll();

但是只建议在 sql 语句很简单的时候采用这种方式,复杂的 sql 语句在这里不便编写,也不利于程序的可读性。

posted @   今天AC了吗  阅读(28)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示