我们当时刚开始做的时候,是需要在Controller中判断SQL是否已经有条件了,因为SQL语句需要拼接起来....这样干的话,就非常容易出错的。
如下的代码,如果有多个条件的话,那么拼接起来很容易出错!
public String listUI () { String hql = "FROM Info i " ; List<Object> objectList = new ArrayList <>(); if (info != null ) { if (StringUtils.isNotBlank(info.getTitle())) { hql += "where i.title like ?" ; objectList.add("%" + info.getTitle() + "%" ); } } infoList = infoServiceImpl.findObjects(hql,objectList); ActionContext.getContext().getContextMap().put("infoTypeMap" , Info.INFO_TYPE_MAP); return "listUI" ; }
后来,我们觉得这样不好,于是就专门写了一个查询助手类:
import java.util.ArrayList;import java.util.List;public class QueryHelper { private String fromClause = "" ; private String whereClause = "" ; private String orderbyClause = "" ; private List<Object> objectList; public static String ORDER_BY_ASC = "asc" ; public static String ORDER_BY_DESC = "desc" ; public QueryHelper (Class aClass, String alias) { fromClause = " FROM " + aClass.getSimpleName() + " " + alias; } public QueryHelper addCondition (String condition, Object... objects) { if (whereClause.length() > 0 ) { whereClause += " AND " + condition; } else { whereClause += " WHERE" + condition; } if (objects == null ) { objectList = new ArrayList <>(); } for (Object object : objects) { objectList.add(object); } return this ; } public QueryHelper orderBy (String property, String order) { if (orderbyClause.length() > 0 ) { orderbyClause += " , " + property +" " + order; } else { orderbyClause += " ORDER BY " + property+" " + order; } return this ; } public String returnHQL () { return fromClause + whereClause + orderbyClause; } public List<Object> getObjectList () { return objectList; } }
这样一来的话,我们就不用自己手动拼接了,给我们的查询助手类去拼接就好了。
而如果我们使用Mybatis的话,就可以免去查询助手类了。因为Mybatis内部就有动态SQL的功能【动态SQL就是自动拼接SQL语句】 !
8.1 动态查询
<!--多条件查询【动态SQL】--> <!--会自动组合成一个正常的WHERE字句--> <!--name值会从map中寻找--> <select id="findByCondition" resultMap="studentMap" parameterType="map" > select * from students <where> <if test="name!=null" > and name=#{name} </if > <if test="sal!=null" > and sal < #{sal} </if > </where> </select>
查询出来小于9000块的人
public List<Student> findByCondition (String name,Double sal) throws Exception { SqlSession sqlSession = MybatisUtil.getSqlSession(); try { Map<String, Object> map = new HashMap (); map.put("name" , name); map.put("sal" , sal); return sqlSession.selectList("StudentID.findByCondition" , map); }catch (Exception e){ e.printStackTrace(); sqlSession.rollback(); throw e; }finally { MybatisUtil.closeSqlSession(); } } public static void main (String[] args) throws Exception { StudentDao studentDao = new StudentDao (); List<Student> students = studentDao.findByCondition(null ,9000D ); for (Student student : students) { System.out.println(student.getId() + "---" + student.getName() + "----" + student.getSal()); } }
8.2 动态更新
<!--动态更新--> <!--不要忘了逗号--> <update id="updateByConditions" parameterType="map" > update students <set> <if test="name!=null" > name = #{name}, </if > <if test="sal!=null" > sal = #{sal}, </if > </set> where id = #{id} </update>
给出三个更新的字段
public void updateByConditions (int id,String name,Double sal) throws Exception { SqlSession sqlSession = MybatisUtil.getSqlSession(); try { Map<String, Object> map = new HashMap (); map.put("id" , id); map.put("name" , name); map.put("sal" , sal); sqlSession.update("StudentID.updateByConditions" , map); sqlSession.commit(); }catch (Exception e){ e.printStackTrace(); sqlSession.rollback(); throw e; }finally { MybatisUtil.closeSqlSession(); } } public static void main (String[] args) throws Exception { StudentDao studentDao = new StudentDao (); studentDao.updateByConditions(2 ,"haha" ,500D ); }
8.3 动态删除
我们现在使用的是Mybatis,SQL语句是自己写的。所以我们可以写下如下的SQL来进行删除
delete from students where id in (?,?,?,?);
而我们的Mybatis又支持动态SQL,所以删除起来就非常方便了!
<delete id="deleteByConditions" parameterType="int" > <!-- foreach用于迭代数组元素 open表示开始符号 close表示结束符合 separator表示元素间的分隔符 item表示迭代的数组,属性值可以任意,但提倡与方法的数组名相同 #{ids}表示数组中的每个元素值 --> delete from students where id in <foreach collection="array" open="(" close=")" separator="," item="ids" > #{ids} </foreach> </delete>
删除编号为2,3,4的记录
public void deleteByConditions (int ... ids) throws Exception { SqlSession sqlSession = MybatisUtil.getSqlSession(); try { sqlSession.delete("StudentID.deleteByConditions" , ids); sqlSession.commit(); }catch (Exception e){ e.printStackTrace(); sqlSession.rollback(); throw e; }finally { MybatisUtil.closeSqlSession(); } } public static void main (String[] args) throws Exception { StudentDao studentDao = new StudentDao (); studentDao.deleteByConditions(2 ,3 ,4 ); }
8.4 动态插入
我们要想动态插入的话,就比其他的DML语句稍微复杂一点,因为它有两部分是不确定的,平常的SQL语句是这样的:
insert into student(id,name,sal) values (?,?,?)
SQL代码块是不能像之前那样帮我们自动去除多余的逗号的,因此我们需要使用trim标签来自己手动去除...
编写insertSQL语句的时候,不要忘了写()括号。
<sql id ="key" > <trim suffixOverrides ="," > <if test ="id!=null" > id, </if > <if test ="id!=null" > name, </if > <if test ="id!=null" > sal, </if > </trim > </sql > <sql id ="value" > <trim suffixOverrides ="," > <if test ="id!=null" > #{id}, </if > <if test ="id!=null" > #{name}, </if > <if test ="id!=null" > #{sal}, </if > </trim > </sql > <insert id ="insertByConditions" parameterType ="zhongfucheng.Student" > insert into students (<include refid ="key" /> ) values (<include refid ="value" /> ) </insert >
测试三个不同内容的数据
public void insertByConditions (Student student) throws Exception { SqlSession sqlSession = MybatisUtil.getSqlSession(); try { sqlSession.insert("StudentID.insertByConditions" , student); sqlSession.commit(); }catch (Exception e){ e.printStackTrace(); sqlSession.rollback(); throw e; }finally { MybatisUtil.closeSqlSession(); } } public static void main (String[] args) throws Exception { StudentDao studentDao = new StudentDao (); studentDao.insertByConditions(new Student (55 , null , null )); studentDao.insertByConditions(new Student (66 , "haxi" , null )); studentDao.insertByConditions(new Student (77 , null , 3999d )); }