这里写目录标题
Mybatis
###collection对多
-
select:另一个映射查询的id,MyBatis会额外执行这个查询获取嵌套对象的结果。
-
column:将主查询中列的结果作为嵌套查询的参数,配置方式如column="{prop1=col1,prop2=col2}",prop1和prop2将作为嵌套查询的参数。
-
fetchType:数据加载方式,可选值为lazy和eager,分别为延迟加载和积极加载。
-
如果要使用延迟加载,除了将fetchType设置为lazy,还需要注意全局配置aggressiveLazyLoading的值应该为false
##继承在表中的实现
继承的实现方法
将一个继承树中的所有内容都存储在一个表中,引入一个特殊的标识列用于标识当前数据的具体子类型
create table t_vehicle(
id bigint primary key auto_increment,
name varchar(32) not null, -- 公共属性 父类
door_num int, -- Car子类型中的特有属性
driven_num int, -- Suv子类型中的特有属性
_type int default 0 -- 标识列,用于说明当前行数据的具体类型0标识Vehicle,1Car2Suv
)engine=innodb default charset utf8;
实体类
父类
public class Vehicle{
private Long id;
private String name;
}
子类型1 -Car
public class Car extends Vehicle{
private int doorNum;
}
子类型2 -Suv
public class Suv extends Vehicle{
private int drivenNum;
}
对应的映射配置文件
<resultMap id="VehicleMap" type="com.yan.entity.VehicleBean">
<id column="id" property="id" jdbcType="BIGINT"/>
<result column="name" property="name" jdbcType="VARCHAR"/>
<discriminator javaType="int" column="_type">
<case value="1" resultType="com.yan.entity.CarBean">
<result property="doorNum" column="door_num"/>
</case>
<case value="2" resultType="com.yan.entity.SuvBean">
<result property="drivenNum" column="driven_num"/>
</case>
</discriminator>
</resultMap>
<select id="loadById" parameterType="long" resultMap="VehicleMap">
select * from t_vehicle where id=#{id}
</select>
动态SQL
if标签用于执行ONGL表达式判断
动态查询
<select id="selectByMap" parameterType="map" resultMap="baseResultMapper">
select * from t_users where 1=1
<if test="username!=null">
and username=#{username}
</if>
<if test="password!=null">
and password=#{password}
</if>
</select>
整形范围查询 between/and
<select id="selectByMap2" parameterType="map" resultMap="baseResultMapper">
select * from t_users where id between #{beginId} and #{endId}
</select>
字符串模糊查询
<select id="selectByMap" parameterType="map" resultMap="baseResultMapper">
select * from t_users where 1=1
<if test="username!=null">
and username like #{username}
</if>
</select>
是否使用模糊查询取决于传递的参数值username中是否有通配符 _或者%
另外写法:
<select id="selectLike" parameterType="map" resultMap="baseResultMapper">
select * from t_users where username like concat('%',#{username},'%')
</select>
动态插入
trim标签可以在语句体的开头或者末尾添加执行的内容或者剔除指定的内容
- prefix在语句体的头部添加指定内容,suffix在语句体的末尾添加指定内容
- prefixoverrides在语句体的头部去除指定内容,suffixoverriders在语句体的末尾去除指定内容
<insert id="save" parameterType="User">
insert into t_users(
username,password,
<trim suffixOverrides=",">
<if test="birth!=null">birth,</if>
<if test="sex!=null">sex,</if>
</trim>
) values(
#{username},#{password},
<trim suffixOverrides=",">
<if test="birth!=null">#{birth,jdbcType=DATE},</if>
<if test="sex!=null">#{sex},</if>
</trim>
)
</insert>
如果表中某些列不允许为null
<insert id="save" parameterType="User">
insert into t_users(
username,password
<if test="birth!=null">,birth</if>
<if test="sex!=null">,sex</if>
) values(
#{username},#{password}
<if test="birth!=null">,#{birth,jdbcType=DATE}</if>
<if test="sex!=null">,#{sex}</if>
)
</insert>
动态修改
<update id="updateUser" parameterType="User">
update t_users set id=#{id}
<if test="username!=null">
,username=#{username}
</if>
<if test="password!=null">
,password=#{password}
</if>
where id=#{id}
</update>
set 用法
如果该标签包含的元素中有返回值,就插入一个set,如果set后面的字符串是以,结尾的,就将这个逗号剔除。
需求:更新用户信息的时候不能将原来有值但没有发生变化的字段更新为空或null,即只更新有值的字段。
<update id="updateUser" parameterType="User">
update t_users
<set>
<if test="username!=null">
username=#{username},
</if>
<if test="password!=null">
password=#{password},
</if>
</set>
where id=#{id}
</update>
where 用法
如果该标签包含的元素中有返回值,就插入一个where,如果where后面的字符串是以AND或者OR开头的,就将它们剔除
需求:根据用户的输入条件来查询用户列表,如果输入了用户名,就根据用户名模糊查询,如果输入了邮箱,就根据邮箱精确查询,如果同时输入了用户名和邮箱,就用这两个条件去匹配用户
<select id="selectByUserWhere" resultType="com.yan.entity.UserBean">
SELECT * FROM t_users
<where>
<if test="userName != null and userName != ''">
AND user_name LIKE CONCAT('%',#{userName},'%')
</if>
<if test="userEmail != null and userEmail != ''">
AND user_email = #{userEmail}
</if>
</where>
</select>
choose用法
当参数id有值时优先使用id查询,当id没有值时就去判断用户名是否有值,如果有值就用用户名查询,如果没值,就使查询无结果
<select id="selectByIdOrUserName" resultType="com.yan.entity.SysUser">
SELECT * FROM sys_user WHERE 1 = 1
<choose>
<when test="id != null">
AND id = #{id}
</when>
<when test="userName != null and userName != ''">
AND user_name = #{userName}
</when>
<otherwise>
AND 1 = 2
</otherwise>
</choose>
</select>
如果没有otherwise这个限制条件,当id和userName都为null时,所有的用户都会被查询出来,但我们接口的返回值是SysUser,当查询结果是多个时就会报错。添加otherwise条件后,由于where条件不满足,因此在这种情况下就查询不到结果。
因为在标签中没有if/else结构,所以可以使用choose模拟出if/else
需求:如果id非空则按照id查询,否则按照id为null进行查询
<select if="select1" parameterType="com.yan.entity.UserBean" resultType="com.yan.entity.UesrBean">
select * from t_users
<choose>
<when test="id!=null">
where id=#{id}
</when>
<otherwise>
where id is null
</otherwise>
</choose>
</select>
foreach用法
主要三种用途:foreach实现in集合、foreach 实现批量插入、foreach 实现动态update
foreach 实现in集合
根据传入的用户id集合查询出所有符合条件的用户,此时需要使用到Sql中的IN,如 id in (1,10,101)
<select id="selectByIdList" resultType="com.zwwhnly.mybatisaction.model.SysUser">
SELECT * FROM sys_user WHERE id IN
<foreach collection="list" open="(" close=")" separator="," item="id" index="i">
#{id}
</foreach>
</select>
- open:整个循环内容开头的字符串。
- close:整个循环内容结尾的字符串。
- separator:每次循环的分隔符。
- item:从迭代对象中取出的每一个值。
- index:如果参数为集合或者数组,该值为当前索引值,如果参数为Map类型时,该值为Map的key。
- collection:要迭代循环的属性名。
foreach 实现批量插入
将传入的用户集合批量写入数据库 insertUserList(List<UserBean> list)
<insert id="insertUserList" parameterType="list">
insert into t_users(username,password) values
<foreach collection="list" item="u" separator=",">
(#{u.username},#{u.password})
</foreach>
</insert>
foreach 实现动态update
传入Map更新数据 int updateByMap(Map<String,Object> map);
<update id="updateByMap" parameterType="map">
UPDATE sys_user SET
<foreach collection="_parameter" item="val" index="key" separator=",">
${key} = #{val}
</foreach>
WHERE id = #{id}
</update>
##特殊符号${}和#{}的区别