以下为mybaties在实际项目中运用总结,供参考
数据库:mysql 或者oracle,开发工具eclipse,开发技术mybaties+spring+springmvc
使用mysql数据库插入数据id自动增长写法
<insert id="addSign" useGeneratedKeys="true" keyProperty="id" parameterType="com.suwei.sysMng.bean.YkatUserSign">
insert into ykat_user_sign(user_id,user_name,user_type,create_time,serial_days,update_time,is_del)
values(#{userId},#{userName},#{userType},#{createTime},#{serialDays},#{updateTime},1)
</insert>
使用like模糊查询,if条件判断
<select id="expertQuery" parameterType="java.util.Map" resultType="java.util.Map">
select e.id,e.expert_name AS expertName,e.phone,e.longitude,e.latitude,
e.expert_address AS expertAddress,
vm.id AS expertGoodAtId,
GROUP_CONCAT(vm.models_name) AS expertGoodAt
from ykat_expert AS e
left join ykat_expert_models AS em on e.id = em.expert_id
left join ykat_vehicle_models AS vm on em.vehicle_models_id = vm.id
where 1=1 and e.is_del=1
<if test="expertName!=null and expertName!='' ">
and e.expert_name like '%${expertName}%'
</if>
<if test="expertGoodAt!=null and expertGoodAt!='' ">
and vm.id=#{expertGoodAt}
</if>
group by e.id
order by e.id desc
limit #{page} , #{pageSize}
</select>
传递多个参数使用map形式
xml文件
<update id="storeStaffUpdate" parameterType="java.util.Map">
update ykat_store_satff
set integral=#{integral}
where user_id=#{userId}
</update>
dao层
int storeStaffUpdate(Map<String, Object> params);
service层
Map<String, Object> driverMap=new HashMap<String, Object>();
driverMap.put("integral", integral);
driverMap.put("userId", userId);
driverDao.updateDriverByUserId(driverMap);
总结:#{xxx}里面的值必须与map的可以值一致,否则报错
传递参数类型为List,Array,Map等写法,foreach使用
foreach介绍:
foreach的主要用在构建in条件中,它可以在SQL语句中进行迭代一个集合。foreach元素的属性主要有item,index,collection,open,separator,close。item表示集合中每一个元素进行迭代时的别名,index指定一个名字,用于表示在迭代过程中,每次迭代到的位置,open表示该语句以什么开始,separator表示在每次进行迭代之间以什么符号作为分隔符,close表示以什么结束,在使用foreach的时候最关键的也是最容易出错的就是collection属性,该属性是必须指定的,在不同情况下,该属性的值是不一样的,主要有一下3种情况:
1.如果传入的是单参数且参数类型是一个List的时候,collection属性值为list
2.如果传入的是单参数且参数类型是一个Array数组的时候,collection的属性值为array
3.如果传入的参数是多个的时候,我们就需要把它们封装成一个Map,当然单参数也可以封装成map,实际上如果你在传入参数的时候,在MyBatis里面也是会把它封装成一个Map的,map的key就是参数名,所以这个时候collection属性值就是传入的List或array对象在自己封装的map里面的key值名称
案例:
实体类:
public class Employees {
private Integer employeeId;
private String firstName;
private String lastName;
private String email;
private String phoneNumber;
private Date hireDate;
private String jobId;
private BigDecimal salary;
private BigDecimal commissionPct;
private Integer managerId;
private Short departmentId;
}
xml文件:
1.传递参数类型为List,foreache中的collection属性类型必须是List,collection的值必须是list,item的值任意,但是必须与#{xxx}里面的值一致,index的值任意,Dao中参数名任意
<select id="getEmployeesListParams" resultType="Employees">
select *
from EMPLOYEES e
where e.EMPLOYEE_ID in
<foreach collection="list" item="employeeId" index="index"
open="(" close=")" separator=",">
#{employeeId}
</foreach>
</select>
2.传递参数类型为Array,foreach中的collection属性类型必须是Array,collection的值必须是array,item的值任意,但是必须与#{xxx}里面的值一致,index的值任意,Dao中参数名任意
<select id="getEmployeesArrayParams" resultType="Employees">
select *
from EMPLOYEES e
where e.EMPLOYEE_ID in
<foreach collection="array" item="employeeId" index="index"
open="(" close=")" separator=",">
#{employeeId}
</foreach>
</select>
3.传递的参数类型为Map,foreach中的collection属性值必须是map的key值,其他属性值必须都是map的key值,比如下面的salary,Dao中参数名任意
<select id="getEmployeesMapParams" resultType="Employees">
select *
from EMPLOYEES e
<where>
<if test="employeeIdsArray!=null and employeeIdsArray.length!=0">
e.EMPLOYEE_ID in
<foreach collection="employeeIdsArray" item="employeeId"
index="index" open="(" close=")" separator=",">
#{employeeId}
</foreach>
</if>
<if test="salary!=null">
order by ${salary} desc
</if>
<if test="page!= null and page!="" and pageSize!= null and pageSize!= '' ">
limit ${page},${pageSize}
<if>
</where>
</select>
Mapper类:
public interface EmployeesMapper {
List<Employees> getEmployeesListParams(List<String> employeeIds);
List<Employees> getEmployeesArrayParams(String[] employeeIds);
List<Employees> getEmployeesMapParams(Map<String,Object> params);
}
测试类:
@Test
public void testGetResultsMapParmas(){
//参数是数组,则在xml文件中if判断时,taskIds.length != 0
// int[] array = new int[5];
// array[0] = 9;
// array[1] = 12;
//参数是列表,则在xml文件中if判断时,taskIds.size != 0
List<Integer> taskIds = new ArrayList<>();
taskIds.add(9);
taskIds.add(12);
Map<String, Object> params = new HashMap<>();
BigDecimal salary=122521541;
params.put("employeeIdsArray",array);
params.put("salary", salary);
//设置分页page可以为0,pageSize不能为0
params.put("page", 0);
params.put("pageSize",1);
List<TestResult> results = testResultDao.getResultsMapParmas(params);
for(TestResult result : results){
System.out.println("resultId:" + result.getResultId() + " ** startTime:" + result.getStartTime());
}
}
总结:
1.如果Map中value为数组或者链表,那么在foreach标签中的collection值必须与它的key值一样,否则会报错。当value为数组时,在if标签中判断时为taskIds.length != 0,当value为链表时,则在if标签中判断时为taskIds.size != 0。
2.使用mybatis-generator自动生成dao,则可以对某张表配置enableSelectByExample=”true”,然后使用Example来传入List参数,并添加其他条件。
3.对传递的参数一定要进行非空判断,在前台获得的参数进行非空判断,或者在xml文件中进行非空判断。
4.以上案例均用到了批量查询操作,可以参考
在日常开发中日期数据库设计为datetime类型,实体类型为Date类型,而在页面显示往往是string类型,显示格式为“yyyy-MM-dd”或者“yyyy-MM-dd”,则在进行数据库查询时我们需要将数据库查询的Date日期转换为字符串类型,以下为mysql和oracle中日期转换格式写法:
mysql数据库,Date日期类型,在xml文件中格式化写法:(常用)
<sql id="Base_Column_List2">
id,user_id,user_name,user_type,trade_points,trade_type,points_reward,points_avail,
date_format(create_time_time,'%Y-%m-%d %H:%i:%S') AS createTime,
date_format(update_time_time,'%Y-%m-%d %H:%i:%S') AS updateTime
</sql>
oracle数据库,Date日期类型,在xml文件中格式化写法(常用)
<sql id="Base_Column_List" >
JQID, JJDID, GLJJDBH, BJFS, JJDW, JJYBH, JJYXM, BJSJ,to_char(BJSJ,'yyyy-MM-dd HH24:mi:ss') bjsj_str, JJSC, BJDH, BJRXM, BJRXB, LXDH,
ZZDW, AFDD, SYXX, ZBXX, BJNR, GXDW, JWQ, BKRS, SSRS, SWRS, JQZT, GXZT, BYZD1, BY2,
</sql>
备注:转换成字符串则要在实体类中定义string类型的日期
oracle数据库,2个日期比较,如开始时间,结束时间
<select id="findjqztEvents5" parameterType="java.util.Map" resultType="com.doron.tcs.model.TItmpTcsEvents">
select jqid, to_char(BJSJ,'HH24:mi') bjsj_str, bjnr, x, y,to_char(bjsj,'yyyy-MM-dd HH24:mi') bjsj_ystr
from t_itmp_tcs_events
where jqzt = 5 and isvalid=1
<if test="bjnr!=null and bjnr!=''">
and bjnr like '%${bjnr}%'
</if>
<if test="bjjb!=null and bjjb!=''">
and bjjb = #{bjjb}
</if>
<if test="kssj!=null and kssj!=''">
and to_date(to_char(bjsj,'yyyy-MM-dd'),'yyyy-MM-dd') >= to_date(#{kssj},'yyyy-MM-dd')
</if>
<if test="jssj!=null and jssj!=''">
<![CDATA[and to_date(to_char(bjsj,'yyyy-MM-dd'),'yyyy-MM-dd') <= to_date(#{jssj},'yyyy-MM-dd')]]>
</if>
order by BJSJ desc
</select>
、
备注:
mybaties报元素内容必须由格式正确的字符数据或标记组成
原因:mybatis查询的时候,需要用到运算符 小于号:< 和 大于号: >,在mybatis配置文件里面,这种会被认为是标签,所以解析错误
故解决方法为:
1.<![CDATA[and to_date(to_char(bjsj,’yyyy-MM-dd’),’yyyy-MM-dd’) <= to_date(#{jssj},’yyyy-MM-dd’)]]>
或者 : 将 < 号换成 < > 号 换成> 等于号用eq;
批量更新:
<update id="updateEventByAllJqid" parameterType="java.util.Map" >
update T_ITMP_TCS_EVENTS
set ISVALID = #{isvalid}
where JQID in
<foreach collection="jqid" item="idItem" open="(" separator="," close=")" >
#{idItem}
</foreach>
</update>
备注:foreache循环的参数一定要进行非空判断,这里没有进行判断,那么必须在传入参数地方进行判断非空操作,否则报错。
xml文件中解析转换特殊字符如大于号,小于号等写法:![CDATA[]]
<select id="findjqztEvents5" parameterType="java.util.Map" resultType="com.doron.tcs.model.TItmpTcsEvents">
select jqid, to_char(BJSJ,'HH24:mi') bjsj_str, bjnr, x, y, to_char(bjsj,'yyyy-MM-dd HH24:mi') bjsj_ystr
from t_itmp_tcs_events
where jqzt = 5 and isvalid=1
<if test="bjnr!=null and bjnr!=''">
and bjnr like '%${bjnr}%'
</if>
<if test="bjjb!=null and bjjb!=''">
and bjjb = #{bjjb}
</if>
<if test="kssj!=null and kssj!=''">
and to_date(to_char(bjsj,'yyyy-MM-dd'),'yyyy-MM-dd') >= to_date(#{kssj},'yyyy-MM-dd')
</if>
<if test="jssj!=null and jssj!=''">
<![CDATA[and to_date(to_char(bjsj,'yyyy-MM-dd'),'yyyy-MM-dd') <= to_date(#{jssj},'yyyy-MM-dd')]]>
</if>
order by BJSJ desc
</select>
插入数据,判断字段是否为空
<insert id="insertSelective" parameterType="com.doron.tcs.model.TItmpTcsEvents" >
insert into T_ITMP_TCS_EVENTS
<trim prefix="(" suffix=")" suffixOverrides="," >
<if test="jqid != null" >
JQID,
</if>
<if test="jjdid != null" >
JJDID,
</if>
<if test="gljjdbh != null" >
GLJJDBH,
</if>
<if test="bjfs != null" >
BJFS,
</if>
<if test="jjdw != null" >
JJDW,
</if>
<if test="jjybh != null" >
JJYBH
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides="," >
<if test="jqid != null" >
#{jqid,jdbcType=VARCHAR},
</if>
<if test="jjdid != null" >
#{jjdid,jdbcType=VARCHAR},
</if>
<if test="gljjdbh != null" >
#{gljjdbh,jdbcType=VARCHAR},
</if>
<if test="bjfs != null" >
#{bjfs,jdbcType=DECIMAL},
</if>
<if test="jjdw != null" >
#{jjdw,jdbcType=DECIMAL},
</if>
<if test="jjybh != null" >
#{jjybh,jdbcType=VARCHAR}
</if>
</trim>
</insert>
mybaties中多表关联查询,2个实体合并成一个实体则xml文件这样写:
<?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="com.doron.tsms.dao.TItmpTsmsDutylineMapper" >
<resultMap id="BaseResultMap" type="com.doron.tsms.model.TItmpTsmsDutyline" >
<id column="ID" property="id" jdbcType="VARCHAR" />
<result column="XLMC" property="xlmc" jdbcType="VARCHAR" />
<result column="CFD" property="cfd" jdbcType="VARCHAR" />
<result column="MDD" property="mdd" jdbcType="VARCHAR" />
<result column="JGLK" property="jglk" jdbcType="VARCHAR" />
<result column="LXCD" property="lxcd" jdbcType="DECIMAL" />
<result column="PJSS" property="pjss" jdbcType="DECIMAL" />
<result column="DWBH" property="dwbh" jdbcType="VARCHAR" />
<result column="SJ" property="sj" jdbcType="TIMESTAMP" />
<result column="YJSJ" property="yjsj" jdbcType="VARCHAR" />
</resultMap>
<resultMap id="ResultMapWithBLOBs" type="com.doron.tsms.model.TItmpTsmsDutyline" extends="BaseResultMap" >
<result column="DLZB" property="dlzb" jdbcType="BLOB" />
</resultMap>
<sql id="Base_Column_List" >
ID, XLMC, CFD, MDD, JGLK, LXCD, LXCD as lxcd_str,PJSS, PJSS as pjss_str, DWBH, SJ,to_char(SJ,'yyyy-MM-dd hh24:mi') as sj_str, YJSJ
</sql>
<sql id="Blob_Column_List" >
DLZB
</sql>
<select id="selectAllList" resultMap="BaseResultMap">
select
<include refid="Base_Column_List" />,<include refid="Blob_Column_List" />,(select count(1) from T_ITMP_TSMS_DUTYTASK t where t.lxbh=p.id) sycs
from T_ITMP_TSMS_DUTYLINE p
<where>
1=1
<if test="cfd != null">
and
(CFD like '%'||#{cfd}||'%'
OR
MDD like '%'||#{cfd}||'%'
OR
XLMC like '%'||#{cfd}||'%')
</if>
<if test="dwbh!=null">
and DWBH =#{dwbh}
</if>
</where>
order by sj desc
</select>
<!--查询关联2个字段-->
<select id="selectByPrimaryKey" resultMap="ResultMapWithBLOBs" parameterType="java.lang.String" >
select
<include refid="Base_Column_List" />,<include refid="Blob_Column_List" />
from T_ITMP_TSMS_DUTYLINE
where ID = #{id,jdbcType=VARCHAR}
</select>
<!-- 判断任务名称是否重复,如果存在返回数量 -->
<select id="selectRwmcByLxmc" parameterType="Map" resultType="int">
select count(xlmc)
from T_ITMP_TSMS_DUTYLINE
where XLMC = #{xlmc,jdbcType=VARCHAR}
<if test="''!=id and id != null" >
and ID != #{id,jdbcType=VARCHAR}
</if>
</select>
</mapper>
批量插入:
方法一:
oracle数据库
<insert id="insertBatch" parameterType="java.util.List" >
insert into T_ITMP_TSMS_EXECUTECALL (ID, RWBH, JYBH, ZT, SJ, GWBH)
<foreach collection="list" item="item" index="index" separator="union all" >
(select #{item.id,jdbcType=VARCHAR}, #{item.rwbh,jdbcType=VARCHAR}, #{item.jybh,jdbcType=VARCHAR},
#{item.zt,jdbcType=VARCHAR}, #{item.sj,jdbcType=VARCHAR}, #{item.gwbh,jdbcType=VARCHAR} from dual)
</foreach>
</insert>
备注:这里一定要用select标签不能insert或者update
mysql数据库
<insert id="insertBatch" useGeneratedKeys="true" parameterType="java.util.List">
<selectKey resultType="long" keyProperty="id" order="AFTER">
SELECT LAST_INSERT_ID()
</selectKey>
insert into t_train_record (add_time,emp_id,activity_id,flag)
values
<foreach collection="list" item="item" index="index" separator="," >
(#{item.addTime},#{item.empId},#{item.activityId},#{item.flag})
</foreach>
</insert>
或者:
<insert id="batchSave" parameterType="java.util.List">
INSERT INTO TABLE_NAME(ID,NAME) VALUES
<foreach collection="list" item="itm" separator=",">
(#{itm.id},#{itm.name})
</foreach>
</insert>
方法二:
<insert id="insertbatch" parameterType="java.util.List">
<selectKey keyProperty="id" order="BEFORE" resultType="long">
SELECT CURRENT_TIMESTAMP()
</selectKey>
insert into T_ITMP_TSMS_EXECUTECALL(ID, RWBH, JYBH, ZT, SJ, GWBH) values
<foreach collection="list" item="item" index="index" separator=",">
(#{item.id,jdbcType=VARCHAR}, #{item.rwbh,jdbcType=VARCHAR}, #{item.jybh,jdbcType=VARCHAR},#{item.zt,jdbcType=VARCHAR}, #{item.sj,jdbcType=VARCHAR},
#{item.gwbh,jdbcType=VARCHAR)
</foreach>
</insert>
总结:
其属性如下:
parameterType ,入参的全限定类名或类型别名
keyColumn ,设置数据表自动生成的主键名。对特定数据库(如PostgreSQL),若自动生成的主键不是第一个字段则必须设置
keyProperty ,默认值unset,用于设置getGeneratedKeys方法或selectKey子元素返回值将赋值到领域模型的哪个属性中
useGeneratedKeys ,取值范围true|false(默认值),设置是否使用JDBC的getGenereatedKeys方法获取主键并赋值到keyProperty设置的领域模型属性中。MySQL和SQLServer执行auto-generated key field,因此当数据库设置好自增长主键后,可通过JDBC的getGeneratedKeys方法获取。但像Oralce等不支持auto-generated key field的数据库就不能用这种方法获取主键了
statementType ,取值范围STATEMENT,PREPARED(默认值),CALLABLE
flushCache ,取值范围true(默认值)|false,设置执行该操作后是否会清空二级缓存和本地缓存
timeout ,默认为unset(依赖jdbc驱动器的设置),设置执行该操作的最大时限,超时将抛异常
databaseId ,取值范围oracle|mysql等,表示数据库厂家,元素内部可通过`<if test=”_databaseId = ‘oracle'”>`来为特定数据库指定不同的sql语句
order属性 ,取值范围BEFORE|AFTER,指定是在insert语句前还是后执行selectKey操作
注意:selectKey操作会将操作查询结果赋值到insert元素的parameterType的入参实例下对应的属性中。并提供给insert语句使用
批量删除:
<delete id="deleteBatch" parameterType="java.util.List">
DELETE FROM STUDENT WHERE id IN
<foreach collection="list" index="index" item="item" open="(" separator="," close=")">
#{item}
</foreach>
</delete>
mybaties查询返回数组:resultType=”string”表示返回string数组
xml文件:
<!-- 根据门店id查询所有用户id -->
<select id="queryByOrderId" parameterType="java.lang.Long" resultType="string">
select user_id
from ykat_store_satff
where store_id=#{storeId} and is_del=1
</select>
则dao层:
/**
* @descript: 根据门店id查询所有用户id
* @param storeId 门店id
* @return
*/
String [] queryByOrderId(@Param("storeId")Long storeId);
server层:
//根据门店id查询所有用户id
String []userId=storeDao.queryByOrderId((long) mapTemp.get("storeId"));
执行结果截图:

原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/11209.html