以下为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/11209.html