【Java EE 学习 79 下】【动态SQL】【mybatis和spring的整合】
一、动态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的整合】的更多相关文章
- 【Java EE 学习 79 上】【mybatis 基本使用方法】
一.简介 mybatis类似于hibernate,都是简化对数据库操作的框架,但是和hibernate不同的是,mybatis更加灵活,整体来说框架更小,这体现在它需要我们手写SQL语句,而hiber ...
- Java EE 学习(7):IDEA + maven + spring 搭建 web(3)- 配置数据库
参考: https://my.oschina.net/gaussik/blog/513444 注:在阅读本文前,请先阅读: Java EE 学习(5):IDEA + maven + spring 搭建 ...
- Java EE 学习(9):IDEA + maven + spring 搭建 web(5)- 博客文章管理
转载:Gaussic(一个致力于AI研究却不得不兼顾项目的研究生) . 注:在阅读本文前,请先阅读: Java EE 学习(5):IDEA + maven + spring 搭建 web(1) Jav ...
- Java EE 学习(8):IDEA + maven + spring 搭建 web(4)- 用户管理
转载:Gaussic(一个致力于AI研究却不得不兼顾项目的研究生) 注:在阅读本文前,请先阅读: Java EE 学习(5):IDEA + maven + spring 搭建 web(1) ava E ...
- Java EE 学习(6):IDEA + maven + spring 搭建 web(2)- 配置 Spring
参考:https://my.oschina.net/gaussik/blog/513353 注:此文承接上一文:Java EE 学习(5):IDEA + maven + spring 搭建 web(1 ...
- 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 ...
- 【Java EE 学习 67 下】【OA项目练习】【SSH整合JBPM工作流】【JBPM项目实战】
一.SSH整合JBPM JBPM基础见http://www.cnblogs.com/kuangdaoyizhimei/p/4981551.html 现在将要实现SSH和JBPM的整合. 1.添加jar ...
- 【Java EE 学习 24 下】【注解在数据库开发中的使用】【反射+注解+动态代理在事务中的应用service层】
一.使用注解可以解决JavaBean和数据库中表名不一致.字段名不一致.字段数量不一致的问题. 1.Sun公司给jdbc提供的注解 @Table.@Column.@Id.@OneToMany.@One ...
- 【Java EE 学习 75 下】【数据采集系统第七天】【二进制运算实现权限管理】【使用反射初始化权限表】【权限捕获拦截器动态添加权限】
一.使用反射动态添加权限 在该系统中,我使用struts2的时候非常规范,访问的Action的形式都是"ActionClassName_MethodName.action?参数列表" ...
随机推荐
- keylogger
import pyHookimport sysimport pythoncomimport loggingfile_log = 'C:\\important\\log.txt'def OnKeyboa ...
- c#面试题汇总
下面的参考解答只是帮助大家理解,不用背,面试题.笔试题千变万化,不要梦想着把题覆盖了,下面的题是供大家查漏补缺用的,真正的把这些题搞懂了,才能“以不变应万变”.回答问题的时候能联系做过项目的例子是最好 ...
- git查看本地和创建分支、上传分支、提交代码到分支、删除分支等,git分支、git查看本地和创建分支以及上传分支到服务器
以下是git命令行里边的命令操作 ##进入项目目录下 giscafer@Faronsince2016 /G/002_project $ cd Comments ##查看远程分支有哪些 giscafer ...
- 差分进化算法 DE-Differential Evolution
差分进化算法 (Differential Evolution) Differential Evolution(DE)是由Storn等人于1995年提出的,和其它演化算法一样,DE是一种模拟生物进化 ...
- NC凭证接口(Java发送流和处理返回结果)
问题描述: 金融行业在系统模块分为财务和业务两个系统,我公司是负责业务模块系统,NC公司负责财务系统.但是财务有时候需要生成凭证,这时候就涉及业务模块了,我方就需要写NC凭证接口.这时候就需要三方交互 ...
- AssetBundle
AssetBundle是Unity推荐的一种资源打包方式,与不使用AssetBundle相比,它有如下优点: 1.AssetBundle是经过LZMA压缩过的,所以体积更小. 2.可以将AssetBu ...
- Linux系统硬链接和软链接介绍
1.链接的概念 在Linux系统中链接分为硬链接和软连接两种,一种为硬链接,另一种为软连接或符号链接(symbolic Link).ln命令就是创建链接文件的,在默认不带参数的情况下,执行ln命令创建 ...
- tomcat server.xml中文版
原文:http://www.blogjava.net/baoyaer/articles/107278.html Tomcat Server的结构图 该文件描述了如何启动Tomcat Server &l ...
- web自动化工具-livereload
web自动化工具-livereload livereload是一个很神奇的工具,主要解放了F5键,监听文件变动,整个页面自动刷新.可搭载gulp等构建工具使用.和liveStyle 针对样式文件相比, ...
- Android 系统工具类SystemUtils
包含的功能有: 获取系统中所有APP应用.获取用户安装的APP应用.根据包名和Activity启动类查询应用信息.跳转到WIFI设置.WIFI网络开关.移动网络开关.GPS开关 当前若关则打开 当前若 ...