一、动态SQL

  什么是动态SQL,就是在不同的条件下,sql语句不相同的意思,曾经在“酒店会员管理系统”中写过大量的多条件查询,那是在SSH的环境中,所以只能在代码中进行判断,以下是其中一个多条件查询的例子:

 public Collection<Card> getCardsByMN(int requestPage, String cardId,
String userName, String typeofcredential, String sex,
String integral) {
int m=(requestPage-1)*PageSplitConfig.pageSize;
int n=PageSplitConfig.pageSize;
String sql="from Card where 1=1 ";
if(cardId!=null&&!"".equals(cardId.trim())){
sql=sql+" and cardId='"+cardId.trim()+"'";
}
if(userName!=null&&!"".equals(userName.trim())){
sql=sql+" and userName='"+userName.trim()+"'";
}
if(typeofcredential!=null&&!"".equals(typeofcredential.trim())&&!"''".equals(typeofcredential.trim())){
sql=sql+" and credentialType.credentialTypeName='"+typeofcredential.trim()+"'";
}
if(sex!=null&&!"".equals(sex.trim())&&!"不限".equals(sex.trim())){
sql=sql+" and sex='"+sex+"'";
}
if(integral!=null&&!"".equals(integral.trim())){
sql=sql+" and integral='"+integral.trim()+"'";
}
return this.cardDao.getAllCards(sql,m,n);
}

  这是在Service方法中进行多条件的判断并最终形成多条件查询的SQL代码的方法,最终该SQL代码会被DAO执行。

  和这个形式非常相似,Mybatis中对这种情况充分做了考虑,它使用配置文件的方式以XML标签的形式对以上的逻辑进行了重新描述。

  在SSH环境中,由于Hibernate不支持动态SQL,所以只能在代码中进行SQL的动态拼接,这么做的弊端是显而易见的,而且该弊端在我的“酒店会员管理系统”中充分的暴露了出来。我的酒店会员管理系统中对对于日志的处理有两种形式,一种是多条件查询日志,一种是导出日志,这两个功能都涉及到了动态SQL拼接的问题,但是由于不是同一个Service方法,所以动态SQL的拼接必须重写两次,这就显得非常的麻烦,而且非常容易发生错误。但是如果使用Mybatis的话这种麻烦就会非常容易避免了。

  1.动态SQL之多条件查询

  这里的需求假设为:传入一个Student对象,程序会根据该对象属性值是否为空作为依据判断是否将该条件拼接到sql中;在映射文件中的配置方式和普通查询相比使用的标签都是select标签,但是里面需要使用mybatis中的逻辑判断标签进行判断:

<!-- 这里是动态查询的方法 -->
<select id="selectAllByCondition" parameterType="com.kdyzm.domain.Student"
resultMap="studentMap">
select * from student
<where>
<if test="id !=null">
and studentid=#{id}
</if>
<if test="name !=null">
and name=#{name}
</if>
<if test="age!=null">
and age=#{age}
</if>
<if test="password !=null">
and password=#{password}
</if>
</where>
</select>

    where标签是一个非常智能的标签,它能够通过不同的条件自动判断是否需要加上where关键字,如果你传入的对象中的属性值都为空,那么它就不会加上where关键字俄而且不需要使用where 1=1 这种写法;每个test中都需要加上and ,if标签也是智能标签,不赘述。

    java代码:

 String statement = "com.kdyzm.domain.Student.selectAllByCondition";
Student student = new Student();
student.setId(1);
// student.setAge(13);
List<Student> list = session.selectList(statement, student);
for (Student stu : list) {
System.out.println(stu);
}

  2.动态SQL之多条件更新

    其方法原理和多条件查询有诸多相似之处,不赘述。

 <!-- 这里是动态更新的方法 -->
<update id="updateStudentByCandition" parameterType="com.kdyzm.domain.Student">
update student
<set>
<!-- <if test="id!=null">
studentid=#{id}
</if> -->
<if test="name!=null">
name=#{name}
</if>
<if test="password!=null">
password=#{password}
</if>
<if test="age!=null">
age=#{age}
</if>
<if test="clazz!=null">
clazz=#{clazz}
</if>
</set>
where studentid=#{id}
</update>

    这里的动态sql的使用方法需要注意的事项:必须至少有一个字段不为空,否则就会报错;我本想着如果将以上代码中的注释部分放开的话就能够避免这种情况了,但是这只是理想状况,如果加上了id的判断,就会出错,原因未知。

