文章转载自:https://www.jiweichengzhu.com/article/987bd23b785947e98d0609c1bb492b12
如果还有问题,加群交流:686430774
案例代码下载,请移步原文链接!
在Mybatis问世之后,基于SSI框架演化出了SSM框架,struts + spring + mybatis,开发起来方便了很多,几乎可以只在mapper中写sql,而不用写具体的dao调用实现了,mybatis会动态的帮我们生成具体实现,我们只需要在接口中写mapper中对应的方法即可。
之前的笔记中,在Struts框架注解版的基础上,也写了相关的demo,整理出来分享给大家,主要变化就是在dao层,所以struts和spring并没有多少变化。
框架版本:
Struts:2.3.24
Spring:4.1.5.RELEASE
Mybatis:3.3.0
applicationContext.xm
<?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:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd"> <!-- 开启注解扫描,并指定路径 --> <context:component-scan base-package="com.ssm"/> <!-- 加载配置文件,也可以使用下面的方式,更加简洁 <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations"> <list> <value>classpath:jdbc.properties</value> </list> </property> </bean> --> <!-- 加载配置文件 --> <context:property-placeholder location="classpath:jdbc.properties"/> <!-- 数据源配置 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> <property name="driverClass" value="${jdbc.driverClass}"/> <property name="jdbcUrl" value="${jdbc.url}"/> <property name="user" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> <!--连接池中保留的最大连接数。Default: 15 --> <property name="maxPoolSize" value="100"/> <!--连接池中保留的最小连接数。 --> <property name="minPoolSize" value="1"/> <!--初始化时获取的连接数,取值应在minPoolSize与maxPoolSize之间。Default: 3 --> <property name="initialPoolSize" value="10"/> <!--最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0 --> <property name="maxIdleTime" value="30"/> <!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 --> <property name="acquireIncrement" value="5"/> <!-- JDBC的标准参数,用以控制数据源内加载的PreparedStatements数量。Default: 0 --> <!-- 但由于预缓存的statements 属于单个connection而不是整个连接池。 --> <!-- 所以设置这个参数需要考虑到多方面的因素。 如果maxStatements与maxStatementsPerConnection均为0,则缓存被关闭。 --> <property name="maxStatements" value="0"/> <!--每60秒检查所有连接池中的空闲连接。Default: 0 --> <property name="idleConnectionTestPeriod" value="60"/> <!--定义在从数据库获取新连接失败后重复尝试的次数。Default: 30 --> <property name="acquireRetryAttempts" value="30"/> <!-- 获取连接失败将会引起所有等待连接池来获取连接的线程抛出异常。 --> <!-- 但是数据源仍有效 保留,并在下次调用getConnection()的时候继续尝试获取连接。 --> <!-- 如果设为true,那么在尝试获取连接失败后该数据源将申明已断开并永久关闭。Default: false --> <property name="breakAfterAcquireFailure" value="true"/> <!-- 因性能消耗大请只在需要的时候使用它。如果设为true那么在每个connection提交的 时候都将校验其有效性。 --> <!-- 建议使用idleConnectionTestPeriod或automaticTestTable,等方法来提升连接测试的性能。Default: false --> <property name="testConnectionOnCheckout" value="false"/> </bean> <!-- 类似于ibatis的sql模板,用来和数据库进行交互 --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <!-- 数据源 --> <property name="dataSource" ref="dataSource"/> <!-- 指定mybatis配置文件的路径 --> <property name="configLocation" value="classpath:mybatis-config.xml"/> <!-- 下面两个选项这里配置了,mybatis配置文件中就可以省略 --> <!-- 指定mapper映射文件的路径 --> <!-- <property name="mapperLocations" value="classpath:mapper/*.xml"/>--> <!-- 配置alias的路径 --> <!-- <property name="typeAliasesPackage" value="com.ssm.entity"/>--> </bean> <!-- mapper扫描配置,这个相比ibatis来说,就是很大的改进了,可以省去很多的代码,直接通过代理动态的调用 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <!-- mapper扫描路径 --> <property name="basePackage" value="com.ssm.dao"/> <!-- 对于sqlSessionFactory来说,它只要求一个名字,而不是一个引用,所以不要使用ref的方式 --> <!-- 而且这个还会导致一个问题,配置文件加载失败 --> <!-- <property name="sqlSessionFactory" ref="sqlSessionFactory" />--> <!-- 官方推荐使用这个来配置 --> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/> </bean> <!-- 配置事务管理 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!-- 支持@Transactional注解(声明式注解) --> <tx:annotation-driven transaction-manager="transactionManager"/> </beans>
这里同样需要配置一个类似于ibatis的sqlMapClient,利用MapperScannerConfigurer进行扫描dao接口,以便于对接口进行动态代理,这块儿真的是非常人性化,爽到飞起。
mybatis-config.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <!-- 全局参数 <settings> 使全局的映射器启用或禁用缓存。 <setting name="cacheEnabled" value="true" /> 全局启用或禁用延迟加载。当禁用时,所有关联对象都会即时加载。 <setting name="lazyLoadingEnabled" value="true" /> 当启用时,有延迟加载属性的对象在被调用时将会完全加载任意属性。否则,每种属性将会按需要加载。 <setting name="aggressiveLazyLoading" value="true" /> 是否允许单条sql 返回多个数据集 (取决于驱动的兼容性) default:true <setting name="multipleResultSetsEnabled" value="true" /> 是否可以使用列的别名 (取决于驱动的兼容性) default:true <setting name="useColumnLabel" value="true" /> 允许JDBC 生成主键。需要驱动器支持。如果设为了true,这个设置将强制使用被生成的主键,有一些驱动器不兼容不过仍然可以执行。 default:false <setting name="useGeneratedKeys" value="false" /> 指定 MyBatis 如何自动映射 数据基表的列 NONE:不隐射 PARTIAL:部分 FULL:全部 <setting name="autoMappingBehavior" value="PARTIAL" /> 这是默认的执行类型 (SIMPLE: 简单; REUSE: 执行器可能重复使用prepared statements语句;BATCH: 执行器可以重复执行语句和批量更新) <setting name="defaultExecutorType" value="SIMPLE" /> 使用驼峰命名法转换字段。 <setting name="mapUnderscoreToCamelCase" value="true" /> 设置本地缓存范围 session:就会有数据的共享 statement:语句范围 (这样就不会有数据的共享 ) defalut:session <setting name="localCacheScope" value="SESSION" /> 设置但JDBC类型为空时,某些驱动程序 要指定值,default:OTHER,插入空值时不需要指定类型 <setting name="jdbcTypeForNull" value="NULL" /> </settings> --> <!-- alias、mapper,推荐在MapperScannerConfigurer中配置,这里手动写有点儿麻烦,每增加一个就需要手动添加 --> <!-- 对于alias,我一直觉着没什么太多作用,反而还会导致一些额外的工作,习惯性写bean的全路径 --> <typeAliases> <typeAlias alias="Book" type="com.ssm.entity.Book"/> <typeAlias alias="School" type="com.ssm.entity.School"/> <typeAlias alias="Student" type="com.ssm.entity.Student"/> </typeAliases> <!-- 若是在sqlSessionFactory中配置了mapperLocations选项,这里就可以不用配置映射文件 --> <mappers> <mapper resource="mapper/Book.xml"/> <mapper resource="mapper/School.xml"/> <mapper resource="mapper/Student.xml"/> </mappers> </configuration>
这个跟ibatis差别并不大,同样是需要配置alias和mapper,同样也都可以省略,在spring文件中配置sqlSessionFactory的时候,可以利用扫描路径来替代逐一配置。
mapper接口:
package com.ssm.dao; import java.util.List; import org.apache.ibatis.annotations.Param; import com.ssm.entity.Student; public interface StudentDao { List<Student> list(@Param("text") String text); void add(Student student); void update(Student student); void delete(@Param("id") int id); Student getById(@Param("id") int id); }
mapper映射文件:
<?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.ssm.dao.StudentDao"> <resultMap id="studentResult" type="Student"> <result property="id" column="id"/> <result property="name" column="student_name"/> <result property="sex" column="student_sex"/> <result property="age" column="student_age"/> <result property="birthday" column="student_birthday"/> <result property="hobby" column="student_hobby"/> <result property="schoolId" column="school_id"/> <result property="schoolName" column="school_name"/> </resultMap> <select id="list" resultMap="studentResult"> select st.*, sc.school_name from students st, schools sc where st.school_id = sc.id <if test="text != null and text != ''"> and st.student_name like '%' || #{text} || '%' </if> </select> <insert id="add" useGeneratedKeys="true" keyProperty="id" parameterType="Student"> insert into students (student_name, student_sex, student_age, student_birthday, student_hobby, school_id) values (#{name}, #{sex}, #{age}, #{birth}, #{hobby}, #{schoolId}) </insert> <update id="update" parameterType="Student"> update students <set> <if test="name != null and name != ''"> student_name = #{name}, </if> <if test="sex != null"> student_sex = #{sex}, </if> <if test="age != null"> student_age = #{age}, </if> <if test="birthday != null"> student_birthday = #{birthday}, </if> <if test="hobby != null and hobby != ''"> student_hobby = #{hobby}, </if> <if test="schoolId != null"> school_id = #{schoolId}, </if> </set> where id = #{id} </update> <delete id="delete" parameterType="int"> delete from students where id = #{id} </delete> <!-- parameterType中的 int = java.lang.Integer,如果大写就要写全包名,如果小写就不用写那么多 --> <select id="getById" parameterType="java.lang.Integer" resultMap="studentResult"> select st.*, sc.school_name from students st, schools sc where st.school_id = sc.id and st.id = #{id} </select> </mapper>区别也不是很大,不过传参的标签出现了变化,在ibatis中是##的方式,而在mybatis中是#{}的方式,这个没什么多说的,写的时候注意一下就行了。
目录结构跟ssi相比,没有太多的变化: