Mybatis 框架实战(上)

本文深入探讨MyBatis框架的高级特性,包括动态SQL、批量操作、自增ID处理等,通过实例演示如何优化数据库操作,提升开发效率。

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

  • Mybatis 持久层:简化工作量、灵活
  • Spring 粘合剂:整合框架 AOP IOC DI
  • SpringMvc 表现层:方便前后端数据的传输

Mybatis:

  • 1.是对jdbc的封装,
  • 2.将sql语句放在映射文件中(xml),
  • 3.自动将输入参数映射到sql语句的动态参数上,
  • 4.自动将sql语句执行的结果映射成java对象

入门示例:

1.创建项目mubatis-01

2.导入jar:

  • mybatis-3.2.8
  • mysql-connect
  • log4j-1.2.17

3.加入配置文件

(1)db.properties

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url = jdbc:mysql://localhost:3306/mysql_0219
jdbc.username = root
jdbc.password = 123456

(2)log4j.properties
https://blog.youkuaiyun.com/sinat_30185177/article/details/73550377

log4j.rootLogger=DEBUG,A1
log4j.logger.org.mybatis=DEBUG
...

(3) mybatis核心配置文件:mybatis-config.xml

(4) BlogMapper.xml

包:com.jingbin.mybatis.mapper

4.编写接口:BlogMapper

5.创建pojo:Blog

6.创建工具类:MyBatisUtil

7.编写测试类:

testSelectBlog
发现要连接数据库,学习mysql内容
学习配置好了后:运行报错:Invalid bound statement (not found): mapper.BlogMapper.selectBlog
解决:https://www.cnblogs.com/cailijuan/p/9505244.html
1)使用创建接口的方式
2)不是用接口的方式

8.列名和属性名不一致的情况

数据库里的列名为author_id,属性名为authorId。在BlogMapper.xml里:

1.使用别名

select author_id as authorId from Blog where id=#{id}

2.使用 resultMap

<resultMap type="Blog" id="blogResultMap">
		<id column="id" property="id" jdbcType="INTEGER"/>
      <result column="author_id" property="authorId" jdbcType="INTEGER"/>
</resultMap>

<select id="selectBlog" parameterType="Integer" resultMap="blogResultMap">
       select * from blog where id = #{id}
</select>

9.模糊查询之#$的区别

模糊查询:根据博客名字查询博客列表

1)使用#传参
2)使用$传参

#是占位符?,$是字符串拼接。

mybatis定义:

  • 使用$。如果参数是单指类型(简单类型),并且只有一个参数,则花括号里只能写value占位。
  • 使用$可以直接将%写里面,可能有sql注入的风险,建议最好使用#。参数是字符串要使用 ‘’
  • 当参数表示表名或列名的时候,只能使用$
<!-- 使用 $ 不区分大小写的查询 lower-->
    <select id="selectBlogByTitle2" parameterType="string" resultType="Blog">
            select * from blog where lower(title) like lower('%${value}%')
    </select>
</mapper>

10.查询排序

需求:按照某一列排序

select * from blog order by CONVERT(${value} USING gbk)

gbk:输入中文时排序成功,否则会失败。且使用gbk规避魅族(gb2313)不排序问题。

11.分页-多参数传递

需求:查询分页数据

  • 1)使用索引

按照参数的顺序,从0开始

select * from blog limit #{0}, #{1}

  • 2)使用注解

注解的value值要和mapper的占位参数一致。

select * from blog limit #{offset}, #{pageSize}
List<Blog> selectBlogByPage2(@Param(value = "offset") int offset, @Param(value = "pageSize") int pageSize);
  • 3)使用map(常用)

注意:mapper中的参数占位符要和测试中的map的key一一对应

select * from blog limit #{offset}, #{pageSize}
// 测试
SqlSession session = MyBatisUtil.getSqlSession();
BlogMapper blogMapper = session.getMapper(BlogMapper.class);
Map<String, Object> objectMap = new HashMap<>();
objectMap.put("offset", 0);
objectMap.put("pageSize", 2);
List<Blog> blogList = blogMapper.selectBlogByPage3(objectMap);

12.插入功能和获取刚刚插入的id

  • 1)插入记录

需求:新增一个博客记录

<insert id="insertBlog" parameterType="Blog">
        insert into `blog`(
          `name`,
          `age`,
          `title`,
          `author_id`,
          `featured`
        ) values (
          #{name},
          #{age},
          #{title},
          #{author_id},
          #{featured}
        )
    </insert>
    
// 提交
session.commit();
  • 2)获取自增id
    方式1:在mapper中配置insert节点的属性 useGeneratedKeyskeyProperty节点
<insert id="insertBlog" parameterType="Blog" useGeneratedKeys="true" keyProperty="id"/>

方式2:在全局配置文件中配置setting

<!--定义数据库链接配置-->
    <properties resource="db.properties"/>
    
<!--具体的insert也得配置 keyProperty节点-->
    <settings>
        <setting name="useGeneratedKeys" value="true"/>
    </settings>