二、mybatis和spring的整合

  项目源代码:https://github.com/kdyzm/day79_2_ssi

  mybatis框架的功能和hibernate功能相似,既然hibernate能够和spring整合并和struts框架整合之后形成所谓的SSH框架,那么mybatis框架能不能和spring、hibernate整合之后形成SSI框架呢?(Mybatis前身是Ibatis,到现在为止该框架中的很多包结构仍然采用ibatis的称呼,所以mybatis只是换了个名称而已,这里仍然使用SSI的称呼也只是从众而已),肯定是可以的。hibernate和Mybatis一样,就算没有spring也能够独立运行,但是既然要和spring整合了,那么Session对象的创建一定都交给了spring容器,这就需要一个中间的插件了,hibernate和spring整合的时候有一个org.springframework.orm-3.1.0.RELEASE.jar包,该jar包是hibernate和spring整合的关键,包括整合的过程中使用到的“本地会话工厂Bean”以及事务管理器,在该包中都有定义,spring发行版中会自带和hibernate整合相关的jar包,但是mybatis并没有这种待遇,mybatis为了能够为了和spring进行整合,它自己开发了和spring整合的jar包。这个jar包需要我们自己到网上下载。

  和spring整合需要的jar包的下载地址:https://github.com/mybatis/spring

  这里我是用了spring3.2的版本,有很多人习惯使用mybatis-spring-1.0.0版本的插件,但是在spring3.2版本下使用该插件的话会出现直接抛出某个异常,可以使用mybatis-spring-1.1.1版本的插件解决该异常,而且使用前者查询出来的结果需要强制类型转换,使用后者的时候就不需要进行强制类型转换。

  mybatis和spring整合的过程与hibernate和spring整合的过程几乎完全相同,有了hibernate和spring整合的经验,mybatis和spring整合就太简单了。

  第一步,加入所有需要的jar包。

    使用的spring的版本:spring3.2

    使用的数据库连接池:c3p0-0.9.5

    使用的mybatis版本:mybatis3.1.1

    使用的mybatis-spring版本:mybatis-spring-1.1.1

    这里就不和struts2进行整合了,实际上和struts2的整合就完全没有必须要了,实际上和struts2的整合还是和spring的整合,略。

    jar包一览图:

 c3p0-0.9.5.jar
com.springsource.com.mchange.v2.c3p0-0.9.1.2.jar
com.springsource.net.sf.cglib-2.2.0.jar
com.springsource.org.aopalliance-1.0.0.jar
com.springsource.org.apache.commons.codec-1.3.0.jar
com.springsource.org.apache.commons.logging-1.1.1.jar
com.springsource.org.aspectj.tools-1.6.6.RELEASE.jar
com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
com.springsource.org.quartz-1.6.2.jar
commons-lang-2.5.jar
log4j.jar
mchange-commons-java-0.2.9.jar
mybatis-3.1.1.jar
mybatis-spring-1.1.1.jar
mysql-connector-java-5.1.18-bin.jar
org.springframework.aop-3.1.0.RELEASE.jar
org.springframework.asm-3.1.0.RELEASE.jar
org.springframework.aspects-3.1.0.RELEASE.jar
org.springframework.beans-3.1.0.RELEASE.jar
org.springframework.context-3.1.0.RELEASE.jar
org.springframework.context.support-3.1.0.RELEASE.jar
org.springframework.core-3.1.0.RELEASE.jar
org.springframework.expression-3.1.0.RELEASE.jar
org.springframework.jdbc-3.1.0.RELEASE.jar
org.springframework.orm-3.1.0.RELEASE.jar
org.springframework.transaction-3.1.0.RELEASE.jar
org.springframework.web-3.1.0.RELEASE.jar
org.springframework.web.servlet-3.1.0.RELEASE.jar
slf4j-api-1.5.8.jar
slf4j-log4j12.jar

整合需要的jar包

  第二步,准备数据源需要的配置文件

    这里使用jdbc.properties,将其放到classpath的根目录下

 jdbc.username=root
