MyBatis进阶

MyBatis进阶

承接上文MyBatis初阶

动态SQL

还是以MyBatis初阶环境一样,MySQL中有user_info 和article_info两张表

引入

这里添加一条记录

UserInfoMapper

java 复制代码
@Insert("insert into user_info (username,`password`,age,gender) " +
       "values(#{username},#{password},#{age},#{gender})")
Integer insertUser2(@Param("userInfo") UserInfo userInfo);

测试

java 复制代码
@Test
void insertUser() {
     UserInfo userInfo = new UserInfo();
     userInfo.setUsername("java123");
     userInfo.setPassword("java123");
     userInfo.setAge(1);
     //userInfo.setGender(1);
     Integer result = userInfoMapper.insertUser(userInfo);
     log.info("影响行数:{},自增主键:{}",result,userInfo.getId());
}

这里测试没有添加Gender,但是这里Gender没有添加默认是0,但是这里却给了null,不符合预期

执行SQL语句

sql 复制代码
insert into user_info (username,`password`,age) values ('C++','C++',20);

这里并不会像上面那样,这里gender没有填写,默认值是0

上面这样就会有错误,我们想要的是,此时这里没有填写的参数应该是默认值,而不是null,因为这里需要使用动态SQL,不需要的参数就不传入进去即可

标签

if标签

这里使用XML方式

UserInfoXMLMapper

java 复制代码
Integer insertByCondititon(UserInfo userInfo);

因为这里是动态SQL,有些东西可能没有传参,此时就直接是默认值即可,动态确定传入了那些参数

UserInfoXMLMapper

java 复制代码
Integer insertByCondititon(UserInfo userInfo);

UserInfoXMLMapper.xml

xml 复制代码
<insert id="insertByCondititon">
        insert into user_info (
            <if test="username!=null">
                username,
            </if>
            <if test="password!=null">
                `password`,
            </if>
            <if test="age!=null">
                age,
            </if>
            <if test="gender!=null">
                gender
            </if>
        ) values (
            <if test="username!=null">
                #{username},
            </if>
            <if test="password!=null">
                #{password},
            </if>
            <if test="age!=null">
                #{age},
            </if>
            <if test="gender!=null">
                #{gender}
            </if>
        )
</insert>
java 复制代码
@Test
    void insertByCondititon() {
        UserInfo userInfo = new UserInfo();
        userInfo.setUsername("java33");
        userInfo.setPassword("java33");
        userInfo.setAge(2);
        //userInfo.setGender(0);
        Integer result = userInfoXMLMapper.insertByCondititon(userInfo);
        log.info("影响行数:{},自增主键:{}",result,userInfo.getId());
    }

但这里会出现一个问题,这里没有填写gender这里就会多出一个,导致这里SQL语句错误,但这里如果将逗号放到前面,导致这里如果username为空,这里前面又多了一个,号,这怎么样都不行,因此这里需要将多余的,去除

标签

trim 标签

xml 复制代码
    <insert id="insertByCondititon">
        insert into user_info
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="username!=null">
                username,
            </if>
            <if test="password!=null">
                `password`,
            </if>
            <if test="age!=null">
                age,
            </if>
            <if test="gender!=null">
                gender
            </if>
        </trim>
        values
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="username!=null">
                #{username},
            </if>
            <if test="password!=null">
                #{password},
            </if>
            <if test="age!=null">
                #{age},
            </if>
            <if test="gender!=null">
                #{gender}
            </if>

        </trim>

    </insert>

trim标签中

prefix配置,开始时候加上 (

suffix配置,结束部分加上 )

因为这里以,结尾,但gender为空,会导致后面多了一个,结尾导致SQL语法错误,使用suffixOverrides去除最后一个多余的逗号

prefixOverrides会去除前一个多余的逗号

看情况使用,如果是每次逗号加后面,使用suffixOverrides去除最前面逗号

如果每次逗号加前面,prefixOverrides去除最前面逗号

标签

where标签

例如这里查找age = 2,gender = 0的数据

sql 复制代码
SELECT * FROM user_info where age = 2 and gender = 0;

UserInfoMapper

java 复制代码
List<UserInfo> selectByCondition(UserInfo userInfo);

UserInfoMapper.xml

java 复制代码
<select id="selectByCondition" resultType="com.mybatis.demo.entity.UserInfo">
        select id, username, password, age, gender, phone,
        delete_flag, create_time, update_time from user_info where
        <if test="age!=null">
            age = #{age}
        </if>
        <if test="gender!=null">
            and gender = #{gender}
        </if>
</select>

这里的确可以找成功,但是如果这时候,age数据为空呢?

java 复制代码
 @Test
 void selectByCondition() {
     UserInfo userInfo = new UserInfo();
     //userInfo.setAge(2);
     userInfo.setGender(0);      userInfoXMLMapper.selectByCondition(userInfo).forEach(System.out::println);
}

