《Java EE核心框架实战》—— 2.6 动态SQL的使用

    xiaoxiao2024-03-19  106

    本节书摘来异步社区《Java EE核心框架实战》一书中的第2章,第2.6节,作者: 高洪岩,更多章节内容可以访问云栖社区“异步社区”公众号查看。

    2.6 动态SQL的使用

    MyBatis框架还支持动态SQL标签的使用,而且某些标签的使用率还非常高。

    2.6.1插入null值时的处理第1种方法—jdbcType

    创建名为dynSqlTest的Web项目,创建名为test1的Servlet对象,核心代码如下。

    public class test1 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Userinfo userinfo = new Userinfo(); userinfo.setUsername("中国"); userinfo.setPassword(null); userinfo.setAge(); userinfo.setInsertdate(new Date()); SqlSession sqlSessionRef = GetSqlSession.getSqlSession(); sqlSessionRef.insert("insertUserinfo", userinfo); sqlSessionRef.commit(); sqlSessionRef.close(); } }``` 在映射文件userinfoMapping.xml中添加如下配置。

    select idauto.nextval from dual insert into userinfo(id,username,password,age,insertdate) values(#{id},#{username},#{password},#{age},#{insertdate})`程序运行后出现如下异常信息。

    ### Error updating database. Cause: org.apache.ibatis.type.TypeException: Error setting null for parameter #3 with JdbcType OTHER . Try setting a different JdbcType for this parameter or a different jdbcTypeForNull configuration property. Cause: java.sql.SQLException: 无效的列类型: 1111``` 从出错信息中可以看到,是用null值对password字段进行了设置,造成MyBatis无法识别,这种情况可以通过设置映射的数据类型来解决。更改映射配置userinfoMapping.xml的代码如下。

    <?xml version="1.0" encoding="UTF-8" ?> select idauto.nextval from dual insert into userinfo(id,username,password,age,insertdate) values(#{id,jdbcType=INTEGER},#{username,jdbcType=VARCHAR},#{password, jdbcType=VARCHAR},#{age,jdbcType=INTEGER},#{insertdate,jdbcType=TIMESTAMP})`这里在#{}格式中加入了数据类型的声明,这样可以明确地告诉MyBatis框架如果遇到null值该如何处理。再次运行程序,成功插入数据表,运行结果如图2-5所示。

    2.6.2 插入null值时的处理第2种方法—< if>

    通过在#{}格式中加入jdbcType即可避免插入null值时的异常,其实使用动态SQL标签也可以达到同样的效果。

    在映射文件userinfoMapping.xml添加如下代码。

    <insert id="insertUserinfo2" parameterType="orm.Userinfo"> <selectKey keyProperty="id" order="BEFORE" resultType="java.lang.Long"> select idauto.nextval from dual </selectKey> <if test="password!=null"> insert into userinfo(id,username,password,age,insertdate) values(#{id},#{username},#{password},#{age},#{insertdate}) </if> <if test="password==null"> insert into userinfo(id,username,age,insertdate) values(#{id},#{username},#{age},#{insertdate}) </if> </insert>``` 创建名为test2的Servlet,核心代码如下。

    public class test2 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Userinfo userinfo1 = new Userinfo(); userinfo1.setUsername("英国"); userinfo1.setPassword(null); userinfo1.setAge(); userinfo1.setInsertdate(new Date()); Userinfo userinfo2 = new Userinfo(); userinfo2.setUsername("法国"); userinfo2.setPassword("法国人"); userinfo2.setAge(); userinfo2.setInsertdate(new Date()); SqlSession sqlSessionRef = GetSqlSession.getSqlSession(); sqlSessionRef.insert("insertUserinfo2", userinfo1); sqlSessionRef.insert("insertUserinfo2", userinfo2); sqlSessionRef.commit(); sqlSessionRef.close(); }}`程序运行后,成功向数据表中插入两条记录,如图2-6所示。

    2.6.3 < choose>标签的使用

    < choose>标签的作用是在众多的条件中选择出一个条件,它有些类似于Java语言中switch语句的作用。

    在映射文件userinfoMapping.xml中添加如下配置代码。

    <select id="selectUserinfo1" parameterType="orm.Userinfo" resultType="map"> select * from userinfo where 1=1 <choose> <when test="username!=null">and username like '%'||#{username}||'%'</when> <when test="password!=null">and password like '%'||#{password}||'%'</when> <otherwise>and age=200</otherwise> </choose> </select>``` 创建名为test3的Servlet对象,核心代码如下。

    public class test3 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Userinfo userinfo1 = new Userinfo(); userinfo1.setUsername("英"); Userinfo userinfo2 = new Userinfo(); userinfo2.setPassword("法"); Userinfo userinfo3 = new Userinfo(); SqlSession sqlSessionRef = GetSqlSession.getSqlSession(); List listMap1 = sqlSessionRef.selectList("selectUserinfo1",

    userinfo1);

    for (int i = 0; i < listMap1.size(); i++) { Map eachMap = listMap1.get(i); System.out.println("listMap1中的内容: " + eachMap.get("ID") + " "

    + eachMap.get("USERNAME") + " " + eachMap.get("PASSWORD") + " " + eachMap.get("AGE") + " " + eachMap.get("INSERTDATE"));

    } List listMap2 = sqlSessionRef.selectList("selectUserinfo1",

    userinfo2);

    for (int i = 0; i < listMap2.size(); i++) { Map eachMap = listMap2.get(i); System.out.println("listMap2中的内容: " + eachMap.get("ID") + " "

    + eachMap.get("USERNAME") + " " + eachMap.get("PASSWORD") + " " + eachMap.get("AGE") + " " + eachMap.get("INSERTDATE"));

    } List listMap3 = sqlSessionRef.selectList("selectUserinfo1",

    userinfo3);

    for (int i = 0; i < listMap3.size(); i++) { Map eachMap = listMap3.get(i); System.out.println("listMap3中的内容: " + eachMap.get("ID") + " "

    + eachMap.get("USERNAME") + " " + eachMap.get("PASSWORD") + " " + eachMap.get("AGE") + " " + eachMap.get("INSERTDATE"));

    } sqlSessionRef.commit(); sqlSessionRef.close(); }}`数据表userinfo中的内容如图2-7所示。

    程序运行后,在控制台输出如图2-8所示的信息。

    2.6.4 < set>标签的使用

    < set>标签可以用在update语句中,作用是动态指定要更新的列。

    在映射文件userinfoMapping.xml中添加如下映射代码。

    <update id="updateUserinfo" parameterType="orm.Userinfo"> update userinfo <set> <if test="username!=null">username=#{username},</if> <if test="password!=null">password=#{password},</if> <if test="age!=null">age=#{age},</if> <if test="insertdate!=null">insertdate=#{insertdate}</if> </set> <if test="id!=null">where id=#{id}</if> </update>``` 创建名为test4的Servlet对象,核心代码如下。

    public class test4 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Userinfo userinfo = new Userinfo(); userinfo.setId(); userinfo.setUsername(null); userinfo.setPassword("新密码"); userinfo.setAge(); userinfo.setInsertdate(new Date()); SqlSession sqlSessionRef = GetSqlSession.getSqlSession(); sqlSessionRef.update("updateUserinfo", userinfo); sqlSessionRef.commit(); sqlSessionRef.close(); }}`程序运行结果如图2-9所示。

    2.6.5 < foreach>标签的使用

    < foreach>标签有循环的功能,可以用来生成有规律的SQL语句。

    < foreach>标签主要的属性有item、index、collection、open、separator和close。

    item表示集合中每一个元素进行迭代时的别名,index指定一个名字,用于表示在迭代过程中,每次迭代到的位置,open表示该语句以什么开始,separator表示在每次迭代之间以什么符号作为分隔符,close表示该语句以什么结束。

    在映射文件userinfoMapping.xml中添加如下配置代码。

    <select id="selectUserinfo2" parameterType="list" resultType="map"> select * from userinfo where id in <foreach collection="list" item="eachId" index="currentIndex" open="(" separator="," close=")"> #{eachId} </foreach> </select> <select id="selectUserinfo3" parameterType="orm.QueryUserinfo" resultType="map"> select * from userinfo where id in <foreach collection="idList" item="eachId" index="currentIndex" open="(" separator="," close=")"> #{eachId} </foreach> and username like '%'||#{username}||'%' </select> <select id="selectUserinfo4" parameterType="map" resultType="map"> select * from userinfo where id in <foreach collection="idList" item="eachId" index="currentIndex" open="(" separator="," close=")"> #{eachId} </foreach> and username like '%'||#{username}||'%' </select>``` 创建名为test5的Servlet,核心代码如下。

    public class test5 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // id的值来自于List List list = new ArrayList(); list.add(1); list.add(3); list.add(5); SqlSession sqlSessionRef = GetSqlSession.getSqlSession(); List listMap1 = sqlSessionRef.selectList("selectUserinfo2", list); for (int i = 0; i < listMap1.size(); i++) { Map eachMap = listMap1.get(i); System.out.println("list1中的内容: " + eachMap.get("ID") + " "

    + eachMap.get("USERNAME") + " " + eachMap.get("PASSWORD") + " " + eachMap.get("AGE") + " " + eachMap.get("INSERTDATE"));

    } // id的值来自于QueryUserinfo实体中的List QueryUserinfo queryUserinfo = new QueryUserinfo(); queryUserinfo.setUsername("法"); queryUserinfo.getIdList().add(198); queryUserinfo.getIdList().add(199); listMap1 = sqlSessionRef.selectList("selectUserinfo3", queryUserinfo); for (int i = 0; i < listMap1.size(); i++) { Map eachMap = listMap1.get(i); System.out.println("list2中的内容: " + eachMap.get("ID") + " "

    + eachMap.get("USERNAME") + " " + eachMap.get("PASSWORD") + " " + eachMap.get("AGE") + " " + eachMap.get("INSERTDATE"));

    } // id的值来自于Map中的List Map paramMap = new HashMap(); paramMap.put("username", "5"); paramMap.put("idList", list); listMap1 = sqlSessionRef.selectList("selectUserinfo4", paramMap); for (int i = 0; i < listMap1.size(); i++) { Map eachMap = listMap1.get(i); System.out.println("list3中的内容: " + eachMap.get("ID") + " "

    + eachMap.get("USERNAME") + " " + eachMap.get("PASSWORD") + " " + eachMap.get("AGE") + " " + eachMap.get("INSERTDATE"));

    } sqlSessionRef.commit(); sqlSessionRef.close(); }}`运行程序后,控制台输出如图2-10所示的结果。

    本文仅用于学习和交流目的,不代表异步社区观点。非商业转载请注明作译者、出处,并保留本文的原始链接。

    相关资源:敏捷开发V1.0.pptx
    最新回复(0)