jdbc.password=5a6f38
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.driver=com.mysql.jdbc.Driver #C3p0 Configuration
c3p0.minPoolSize=2
c3p0.maxPoolSize=10
c3p0.initPoolSize=2
c3p0.increment=2

  第三步,不需要准备mybatis-config.xml配置文件

    因为该配置文件中需要配置的所有内容都转移到了spring中的配置文件中进行配置了。

  第四步,配置spring的配置文件,这里的配置过程和hibernate与spring整合的的配置过程几乎完全相同,不赘述。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans file:///D:\程序\java\Spring\spring-framework-4.2.1\spring-framework-4.2.1.RELEASE\schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context file:///D:\程序\java\Spring\spring-framework-4.2.1\spring-framework-4.2.1.RELEASE\schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/aop file:///D:\程序\java\Spring\spring-framework-4.2.1\spring-framework-4.2.1.RELEASE\schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/tx file:///D:\程序\java\Spring\spring-framework-4.2.1\spring-framework-4.2.1.RELEASE\schema/tx/spring-tx-2.5.xsd">
<context:component-scan base-package="com.kdyzm.dao"></context:component-scan>
<context:property-placeholder location="classpath:jdbc.properties" />
<!-- 第一步还是配置数据源 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
<property name="jdbcUrl" value="${jdbc.url}"></property>
<property name="driverClass" value="${jdbc.driver}"></property> <property name="initialPoolSize" value="${c3p0.initPoolSize}"></property>
<property name="minPoolSize" value="${c3p0.minPoolSize}"></property>
<property name="maxPoolSize" value="${c3p0.maxPoolSize}"></property>
<property name="acquireIncrement" value="${c3p0.increment}"></property>
</bean>
<!-- 下一步,配置Session创建工厂 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<!-- <property name="configLocation" value="classpath:mybatis-config.xml"></property> -->
<property name="mapperLocations">
<list>
<value>classpath:com/kdyzm/domain/Student.xml</value>
</list>
</property>
</bean>
<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory"></constructor-arg>
</bean>
</beans>

    重点是黄色背景部分的配置,形式上和hibernate的和spring的整合过程一模一样,只是换了个类而已。

    以上没有配置事务,但是已经能够进行正常测试了。

    测试的过程略,想看直接到git中的相应项目中查看。

  第五步:事务的配置

  和hibernate和spring整合过程中事务的配置方式如出一辙,但是需要注意下面黄色背景部分的配置,事务管理器和hibernate使用的org.springframework.orm.hibernate3.HibernateTransactionManager是不相同的。

<!-- 事务的配置 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="save*" isolation="DEFAULT" read-only="false" propagation="REQUIRED"/>
<tx:method name="update*" isolation="DEFAULT" read-only="false" propagation="REQUIRED"/>
<tx:method name="new*" isolation="DEFAULT" read-only="false" propagation="REQUIRED"/>
<tx:method name="delete*" isolation="DEFAULT" read-only="false" propagation="REQUIRED"/> <tx:method name="get*" read-only="true"/>
<tx:method name="select*" read-only="true"/>
<tx:method name="find*" read-only="true"/> <!-- 其它方法默认全部加上事务 -->
<tx:method name="*" isolation="DEFAULT" read-only="false" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice> <aop:config>
<aop:pointcut expression="execution(* com.kdyzm.service.*.*(..))" id="txAop"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txAop"/>
</aop:config>

三、进行测试即可,测试使用的DAO/Service等在项目中。

  产生的疑问:保存Student对象的同时不能级联保存Clazz的问题,由于使用的是OGNL表达式,所以在前端页面中使用的Struts2的规则可以仿照这搬过来。

  测试代码:

StudentService service=(StudentService) context.getBean("studentService");
ClazzService clazzService=(ClazzService) context.getBean("clazzService");
Student student=new Student();
student.setId(8);
student.setName("小吧");
student.setPassword("xiaozhang");
student.setAge(120);
Clazz clazz=clazzService.getClazzById(2);
student.setClazz(clazz);
int result=service.saveStudent(student);
System.out.println("执行结果是:"+result);

  配置文件:

<insert id="insertIntoStudent" parameterType="com.kdyzm.domain.Student">
insert into
student(studentid,name,password,age,clazz)
values(#{id},#{name},#{password},#{age},#{clazz.id})
</insert>

  注意在这里的写法:如果直接写#{clazz},肯定直接报错,因为数据库中的字段类型是int类型,但是clazz在这里是Clazz对象。

【Java EE 学习 79 下】【动态SQL】【mybatis和spring的整合】的更多相关文章

  1. 【Java EE 学习 79 上】【mybatis 基本使用方法】

    一.简介 mybatis类似于hibernate,都是简化对数据库操作的框架,但是和hibernate不同的是,mybatis更加灵活,整体来说框架更小,这体现在它需要我们手写SQL语句,而hiber ...

  2. Java EE 学习(7):IDEA + maven + spring 搭建 web(3)- 配置数据库

    参考: https://my.oschina.net/gaussik/blog/513444 注:在阅读本文前,请先阅读: Java EE 学习(5):IDEA + maven + spring 搭建 ...

  3. Java EE 学习(9):IDEA + maven + spring 搭建 web(5)- 博客文章管理

    转载:Gaussic(一个致力于AI研究却不得不兼顾项目的研究生) . 注:在阅读本文前,请先阅读: Java EE 学习(5):IDEA + maven + spring 搭建 web(1) Jav ...

  4. Java EE 学习(8):IDEA + maven + spring 搭建 web(4)- 用户管理

    转载:Gaussic(一个致力于AI研究却不得不兼顾项目的研究生) 注:在阅读本文前,请先阅读: Java EE 学习(5):IDEA + maven + spring 搭建 web(1) ava E ...

  5. Java EE 学习(6):IDEA + maven + spring 搭建 web(2)- 配置 Spring

    参考:https://my.oschina.net/gaussik/blog/513353 注:此文承接上一文:Java EE 学习(5):IDEA + maven + spring 搭建 web(1 ...

  6. Java EE 学习(5):IDEA + maven + spring 搭建 web(1)

    参考:http://www.cnblogs.com/lonelyxmas/p/5397422.html http://www.ctolib.com/docs-IntelliJ-IDEA-c--1590 ...

  7. 【Java EE 学习 67 下】【OA项目练习】【SSH整合JBPM工作流】【JBPM项目实战】

    一.SSH整合JBPM JBPM基础见http://www.cnblogs.com/kuangdaoyizhimei/p/4981551.html 现在将要实现SSH和JBPM的整合. 1.添加jar ...

  8. 【Java EE 学习 24 下】【注解在数据库开发中的使用】【反射+注解+动态代理在事务中的应用service层】

    一.使用注解可以解决JavaBean和数据库中表名不一致.字段名不一致.字段数量不一致的问题. 1.Sun公司给jdbc提供的注解 @Table.@Column.@Id.@OneToMany.@One ...

  9. 【Java EE 学习 75 下】【数据采集系统第七天】【二进制运算实现权限管理】【使用反射初始化权限表】【权限捕获拦截器动态添加权限】

    一.使用反射动态添加权限 在该系统中,我使用struts2的时候非常规范,访问的Action的形式都是"ActionClassName_MethodName.action?参数列表" ...

随机推荐

  1. 一道javascript数组操作题

    题目如下: var arr = ['100px','abc'-6,[],-98765,34,-2,0,'300',,function(){alert(1);}, null, document, [], ...

  2. css悬浮

    <!DOCTYPE html><html><head>  <meta charset="UTF-8">    <title&g ...

  3. RabbitMQ学习系列(五): RPC 远程过程调用

    前面讲过一些RabbitMQ的安装和用法,也说了说RabbitMQ在一般的业务场景下如何使用.不知道的可以看我前面的博客,http://www.cnblogs.com/zhangweizhong/ca ...

  4. OncrickListener的实现

    在Java中实现的监控事件的方法 button.addActionListener(new ActionListener() { @Override public void actionPerform ...

  5. vcpu

    qemu_kvm_start_vcpu --> qemu_init_vcpu --> x86_cpu_realizefn -->  x86_cpu_common_class_init ...

  6. eclipse项目打包

    一.直接在eclipse里export即可 二.如果需要打好的包可以直接使用,则需要修改包中的META-INF文件夹中的MANIFEST.MF文件,主要可能会涉及到的字段主要有以下两个. 1.Main ...

  7. Maven的Missing artifact问题解决

     Maven的Missing artifact问题解决   今天在创建一个新的Maven项目时,在其中添加了很多依赖.刚开始为了避免错误就每添加一次,保存一下,Eclipse就会下载相应的包.最后为了 ...

  8. AFNetworking 与 gbk 编码格式后台数据的使用

    仅针,后台数据为GBK编码时的AFNetWorking 使用情况: 1. Request failed: unacceptable content-type: text/html     soluti ...

  9. No.23

    腓利比书3:19:"他们的结局就是沉沦,他们的神就是自己的肚腹,他们以自己的羞辱为荣耀,专以地上的事为念". 谨记!

  10. asp:Repeater实例备忘

    1.前置部分 <asp:Repeater ID="rptPlanNo" runat="server" OnItemDataBound="rptP ...