此时这里没有传入age导致这里动态SQL中多了一个and导致SQL语法错误,因此这里需要使用这个trim标签中prefixOverrides去除前面多余的and

java 复制代码
<select id="selectByCondition" resultType="com.mybatis.demo.entity.UserInfo">
        select id, username, password, age, gender, phone,
        delete_flag, create_time, update_time from user_info where
        <trim prefixOverrides="and">
            <if test="age!=null">
                age = #{age}
            </if>
            <if test="gender!=null">
                and gender = #{gender}
            </if>
        </trim>
</select>

此时解决了没有填写age多一个and问题,但是如果两个都没有填写数据,这里会多一个where关键字,这里可以让其加一个1=1解决问题,并且这个也可以解决多余and问题

java 复制代码
<select id="selectByCondition" resultType="com.mybatis.demo.entity.UserInfo">
        select id, username, password, age, gender, phone,
        delete_flag, create_time, update_time from user_info where 1=1
        <trim prefixOverrides="and">
            <if test="age!=null">
                age = #{age}
            </if>
            <if test="gender!=null">
                and gender = #{gender}
            </if>
        </trim>
</select>
java 复制代码
@Test
void selectByCondition() {
      UserInfo userInfo = new UserInfo();
      //userInfo.setAge(2);
      //userInfo.setGender(0);
  userInfoXMLMapper.selectByCondition(userInfo).forEach(System.out::println);
}

但是上面比较繁琐,因此这里可以使用where标签

这里的where标签会去除前面多余的and或者or,如果没有条件,其会去除where关键字

java 复制代码
<select id="selectByCondition" resultType="com.mybatis.demo.entity.UserInfo">
        select id, username, password, age, gender, phone,
        delete_flag, create_time, update_time from user_info
        <where>
            <if test="age!=null">
                age = #{age}
            </if>
            <if test="gender!=null">
                and gender = #{gender}
            </if>
        </where>
</select>

标签

set标签

例如修改这里id = 18的这一行

sql 复制代码
update user_info set username = 'java66',age = 16,gender = 0 where id = 18;
java 复制代码
Integer updateByCondition(UserInfo userInfo);

这里需要注意多的逗号处理和where中没有条件的处理,依旧需要去除多余逗号,这里条件可以直接使用where标签

java 复制代码
  <update id="updateByCondition">
        update user_info set
        <trim prefixOverrides=",">
            <if test="username!=null">
                username = #{username}
            </if>
            <if test="age!=null">
                ,age = #{age}
            </if>
            <if test="gender!=null">
                ,gender = #{gender}
            </if>
            <where>
                id = #{id}
            </where>
        </trim>
    </update>

测试

java 复制代码
@Test
void updateByCondition() {
        UserInfo userInfo = new UserInfo();
        userInfo.setUsername("java66");
        userInfo.setAge(16);
        userInfo.setGender(0);

        userInfo.setId(18);
        log.info("影响行数:{}",userInfoXMLMapper.updateByCondition(userInfo));
}

这里可以执行

此时可以直接使用set标签

java 复制代码
 <update id="updateByCondition">
        update user_info
          <set>
              <if test="username!=null">
                  username = #{username}
              </if>
              <if test="age!=null">
                  ,age = #{age}
              </if>
              <if test="gender!=null">
                  ,gender = #{gender}
              </if>
              <where>
                  id = #{id}
              </where>
          </set>
    </update>

但是这里如果要修改的参数一个没有修改,这里就会出错,正常的没有修改不会使用set标签

如果一个set中的要修改的参数不传入会报错

标签

对集合进行遍历会使用到该标签

collection:绑定的集合,像List、Set、Map等

item:每一个对象

open:语句开始字符串

close:语句结束字符串

separator:每次遍历之间用什么分割

这里根据id进行删除

UserInfoMapper

java 复制代码
Integer DeleteByIds(List<Integer> ids);

UserInfoMapper.xml

java 复制代码
 <delete id="DeleteByIds">
        delete from user_info where id in
        <foreach collection="ids" item="id" open="(" close=")" separator=",">
            #{id}
        </foreach>
    </delete>

测试

java 复制代码
 @Test
    void deleteByIds() {
        List<Integer> ids = new ArrayList<>();
        ids.add(13);
        ids.add(14);
        ids.add(18);

        Integer result = userInfoXMLMapper.DeleteByIds(ids);
        log.info("影响行数:{}",result);
    }

执行结果

标签

从这里可以发现,经常使用到表中所有列的字段,这里代码就有些冗余,因此可以将这里所有列放一起

xml 复制代码
<select id="selectAll" resultType="com.mybatis.demo.entity.UserInfo">
        select id, username, password, age, gender, phone,
        delete_flag, create_time, update_time from user_info
</select>

可以使用sql标签封装一个经常使用的sql片段,通过include标签中进行引用这里的sql标签

xml 复制代码
<sql id="Allcols">
        id, username, password, age, gender, phone,
        delete_flag, create_time, update_time
