MyBatis————进阶
1,动态SQL
还是这个东西,如果delete_flag为null并且没有默认值的话,如果不传入值的话就会发生为null的异常,所以我们就需要动态SQL:
还是来写一个插入的SQL,
这把不带大家写配置文件了嗷,写好多遍了,model:
@Data
public class UserInfo {private Integer id;private String userName;private String password;private Integer deleteFlag;private Date createTime;private Date updateTime;
}
mapper:
void InsertUserInfo(UserInfo userInfo);
xml:
<insert id="InsertUserInfo">insert into user_info (user_name,password,delete_flag) values #{userName},#{password},#{deleteFlag};</insert>
test:
@SpringBootTest
class UserMapperTest {@Autowiredprivate UserMapper userMapper;@Testvoid insertUserInfo() {UserInfo userInfo = new UserInfo();userInfo.setUserName("姚宇2");userInfo.setPassword("sb");userMapper.InsertUserInfo(userInfo);}
}
来看一下运行结果:
是发生报错的,没有值和delete_flag匹配,这时候我们就要使用动态SQL了,有些值我想传就传呀,那么多限制,现在带大家来学习动态SQL:
1,<if>标签
直接上代码吧:
void InsertUserInfo2(UserInfo userInfo);
<insert id="InsertUserInfo2">insert into user_info (user_name,password<if test="deleteFlag!=null">,delete_flag</if>) values (#{userName},#{password}<if test="deleteFlag!=null">,#{deleteFlag}</if>)</insert>
@Testvoid insertUserInfo2() {UserInfo userInfo = new UserInfo();userInfo.setUserName("姚宇5");userInfo.setPassword("sb");userMapper.InsertUserInfo(userInfo);}
都成功添加了,但是嗷,这个是因为只有一个字段,我们可以根据具体情况来设置这个,就比如我们写的这个代码,如果存在多个代码呢,如果全部都可以为null呢,我们在if字段中都设置为(,属性),这样的话就有问题了,第一个为空不全崩盘了,但如果是 属性,) 的话也是有问题的,最后一个为null就在后面多一个,号了;
2,<trim>标签
trim标签就对应着多个字段,我们可以控制这个,号了,这个标签有4个属性,
1,prefix:表示整个语句块,以prefix的值作为前缀
2,suffix:表示整个语句块,以suffix的值作为后缀
3,prefixOverrides:表示整个语句块要去除的前缀
4,suffixOverrides:表示整个语句块要去除的后缀
现在在来写一个SQL语句,我们把这个字段改一下:
再来添加:
来添首为null,中间为null,尾为null的SQL语句:
void InsertUserInfo3(UserInfo userInfo);
<insert id="InsertUserInfo3">insert into user_info<trim prefix="(" suffix=")" prefixOverrides=","><if test="userName!=null">,user_name</if><if test="password!=null">,password</if><if test="deleteFlag!=null">,delete_flag</if></trim>values<trim prefix="(" suffix=")" prefixOverrides=","><if test="userName!=null">,#{userName}</if><if test="password!=null">,#{password}</if><if test="deleteFlag!=null">,#{deleteFlag}</if></trim></insert>
@Testvoid insertUserInfo3() {UserInfo userInfo = new UserInfo();userInfo.setUserName("鳐鱼");userMapper.InsertUserInfo3(userInfo);UserInfo userInfo1 = new UserInfo();userInfo1.setPassword("123123");userMapper.InsertUserInfo3(userInfo1);UserInfo userInfo2 = new UserInfo();userInfo2.setDeleteFlag(0);userMapper.InsertUserInfo3(userInfo2);}
添加成功了;
3,<where>
List<UserInfo> SelectUserInfoById(UserInfo userInfo);
<select id="SelectUserInfoById" resultType="org.example.java_test_6_8.model.UserInfo">select * from user_info<where><if test="deleteFlag!=null">and delete_flag = #{deleteFlag}</if><if test="password!=null">and password = #{password}</if></where></select>
@Testvoid selectUserInfoById() {UserInfo userInfo = new UserInfo();userInfo.setPassword("sb");userInfo.setDeleteFlag(1);userMapper.SelectUserInfoById(userInfo);}
查到了,看下数据库,是不是对应的上,
这里和大家说一下这个where标签就相当于where语句,他会自动把前面的and清除;
4,<set>标签
就是update 表名 set的那个set,会帮助我们去除多余的,号;
来更新那个id为21的字段,
void updateUserInfo(UserInfo userInfo);
<update id="updateUserInfo">update user_info<set><if test="userName!=null">user_name = #{userName},</if><if test="password!=null">password = #{password},</if><if test="deleteFlag!=null">delete_flag = #{deleteFlag},</if></set>where id = #{id}</update>
@Testvoid updateUserInfo() {UserInfo userInfo = new UserInfo();userInfo.setId(21);userInfo.setUserName("要与");userInfo.setPassword("12412414");userInfo.setDeleteFlag(0);userMapper.updateUserInfo(userInfo);}
更新成功了;
5,<foreach>标签
这个用来对集合遍历,我们来看标签的属性
~collection:参数绑定参数中的集合,
~item:遍历时的每一个对象
~open:语块开头的字符串
~close:语句块结束的字符串
~separator:每次遍历之间间隔的字符串
来把1,3,4删了:
void deleteUserInfoByIds(Integer[] ids);
<delete id="deleteUserInfoByIds">delete from user_info where id in<foreach collection="ids" item="id" open="(" close=")" separator=",">#{id}</foreach></delete>
@Testvoid deleteUserInfoByIds() {Integer[] arr = new Integer[]{1,3,4};userMapper.deleteUserInfoByIds(arr);}
来测试:
删除成功
6,<include>标签
这个就是一个懒人用品,比如这个select* ,要具体的字段的话就很长了,我们可以把这很长的一段放到一个SQL片段中,之后只要有重复的就引用这个,就好了;
来试试:
UserInfo selectUserInfo(Integer id);
<sql id="select111">id,user_name,password</sql><select id="selectUserInfo" resultType="org.example.java_test_6_8.model.UserInfo">select <include refid="select111"></include> from user_info where id =#{id};</select>
@Testvoid selectUserInfo() {userMapper.selectUserInfo(10);}
2,MyBatis Generator
我们刚才写的这些代码说实话挺麻烦的,不能封装一下吗,当然是可以的,MyBatis-plus就是对这些做了封装,我们先不学,下期来学,我们先来看下一个能直接帮我们生成model,Mapper,和SQL映射文件的东西:这个就是MyBatis Generator;
来pom的配置文件:
#MyBatis generator的pom文件<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/mybatisGenerator/generatorConfig.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>
意思是在这下面创建一个包,之后创建一个xml文件;在xml文件中写东西,
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfigurationPUBLIC "-//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"><!--禁⽤⾃动⽣成的注释--><commentGenerator><property name="suppressDate" value="true"/><property name="suppressAllComments" value="true" /></commentGenerator><!-- 数据库连接信息--><jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"connectionURL="jdbc:mysql://127.0.0.1:3306/book_test?serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true"userId="root"password="123456"></jdbcConnection><!--⽣成实体类,配置路径--><javaModelGenerator targetPackage="org.example.java_test_6_8.model"targetProject="src/main/java" ><property name="enableSubPackages" value="false"/><property name="trimStrings" value="true"/></javaModelGenerator><!--⽣成mapxml⽂件--><sqlMapGenerator targetPackage="mapper"targetProject="src/main/resources" ><property name="enableSubPackages" value="false" /></sqlMapGenerator><!--⽣成mapxml对应client,也就是接⼝dao --><javaClientGenerator targetPackage="org.example.java_test_6_8.mapper"targetProject="src/main/java" type="XMLMAPPER" ><property name="enableSubPackages" value="false" /></javaClientGenerator><!-- table可以有多个,tableName表⽰要匹配的数据库表 --><table tableName="book_info" domainObjectName="BookInfo"enableSelectByExample="true"enableDeleteByExample="true" enableDeleteByPrimaryKey="true"enableCountByExample="true"enableUpdateByExample="true"><!-- 类的属性是否⽤数据库中的真实字段名做为属性名, 不指定这个属性会⾃动转 _ 为驼峰命名规则--><property name="useActualColumnNames" value="false" /><!-- 数据库表主键--><generatedKey column="id" sqlStatement="Mysql" identity="true" /></table></context>
</generatorConfiguration>
之后写这个文件:
<jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"connectionURL="jdbc:mysql://127.0.0.1:3306/book_test?serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true"userId="root"password="123456">
这写自己数据库的信息,
<javaModelGenerator targetPackage="org.example.java_test_6_8.model"targetProject="src/main/java" ><property name="enableSubPackages" value="false"/><property name="trimStrings" value="true"/></javaModelGenerator>
这是model类的路径,会帮我们创建,
<sqlMapGenerator targetPackage="mapper"targetProject="src/main/resources" ><property name="enableSubPackages" value="false" /></sqlMapGenerator>
xml文件的路径,
<javaClientGenerator targetPackage="org.example.java_test_6_8.mapper"targetProject="src/main/java" type="XMLMAPPER" ><property name="enableSubPackages" value="false" /></javaClientGenerator>
mapper文件的路径:
<table tableName="book_info" domainObjectName="BookInfo"enableSelectByExample="true"enableDeleteByExample="true" enableDeleteByPrimaryKey="true"enableCountByExample="true"enableUpdateByExample="true"><!-- 类的属性是否⽤数据库中的真实字段名做为属性名, 不指定这个属性会⾃动转 _ 为驼峰命名规则--><property name="useActualColumnNames" value="false" /><!-- 数据库表主键--><generatedKey column="id" sqlStatement="Mysql" identity="true" /></table>
这个就是我们要根据哪一个表来创建mapper,model和xml文件,
之后就帮我们生成了,
有很多的方法 ,说实话,我觉得挺麻烦的,我们后期学plus;