方式3:适用于没有自增主键的数据库

<insert id="insertBlogOracle" parameterType="Blog">
        <selectKey resultType="java.lang.Integer" order="BEFORE" keyProperty="id">
            select seq.nextval as id from dual
        </selectKey>
        insert into `blog`(
          `name`,
          `age`,
          `title`,
          `author_id`,
          `featured`
        ) values (
          #{name},
          #{age},
          #{title},
          #{author_id},
          #{featured}
        )
    </insert>

    <insert id="insertBlogMysql" parameterType="Blog">
        <selectKey resultType="java.lang.Integer" order="AFTER" keyProperty="id">
            SELECT LAST_INSERT_ID()
        </selectKey>

        insert into `blog`(
        `name`,
        `age`,
        `title`,
        `author_id`,
        `featured`
        ) values (
        #{name},
        #{age},
        #{title},
        #{author_id},
        #{featured}
        )
    </insert>

13.修改功能和修改部分字段注意的问题

<update id="updateBlog" parameterType="Blog">
        update `blog`
        set
        `name` = #{name},
        `age` = #{age},
        `title` = #{title},
        `author_id` = #{author_id},
        `featured` = #{featured}
        where
        `id` = #{id}
    </update>

注意:如果没有为对象设置所有的要修改的属性,那么未设置的属性会用成员变量的默认值填充。
解决:
方式1:数据库查一遍,再返回的数据修改。缺点:又执行了一遍数据库操作
方式2:查询语句里增加if else。

14.删除记录

<delete id="deleteBlogById">
  delete from blog where id=#{id}
</delete>

动态sql
批量删除:使用动态sql实现
if、[choose、when、otherwise]、where、set、trim、foreach、sql片段

15.if

需求:

  • 1.查询已激活的并且博客的名字是包含某个查询字符串的记录
  • 2.如果用户没有输入任何查询字符串,那么就显示所有已激活的记录

// 如果用户输入了查询字符串
select * from blog
where state = ‘ACTIVE’
and title like ‘%o%’

// 用户没有输入查询字符串
select * from blog
where state = ‘ACTIVE’

select * from blog
where state = 'ACTIVE' 
<if test="value != null and value!=''">
   and title like value[%%] 具体见代码
</if>

16.choose、when、otherwise

需求:

  • 1、查询已激活的
  • 2、如果用户输入了标题的查询关键字,则根据关键字查询
  • 3、否则根据blog风格样式查询
  • 4、如果什么都没有输入,则显示推荐的博客