</sql>
<select id="selectAll" resultType="com.mybatis.demo.entity.UserInfo">
    select <include refid="Allcols"></include>
    from user_info
</select>

其实上面这些XML实现动态sql也可以直接使用,但是这样写不方便,并且这里报错提示信息也不好,不建议写在这上面,建议使用xml的方式进行写

MyBatis Generator

这些关于数据库的相关操作可以使用插件来处理

引入插件

这个插件是通过pom.xml文件操作

xml 复制代码
<plugin>
			<groupId>org.mybatis.generator</groupId>
			<artifactId>mybatis-generator-maven-plugin</artifactId>
			<version>1.3.6</version>
			<executions>
				<execution>
					<id>Generate MyBatis Artifacts</id>
					<phase>deploy</phase>
					<goals>
						<goal>generate</goal>
					</goals>
				</execution>
			</executions>
			<configuration>
				<!--generator配置文件所在位置-->
				<configurationFile>src/main/resources/generate/generator.xml</configurationFile>
				<!-- 允许覆盖生成的文件, mapxml不会覆盖, 采用追加的方式-->
				<overwrite>true</overwrite>
				<verbose>true</verbose>
				<!--将当前pom的依赖项添加到生成器的类路径中-->
				<includeCompileDependencies>true</includeCompileDependencies>
			</configuration>
			<dependencies>
				<dependency>
					<groupId>mysql</groupId>
					<artifactId>mysql-connector-java</artifactId>
					<version>8.0.33</version>
				</dependency>
			</dependencies>
		</plugin>

添加generator.xml文件

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
        PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<!-- 配置生成器 -->
<generatorConfiguration>

    <!-- 一个数据库一个context -->
    <context id="MysqlTables" targetRuntime="MyBatis3Simple" defaultModelType="flat">
        <!--去除注释-->
        <commentGenerator>
            <property name="suppressDate" value="true"/>
            <property name="suppressAllComments" value="true" />
        </commentGenerator>

        <!--数据库链接信息-->
        <jdbcConnection driverClass="com.mysql.jdbc.Driver"
                        connectionURL="jdbc:mysql://127.0.0.1:3306/book_test?serverTimezone=Asia/Shanghai&amp;nullCatalogMeansCurrent=true"
                        userId="root"
                        password="060610">
        </jdbcConnection>

        <!-- 生成实体类 -->
        <javaModelGenerator targetPackage="generator.entity" targetProject="src/main/java" >
            <property name="enableSubPackages" value="false"/>
            <property name="trimStrings" value="true"/>
        </javaModelGenerator>
        <!-- 生成mapxml文件 -->
        <sqlMapGenerator targetPackage="mybatisGenerator" targetProject="src/main/resources" >
            <property name="enableSubPackages" value="false" />
        </sqlMapGenerator>
        <!-- 生成mapxml对应client,也就是接口dao -->
        <javaClientGenerator targetPackage="generator.mapper" targetProject="src/main/java" type="XMLMAPPER" >
            <property name="enableSubPackages" value="false" />
        </javaClientGenerator>
        <!-- table可以有多个,每个数据库中的表都可以写一个table,tableName表示要匹配的数据库表,也可以在tableName属性中通过使用%通配符来匹配所有数据库表,只有匹配的表才会自动生成文件 -->
        <table tableName="user_info">
            <property name="useActualColumnNames" value="false" />
            <!-- 数据库表主键 -->
            <generatedKey column="id" sqlStatement="Mysql" identity="true" />
        </table>
        <table tableName="book_info">
            <property name="useActualColumnNames" value="false" />
            <!-- 数据库表主键 -->
            <generatedKey column="id" sqlStatement="Mysql" identity="true" />
        </table>
    </context>
</generatorConfiguration>

最终就会生成对应的实体类,和数据相关操作的xml

相关推荐
captain37613 小时前
MyBatis(入门5)其他查询操作
java·数据库·spring boot·mybatis
captain37615 小时前
MyBatis(进阶1)
mybatis
学长毕设21 小时前
基于SpringBoot的烘焙商品商品系统-附源码
java·spring boot·后端
howard20051 天前
英中 / 中英对照制作程序:操作指南
spring boot·bootstrap·thymeleaf·操作指南·对照制作程序
CoderYanger1 天前
Java EE 进阶:5. Spring IoC&DI(第三弹):Spring DI
java·开发语言·spring boot·spring·面试·java-ee·mvc
郭小李1 天前
mybatis的 Mapper.xml语法
xml·java·mybatis
小蒜学长1 天前
基于SpringBoot 框架的自媒体新闻系统的设计与实现(代码+数据库+LW)
java·spring boot·后端·mysql数据库·自媒体新闻管理系统
m0_639906941 天前
MyBatis 实现分页查询|逻辑分页、物理分页、PageHelper 原理
mybatis
余槐i1 天前
PostgreSQL 加索引后查询反而更慢:优化器弃用索引的 3 种情形
spring boot·redis·mysql·postgresql·事务