<select id="selectActiveBlogByTitleOrStyle" parameterType="Blog" resultType="Blog">
    select * from blog
    where state = 'ACTIVE'
    <choose>
        <when test="title != null and title!=''">and lower(title) like lower(#{title})</when>
        <when test="style != null and style!=''">and style = #{style}</when>
        <otherwise> and featured = true</otherwise>
    </choose>
</select>

17.where

需求:多条件查询,根据状态,标题,是否被推荐
自动修补查询条件,查询语句中的where关键字使用标签替代,不能省略 and or 关键字

<select id="selectBlogByCondition" parameterType="Blog" resultType="Blog">
    select * from blog
    <where>
        <if test="state != null and state!=''">
            state = #{state}
        </if>
        <if test="title != null and title!=''">
            and lower(title) like lower(#{title})
        </if>
        <if test="featured != null">
            and featured = #{featured}
        </if>
    </where>
</select>

18.set

需求:按需修改,修改执行的列,未指定的不修改
set 会自动去掉if语句后面的逗号

<update id="updateBlogByCondition" parameterType="Blog">
    update `blog`
    <set>
        <if test="name != null">`name` = #{name},</if>
        <if test="age != null">`age` = #{age},</if>
        <if test="title != null">`title` = #{title},</if>
        <if test="author_id != null">`author_id` = #{author_id},</if>
        <if test="featured != null">`featured` = #{featured},</if>
        <if test="state != null">`state` = #{state},</if>
        <if test="style != null">`style` = #{state},</if>
    </set>
    where `id` = #{id}
</update>

19.trim

<select id="selectBlogByConditionTrim" parameterType="Blog" resultType="Blog">
    select * from blog
    -- prefixOverrides 去掉前面的 and 或 or
    <trim prefix="where" prefixOverrides="and | or">
        <if test="state != null and state!=''">
            state = #{state}
        </if>
        <if test="title != null and title!=''">
            and lower(title) like lower(#{title})
        </if>
        <if test="featured != null">
            and featured = #{featured}
        </if>
    </trim>
</select>

<update id="updateBlogByConditionTrim" parameterType="Blog">
    update `blog`
    -- suffixOverrides 去掉后面的 ,
    <trim prefix="set" suffixOverrides=",">
        <if test="name != null">`name` = #{name},</if>
        <if test="age != null">`age` = #{age},</if>
        <if test="title != null">`title` = #{title},</if>
        <if test="author_id != null">`author_id` = #{author_id},</if>
        <if test="featured != null">`featured` = #{featured},</if>
        <if test="state != null">`state` = #{state},</if>
        <if test="style != null">`style` = #{state},</if>
    </trim>
    where `id` = #{id}
</update>

20.foreach

需求:批量删除

 <!-- parameterType 与 collection 一致-->
<delete id="deleteBlogList" parameterType="list">
    delete from blog where id in
    <foreach collection="list" item="item" open="(" close=")" separator=",">
        #{item}
    </foreach>
</delete>

@Test
public void testDeleteBlogList() {
    SqlSession session = MyBatisUtil.getSqlSession();
    BlogMapper blogMapper = session.getMapper(BlogMapper.class);
    List<Integer> asList = Arrays.asList(1, 2);
    int count = blogMapper.deleteBlogList(asList);
    // 提交
    session.commit();
    session.close();
    System.out.println("更新了" + count + "条记录");
}
### 关于 MyBatis 框架实战的实验报告及相关资料 #### 资料概述 MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。通过提供的参考资料[^1],可以了解到 MyBatis 的核心功能及其在实际项目中的应用方式。这些资源涵盖了从基础到高级的主题,包括但不限于开发环境搭建、接口编程、CRUD 操作、关联查询、分页处理、动态 SQL 和代码生成工具。 以下是针对 MyBatis 框架实战的相关实验报告和示例下载的内容整理: --- #### 开发环境搭建与配置 为了快速入门 MyBatis,可以从官方文档或教程入手完成开发环境的搭建。具体步骤通常涉及 Maven 或 Gradle 构建工具的引入,以及数据库连接池的设置。参考资料中提到的 `SqlSession` 使用方法是一个重要的切入点[^1]。 ```xml <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.x</version> </dependency> ``` --- #### 数据库 CRUD 操作 MyBatis 提供了灵活的方式来执行基本的数据操作(增删改查)。以下是一个简单的 Mapper 接口定义及对应的 XML 配置文件片段[^1]: ```java public interface UserMapper { List<User> selectAll(); } ``` ```xml <select id="selectAll" resultType="User"> SELECT * FROM users; </select> ``` --- #### 多表查询与复杂关系处理 对于复杂的业务场景,如多表联结查询,MyBatis 支持多种解决方案。例如,一对一、一对多或多对多的关系可以通过嵌套结果集来实现[^2]。下面展示了一个典型的 1 对多查询实例: ```xml <resultMap id="orderResultMap" type="Order"> <collection property="items" ofType="Item"> <id column="item_id" property="itemId"/> <result column="name" property="itemName"/> </collection> </resultMap> <select id="getOrdersWithItems" resultMap="orderResultMap"> SELECT o.id AS order_id, i.id AS item_id, i.name FROM orders o LEFT JOIN items i ON o.item_id = i.id; </select> ``` --- #### 动态 SQL 及条件过滤 MyBatis 中的动态 SQL 特性允许开发者根据运行时参数构建灵活的查询语句。这在处理复杂查询逻辑时非常有用[^3]。以下展示了如何利用 `<if>` 标签实现条件筛选的功能: ```xml <select id="findUsersByCondition" parameterType="map" resultType="User"> SELECT * FROM users WHERE 1=1 <if test="username != null and username != &#39;&#39;"> AND username LIKE CONCAT(&#39;%&#39;, #{username}, &#39;%&#39;) </if> <if test="age != null"> AND age >= #{age} </if> </select> ``` --- #### 分页与性能优化 当面对大规模数据量时,分页技术显得尤为重要。MyBatis 自身并不提供内置的分页机制,但可通过插件形式扩展此功能。参考资料中提到了一种基于拦截器的分页方案[^1]: ```java @Intercepts({ @Signature(type = Executor.class, method = "query", args = { MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class }) }) public class PaginationInterceptor implements Interceptor { public Object intercept(Invocation invocation) throws Throwable { // 实现分页逻辑... } } ``` --- #### Spring 整合与 Web 应用实践 现代 Java 企业级开发往往离不开 Spring 框架的支持。参考资料详细描述了 MyBatis 如何无缝集成至 Spring 容器,并提供了完整的源码示例。这种组合能够显著提升项目的可维护性和灵活性。 ```java @Configuration @MapperScan(basePackages = "com.example.mapper") public class MyBatisConfig { @Bean public DataSource dataSource() { return new EmbeddedDatabaseBuilder() .setType(EmbeddedDatabaseType.HSQL) .addScript("schema.sql").build(); } @Bean public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception { SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); sessionFactory.setDataSource(dataSource); return sessionFactory.getObject(); } } ``` --- #### 示例下载与进一步学习 如果希望获取更多关于 MyBatis实战案例和实验报告,建议访问以下平台: - **GitHub**: 许多开源项目都包含了详细的 README 文件和技术博客链接。 - **优快云/掘金**: 社区分享的文章常附带完整代码包。 - **官方文档**: https://mybatis.org/mybatis-3/ 以上内容均来源于公开可用的技术资料[^2][^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值