本文主要介绍 Mybatis(一)之后剩下的内容:
1 mybatis 中 log4j的配置
2 dao层的开发(使用mapper代理的方式)
3 mybatis的配置详解
4 输入输出映射对应的类型 ( parameterType 和 resultType )
5 mybatis 动态 sql
6 mybatis 中的一级缓存
7 mybatis 中的二级缓存
8 mybatis 和 缓存框架的整合
9 mybatis 中二级缓存使用时注意的问题
10 mybatis 和 spring 整合
11 mybatis + spring mvc
一、mybatis 中 log4j 的配置
在 config 文件夹下,新建 log4j.properties ,其内容如下: 即可
log4j.rootLogger=DEBUG, Console
#Console
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n
log4j.logger.java.sql.ResultSet=INFO
log4j.logger.org.apache=INFO
log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
二、dao层的开发(使用mapper代理的方式)
使用mapper代理的方式 ,只需要mapper接口(相当于dao接口)即可,不用完实现类了。
程序员只需要写 mapper接口 ,必须遵守一定的规范
-- UserMapper.xml , namepsace 属性 等于接口的全路径名 <mapper namespace="cat.mapper.UserMapper">
-- mapper接口中的方法名,要和映射文件中的sql的id相同 (statement 的 id)
-- mapper接口中方法的参数类型和返回值类型也要和映射文件中的 parameterType, resultType 一致
mybatis 就可以自动生成mapper接口实现类的代理对象
-
创建mapper接口
//相当于IUserDao public interface UserMapper { UserInfo getuser_byid(int id); int add_user(UserInfo user); //其实这里用int 型的返回值也行,能返回来 }
2)创建配置文件 UserMapper.xml
和原来的UserInfo.xml配置基本一样,只要改动下面的这句即可
<mapper namespace="cat.mapper.UserMapper">
不要忘了在主配置文件中引入
1<mappers> 2 <mapper resource="mapper/UserMapper.xml" /> 3</mappers>
3)使用
1static void test() throws IOException{ 2 InputStream in= Resources.getResourceAsStream("SqlMapConfig.xml"); 3 SqlSessionFactory factor=new SqlSessionFactoryBuilder().build(in); 4 SqlSession session =factor.openSession(); 5 6 //由mybatsi生成一个UserMapper的实现类的一个对象 7 UserMapper userMapper=session.getMapper(UserMapper.class); 8 UserInfo user=userMapper.getuser_byid(2); 9 System.out.println(user); 10 11 session.close(); 12 } 13 14 15 //附注: 如果方法的参数,有多个, parameterType 要怎么写 ?可以使用pojo类型,或 使用 map
三、mybatis的配置详解
properties : 用于配置属性信息
settings : 用于配置mybatis的运行方式
typeAliases : 用于配置类型别名
typeHandlers:用于配置类型处理器
plugins :配置拦截器
environments :用于配置数据源,连接池,事务属性等
mappers : 配置sql映射文件
- properties
这些是外部化的, 可替代的属性, 这些属性也可以配置在典型的 Java 属性配置文件中, 或者通过 properties 元素的子元素来传递。例如:
1<properties resource="org/mybatis/example/config.properties"> 2 <property name="username" value="dev_user"/> 3 <property name="password" value="F2Fa3!33TYyg"/> 4</properties>
其中的属性就可以在整个配置文件中使用,使用可替换的属性来实现动态配置。比如:
1<dataSource type="POOLED"> 2 <property name="driver" value="${driver}"/> 3 <property name="url" value="${url}"/> 4 <property name="username" value="${username}"/> 5 <property name="password" value="${password}"/> 6</dataSource>
这个例子中的 username 和 password 将会由 properties 元素中设置的值来替换。 driver 和 url 属性将会从包含进来的 config.properties 文件中的值来替换。这里提供很多配置的选项。
如果在这些地方,属性多于一个的话,MyBatis 按照如下的顺序加载它们:
在 properties 元素体内指定的属性首先被读取。从类路径下资源或 properties 元素的 url 属性中加载的属性第二被读取,它会 覆盖已经存在的完全一样的属性。作为方法参数传递的属性最后被读取, 它也会覆盖任一已经存在的完全一样的 属性,这些属性可能是从 properties 元素体内和资源/url 属性中加载的。因此, 最高优先级的属性是那些作为方法参数的, 然后是资源/url 属性, 最后是 properties 元素中指定的属性。
-
settings 用于配置mybatis的运行方式
<settings> <setting name="cacheEnabled" value="true" /> <setting name="lazyLoadingEnabled" value="true" /> <setting name="multipleResultSetsEnabled" value="true" /> <setting name="useColumnLabel" value="true" /> <setting name="useGeneratedKeys" value="false" /> <setting name="autoMappingBehavior" value="PARTIAL" /> <setting name="defaultExecutorType" value="SIMPLE" /> <setting name="defaultStatementTimeout" value="25" /> <setting name="safeRowBoundsEnabled" value="false" /> <setting name="mapUnderscoreToCamelCase" value="false" /> <setting name="localCacheScope" value="SESSION" /> <setting name="jdbcTypeForNull" value="OTHER" /> <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString" /> </settings> -
typeAliases 配置类型别名
<typeAliases> //单个别名的定义 <typeAlias type="cat.beans.UserInfo" alias="userInfo" />//批量别名的定义,会把beans包下的所有的类名定义成别名,首字母大小写均可 --> <package name="cat.beans" /> </typeAliases>
-
typeHandlers:用于配置类型处理器
mybatis 中通过它完成java类型和jdbc类型的转换,通常mybatis提供的都够用,不用自定义。
-
plugins 略
-
environments
//例 <environments default="development"> <environment id="development"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="${db.driver}" /> <property name="url" value="${db.url}" /> <property name="username" value="${db.username}" /> <property name="password" value="${db.password}" /> </dataSource> </environment> </environments>
-
mappers 用于引入sql配置文件的
//例如 <mapper resource="mapper/UserMapper.xml" /> // 有几下几种方式
// 1.相对于类路径的引入方式 <mappers> <mapper resource="org/mybatis/builder/AuthorMapper.xml"/> <mapper resource="org/mybatis/builder/BlogMapper.xml"/> </mappers>
//2.使用全路径引入 <mappers> <mapper url="file:///var/mappers/AuthorMapper.xml"/> <mapper url="file:///var/mappers/BlogMapper.xml"/> </mappers>
//3.使用类名包等 <mappers> <mapper class="org.mybatis.builder.AuthorMapper"/> <mapper class="cat.mapper.UserMapper"/> </mappers> //命名规范 类名必须是 UserMapper 这样的,而且映射文件要和接口文件放在同一个文件夹下
//3.使用mapper方式批量加载 <mappers> <package name="cat.mapper" /> 批量加载 cat.mapper包下的所有mapper </mappers>
四、输入输出映射对应的类型 ( parameterType 和 resultType )
-
输入参数的类型 parameterType
<insert id="add_user" parameterType="userInfo" > insert into userInfo (userName,password,note) values (#{userName},#{password}, #{note} ) </insert>
这里的 parameterType 可以传的类型有几以下几种
1.简单类型
2.pojo
3.hashmap
4.包装过的pojo
1//例子 使用 hashmap 做为 parameterType 2<select id="get_login_user" parameterType="java.util.HashMap" resultType="userInfo" > 3 select * from userInfo where userName=#{userName} and password= #{password} 4</select> 5 6 static void test2() throws IOException{ 7 InputStream in= Resources.getResourceAsStream("SqlMapConfig.xml"); 8 SqlSessionFactory factor=new SqlSessionFactoryBuilder().build(in); 9 SqlSession session =factor.openSession(); 10 UserMapper userMapper=session.getMapper(UserMapper.class); 11 HashMap map=new HashMap(); 12 map.put("userName", "高洪喜"); 13 map.put("password", "admin"); 14 UserInfo user=userMapper.get_login_user(map); 15 System.out.println(user); 16 session.close(); 17 }
附:
1<select id="get_login_user" parameterType="java.util.HashMap" resultType="userInfo" > 2 select userName,password as pwd,note from userInfo where userName=#{userName} and password= #{password} 3</select> 4 5//上面的查询,对于 password 多了一个as pwd,结果发现查询出来的目标对象的password是null 6//只要有一个属性和类中的属性对上了,它就创建类对象
2)输出参数的类型 resultType
输出参数的类型有两种 一仩是 resultType 一个是 resultMap
1//resultMap的使用 2<select id="get_login_user" parameterType="java.util.HashMap" resultMap="userInfoResultMap" > //这里的返回类型 resultMap 3 select userName as uname,password as pwd,note from userInfo where userName=#{userName} and password= #{password} 4</select> 5 6<resultMap id="userInfoResultMap" type="userInfo"> 7 <id property ="id" column="id" /> //这列特殊,用来指定id 8 <result property="userName" column="uname" /> 9 <result property="password" column="pwd" /> 10</resultMap> 11 12//说明: 如果 userInfoResultMap 是配置在别的配置文件中的,在使用的时候要加上它的namespace
五、mybatis 动态 sql
MyBatis的动态SQL是基于OGNL表达式的,它可以帮助我们方便的在SQL语句中实现某些逻辑。
MyBatis中用于实现动态SQL的元素主要有:
if
choose(when,otherwise)
trim
where
set
foreach
1)if
1<select id="get_userList" parameterType="userInfo" resultType="userInfo" > 2 select * from userInfo where 1 = 1 3 <if test="id != 0"> 4 and id = #{id} 5 </if> 6 <if test="userName != null and userName !='' " > 7 and userName = #{userName} 8 </if> 9 <if test="password != null and password!=''"> 10 and password = #{password} 11 </if> 12</select>
2)foreach
主要用在构建in条件中,它可以在SQL语句中进行迭代一个集合。foreach元素的属性主要有item,index,collection,open,separator,close。
item 集合中每一个元素进行迭代时的别名,
index 指定一个名字,用于表示在迭代过程中,每次迭代到的位置,
open 该语句以什么开始,
separator 每次进行迭代之间以什么符号作为分隔符,
注意:close 在什么结束?
在使用foreach的时候最关键的也是最容易出错的就是collection属性,该属性是必须的,不同情况下,值是不同的,主要有 3 种情况:
如果传入的是单参数且参数类型是一个List的时候,collection属性值为list
如果传入的是单参数且参数类型是一个array 数组的时候,collection的属性值为array
如果传入的参数是多个的时候,我们就需要把它们封装成一个Map了,当然单参数也可以封装成map,实际上如果你在传入参数的时候,在MyBatis里面也是会把它封装成一个Map的,map的key就是参数名,所以这个时候collection属性值就是传入的List或array对象在自己封装的map里面的key。
1/* 以下面个写法来自网上,没有测试 2<select id="dynamicForeachTest" resultType="Blog"> 3 select * from t_blog where id in 4<foreach collection="list" index="index" item="item" open="(" separator="," close=")"> 5 #{item} 6</foreach> 7</select> 8 9 <if test="ids!=null"> 10<foreach collection="ids" item="userid" open=" and (" close=")" separator="or"> 11 <!-- 遍历拼接的串 --> 12 id=#{id} 13</foreach> 14 </if> 15 16 比如 where id in(1,3,6) 17 18 <if test="ids!=null"> 19 <foreach collection="ids" item="userid" open=" and id in (" close=")" separator=","> 20 <!-- 遍历拼接的串 --> 21 #{id} 22 </foreach> 23 </if> 24*/ 25 26//例子 27<select id="getuser_by_ids" resultType="cat.beans.UserInfo" parameterType="list"> //注意,这里的 parameterType 给的是list 28 select * from UserInfo where id in 29 <foreach collection="list" item="userid" open=" (" close=")" separator=","> 30 #{userid} 31 </foreach> 32</select> 33 34//上面的写法 collection = ids 这样写可能是因为 它的paramenter type指定成 dto 中的 ids了
3) where 主要用来简化where语句中的条件判断
就是把if 那个例子中的 where 1=1 换成了 <where>
1<where> 2 <if test="id != 0"> 3 and id = #{id} 4 </if> 5 <if test="userName != null and userName !='' " > 6 and userName = #{userName} 7 </if> 8 <if test="password != null and password!=''"> 9 and password = #{password} 10 </if> 11< /where>
sql片段:
1// 声明一个sql片段 在这个片断中尽量不要写where 2<sql id="query_user_condation"> 3 <if test="id != 0"> 4 and id = #{id} 5 </if> 6 <if test="userName != null and userName !='' " > 7 and userName = #{userName} 8 </if> 9 <if test="password != null and password!=''"> 10 and password = #{password} 11 </if> 12</sql> 13 14//引用sql片段 15<select id="get_userlist" parameterType="userInfo" resultType="userInfo" > 16 select * from userInfo 17 <where> 18 <include refid="query_user_condation" /> 19 and note ='这是note' 20 </where> 21</select>
六、mybatis 中的一级缓存
mybatis 中的一级缓存是在一个Session域内, session未关闭的时候执行查询会根据sql的key进行缓存,如果对缓存的数据进行了增删改等操作,会清除缓存
mybatis 默认支持一级缓存。
1static void test4() throws IOException{ 2 InputStream in= Resources.getResourceAsStream("SqlMapConfig.xml"); 3 SqlSessionFactory factor=new SqlSessionFactoryBuilder().build(in); 4 SqlSession session =factor.openSession(); 5 6 UserMapper userMapper=session.getMapper(UserMapper.class); 7 8 UserInfo user=userMapper.getuser_byid(2); 9 UserInfo user2=userMapper.getuser_byid(2); //输出一条查询语句,证明用了一级缓存 10 11 session.close(); 12 }
七、mybatis 中的二级缓存
二级缓存和一级缓存的机制相同,默认也是采用 PerpetualCache (其实就是mybatis 中Cache 这个的接口的实现类)它也是用hashmap进行存储,它和一级缓存的不同 是它的作用域 Mapper ( namespace ) 就是同一个 namespace 共享一份缓存,可以自定义存储源 比如Ehcache 等。
对于缓存数据更新机制,当某一个作用域(一级缓存Session/二级缓存Namespaces)的进行了 C/U/D 操作后,默认该作用域下所有 select 中的缓存将被clear。
代码实例:二级缓存测试
-
开启二级缓存
<mapper namespace="cat.mapper.UserMapper" > <cache /> //这样就可以开启 .... </mapper>
2)代码
1static void test5() throws IOException{ 2 InputStream in = Test.class.getClassLoader().getResourceAsStream("SqlMapConfig.xml"); 3 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in); 4 5 SqlSession session1=factory.openSession(); 6 SqlSession session2=factory.openSession(); //用的是两个不同的session 7 8 9 UserMapper userMapper1=session1.getMapper(UserMapper.class); 10 UserMapper userMapper2=session2.getMapper(UserMapper.class); 11 12 UserInfo user=userMapper1.getuser_byid(2); 13 14 session1.close(); 15 UserInfo user2=userMapper2.getuser_byid(2); //结果就输出一条查询语句,可以证明使用的是二级缓存 16 17 session2.close(); 18 19 System.out.println(user); 20 }
3) 关于二级缓存的说明
== 要进行缓存的实体类要实现 Serializable 接口
== 映射文件中的所有的select 语句都会被缓存
== 映射文件中的所有的inser,updage,delete 相关的语句都会清除缓存
== 缓存会使用Last Recently Used(LRU,最近最少使用的)算法来收回
== 缓存会根据指定的时间间隔来刷新
== 缓存默认会存储1024个对象
-
catch 标签的常用属性
<cache eviction="FIFO" //回收策略为先进先出 flushInterval="60000" //自动刷新时间60s size="512" //最多缓存512个引用对象 readOnly="true" //只读 // type="org.mybatis.caches.ehcache.LoggingEhcache" 可以用type属性指定缓存提供者 />
5) MyBatis中有flushCache、useCache这两个配置属性,分为下面几种情况
(1)当为select语句时:
flushCache默认为false,表示任何时候语句被调用,都不会去清空本地缓存和二级缓存。
useCache默认为true,表示会将本条语句的结果进行二级缓存。
(2)当为insert、update、delete语句时:
flushCache默认为true,表示任何时候语句被调用,都会导致本地缓存和二级缓存被清空。
useCache属性在该情况下没有。
上面的信息来自 MyBatis官方文档。如果有必要,那么就需要人工修改配置,修改结果类似下面:
1<select id="save" parameterType="XXXXXEO" statementType="CALLABLE" flushCache="true" useCache="false"> 2 …… 3</select>
八、mybatis 和 缓存框架的整合
EhCache 是一个纯Java的进程内缓存框架,具有快速、精干等特点,是Hibernate中默认的CacheProvider。
Ehcache是一种广泛使用的开源Java分布式缓存。主要面向通用缓存,Java EE和轻量级容器。它具有内存和磁盘存储,缓存加载器,缓存扩展,缓存异常处理程序,一个gzip缓存servlet过滤器,支持REST和SOAP api等特点。
Ehcache最初是由Greg Luck于2003年开始开发。2009年,该项目被Terracotta购买。软件仍然是开源,但一些新的主要功能。(例如,快速可重启性之间的一致性的)只能在商业产品中使用,例如Enterprise EHCache and BigMemory。, 维基媒体Foundationannounced目前使用的就是Ehcache技术。
mybatis 和 eache 的整合
- 导包
mybatis-ehcache-1.0.3.jar
ehcache-core-2.6.8.jar
slf4j-api-1.6.1.jar
<mapper namespace="cat.mapper.UserMapper" >
1//mybatis ehcache缓存配置 --> 2//以下两个<cache>标签二选一,第一个可以输出日志,第二个不输出日志 3 <cache type="org.mybatis.caches.ehcache.LoggingEhcache" /> 4 <cache type="org.mybatis.caches.ehcache.EhcacheCache" /> 5 6 .... 7</mapper>
附加说明 : mybatis 提供了Cache 这样一个接口,它自己的默认实现类是 PerpetualCache
1public abstract interface org.apache.ibatis.cache.Cache { 2 public abstract java.lang.String getId(); 3 public abstract void putObject(java.lang.Object arg0, java.lang.Object arg1); 4 public abstract java.lang.Object getObject(java.lang.Object arg0); 5 public abstract java.lang.Object removeObject(java.lang.Object arg0); 6 public abstract void clear(); 7 public abstract int getSize(); 8 public abstract java.util.concurrent.locks.ReadWriteLock getReadWriteLock(); 9 }
3) ehcache 的配置文件 ehcache.xml (这是全部内容) // 放在config目录下(类路径下)即可
1<?xml version="1.0" encoding="UTF-8"?> 2<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 3xsi:noNamespaceSchemaLocation="ehcache.xsd" updateCheck="false"> 4 <diskStore path="java.io.tmpdir/mybatis/g" /> //如果往磁盘上放,默认放在哪个目录 5 6 <!-- DefaultCache setting. --> 7 <defaultCache 8 maxEntriesLocalHeap="10000" 9 eternal="false" 10 timeToIdleSeconds="300" 11 timeToLiveSeconds="600" 12 overflowToDisk="true" 13 maxEntriesLocalDisk="100000" 14 memoryStoreEvictionPolicy="LFU"/> 15 16 <!-- security entity--> 17 <cache 18 name="entityCache" 19 maxEntriesLocalHeap="10000" 20 eternal="true" 21 overflowToDisk="true" 22 maxEntriesLocalDisk="1000000" /> 23 </ehcache>
九、mybatis 中二级缓存使用时注意的问题
- 只能在【只有单表操作】的表上使用缓存
不只是要保证这个表在整个系统中只有单表操作,而且和该表有关的全部操作必须全部在一个namespace下。
- 在可以保证查询远远大于insert,update,delete操作的情况下使用缓存。这一点不需要多说,所有人都应该清楚。记住,这一点需要保证在1的前提下才可以!
可能会有很多人不理解这里,二级缓存带来的好处远远比不上他所隐藏的危害。
缓存是以namespace为单位的,不同namespace下的操作互不影响。
insert,update,delete操作会清空所在namespace下的全部缓存。通常使用MyBatis Generator生成的代码中,都是各个表独立的,每个表都有自己的namespace。
为什么避免使用二级缓存 ?
在符合【Cache使用时的注意事项】的要求时,并没有什么危害。
其他情况就会有很多危害了。
1)针对一个表的某些操作不在他独立的namespace下进行。
例如在UserMapper.xml中有大多数针对user表的操作。但是在一个XXXMapper.xml中,还有针对user单表的操作。这会导致user在两个命名空间下的数据不一致。如果在UserMapper.xml中做了刷新缓存的操作,在XXXMapper.xml中缓存仍然有效,如果有针对user的单表查询,使用缓存的结果可能会不正确。
更危险的情况是在XXXMapper.xml做了insert,update,delete操作时,会导致UserMapper.xml中的各种操作充满未知和风险。有关这样单表的操作可能不常见。但是你也许想到了一种常见的情况。
多表操作一定不能使用缓存 为什么不能?
首先不管多表操作写到那个namespace下,都会存在某个表不在这个namespace下的情况。
例如两个表:role和user_role,如果我想查询出某个用户的全部角色role,就一定会涉及到多表的操作。
1<select id="selectUserRoles" resultType="UserRoleVO"> 2 select * from user_role a,role b where a.roleid = b.roleid and a.userid = #{userid} 3</select>
像上面这个查询,你会写到那个xml中呢??
不管是写到RoleMapper.xml还是UserRoleMapper.xml,或者是一个独立的XxxMapper.xml中。如果使用了二级缓存,都会导致上面这个查询结果可能不正确。
如果你正好修改了这个用户的角色,上面这个查询使用缓存的时候结果就是错的。这点应该很容易理解。在我看来,就以MyBatis目前的缓存方式来看是无解的。多表操作根本不能缓存。如果你让他们都使用同一个namespace(通过<cache-ref>)来避免脏数据,那就失去了缓存的意义。看到这里,实际上就是说,二级缓存不能用。整篇文章介绍这么多也没什么用了。
十、mybatis 和 spring 整合
最主要的,就是把 SessionFactory 的创建交给Spring
-
导jar包
-
工程结构
-
配置spring的主配置文件 applicationContext.xml
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
<context:property-placeholder location="classpath:mydbconfig.properties" />
//数据源 <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="${db.driver}" /> <property name="url" value="${db.url}" /> <property name="username" value="${db.username}" /> <property name="password" value="${db.password}" /> <property name="initialSize" value="10" /> <property name="maxActive" value="500" /> <property name="maxIdle" value="2" /> <property name="minIdle" value="3" /> </bean>
//配置sqlSessionFacory <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="configLocation" value="classpath:mybatis/SqlMapConfig.xml" /><!-- 这里要指定mybatis合局配置文件 --> </bean>
</beans>1 <bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean"> 2 <property name="mapperInterface" value="cat.mapper.UserMapper" /> 3 <property name="sqlSessionFactory" ref="sqlSessionFactory" /> 4 </bean> 5 6 -
配置 mybatis 的主配置文件 SqlMapConfig.xml
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <typeAliases> <package name="cat.beans" /> </typeAliases>
</configuration>1 <mappers> 2 <package name="cat.mapper" /> 3 </mappers> -
配置映射文件 UserMapper.xml //和过去一样,没有任何区别
<?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">
<!-- 声明一个sql片段 在这个片断中尽量不要写where -->1 <mapper namespace="cat.mapper.UserMapper" > 2 <cache/> 3
</mapper>1 <sql id="query_user_condation"> 2 <if test="id != 0"> 3 and id = #{id} 4 </if> 5 <if test="userName != null and userName !='' " > 6 and userName = #{userName} 7 </if> 8 <if test="password != null and password!=''"> 9 and password = #{password} 10 </if> 11 </sql> 12 13 <!-- 引用sql片断 --> 14 <select id="get_userlist" parameterType="userInfo" resultType="userInfo" > 15 select * from userInfo 16 <where> 17 <include refid="query_user_condation" /> 18 and note ='这是note' 19 </where> 20 21 </select> 22 23 <resultMap id="userInfoResultMap" type="userInfo"> 24 <id property ="id" column="id" /> 25 <result property="userName" column="uname" /> 26 <result property="password" column="pwd" /> 27 </resultMap> 28 29 <select id="getuser_byid" parameterType="int" resultType="userInfo" > 30 select * from userInfo where id=#{id} 31 </select> 32 <select id="getuser_biname" parameterType="string" resultType="userInfo"> 33 select * from userInfo where userName like '%${value}%' 34 </select> 35 36 <!-- 对于添加这类方法,是没有resultType的 --> 37 <insert id="add_user" parameterType="userInfo" > 38 <selectKey order="AFTER" keyProperty="id" resultType="int"> 39 select last_insert_id() 40 </selectKey> 41 insert into userInfo (userName,password,note) values (#{userName},#{password}, #{note} ) 42 </insert> 43 44 <select id="get_login_user" parameterType="java.util.HashMap" resultMap="userInfoResultMap" > 45 select userName as uname,password as pwd,note from userInfo where userName=#{userName} and password= #{password} 46 </select> 47 48 <insert id="add_user_new" parameterType="userInfo" > 49 <selectKey order="BEFORE" keyProperty="id" resultType="string"> 50 select uuid() 51 </selectKey> 52 insert into userInfo (id,userName,password,note) values (#{id},#{userName},#{password}, #{note} ) 53 </insert> 54 55 <delete id="deluser_byid" parameterType="int" > 56 delete from userInfo where id=#{id} 57 </delete> 58 59 <update id="update_user" parameterType="cat.beans.UserInfo" > <!-- 传过来的userInfo对象中要有id --> 60 update userInfo set userName= #{userName},password= #{password}, note =#{note} where id= #{id} 61 </update> 62 -
接口 UserMapper.java //和过去一样
public interface UserMapper { UserInfo getuser_byid(int id); int add_user(UserInfo user); //其实这里用int 型的返回值也行,能返回来 UserInfo get_login_user(HashMap map); List<UserInfo>get_userlist(UserInfo user); }
7)测试
1ClassPathXmlApplicationContext context =new ClassPathXmlApplicationContext("classpath:spring/applicationContext.xml"); 2 UserMapper userMapper=(UserMapper)context.getBean("userMapper"); 3 4 UserInfo user=userMapper.getuser_byid(2); 5 System.out.println(user);
说明,关于spring中加载mapper
上面的例子中,如果有多个mapper ,则在spring 中要配置多次,很不方便。可以使用扫描的方式加载:
1// 它来自mybatis-spring-1.2.2.jar --> 2<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> //由于是批量,就不用加id属性了 3 <property name="basePackage" value="cat.dao" /> 4 <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" /> 5</bean> 6 7//使用了这种方式以后,mybatis 主配置文件 SqlMapConfig 中的下面就可以不要了 8<mappers> 9 <package name="cat.mapper" /> 10</mappers>
十一、mybatis + spring mvc
-
加入springmvc的配置文件
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop"
1 xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd 2 http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd 3 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd 4 http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd"> 5 6<context:component-scan base-package="cat.controller" /> <mvc:annotation-driven /> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" > <property name="prefix" value="/" /> <property name="suffix" value=".jsp" /> </bean>
</beans><mvc:resources location="/resource/" mapping="resources/**"></mvc:resources>
配置事物管理器
1<aop:config> 2 <aop:pointcut id="myTxPointCut" expression="execution(* cat.service.impl.*.*(..))" /> 3 <aop:advisor advice-ref="txActive" pointcut-ref="myTxPointCut"/> 4</aop:config> 5 6<tx:advice id="txActive" transaction-manager="txManager"> 7 <tx:attributes> 8 <tx:method name="get*" read-only="true" propagation="NOT_SUPPORTED"/> 9 <tx:method name="update*" propagation="REQUIRED" /> 10 <tx:method name="insert*" propagation="REQUIRED" /> 11 <tx:method name="del*" propagation="REQUIRED" /> 12 <tx:method name="add*" propagation="REQUIRED" /> 13 </tx:attributes> 14</tx:advice>
2) 在web.xml中配置 (一是配置spring, 是配置核心控制器)
1//加载spring主配置文件 2<context-param> 3 <param-name>contextConfigLocation</param-name> 4 <param-value>classpath:spring/applicationContext.xml</param-value> 5</context-param> 6 <listener> 7 <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 8 </listener> 9 10//配置springmvc的核心控制器 11<servlet> 12 <servlet-name>springmvc</servlet-name> 13 <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 14 <init-param> 15 <param-name>contextConfigLocation</param-name> 16 <param-value>classpath:spring/springmvc.xml</param-value> 17 </init-param> 18 <load-on-startup>1</load-on-startup> 19</servlet> 20 21<servlet-mapping> 22 <servlet-name>springmvc</servlet-name> 23 <url-pattern>/</url-pattern> 24</servlet-mapping>
3) Action的配置
1@Controller 2public class UserAction { 3 4 @Resource 5 private UserMapper mapper; 6 7 @RequestMapping("/get_user") 8 public ModelAndView getUser(){ 9 ModelAndView mv=new ModelAndView(); 10 UserInfo user=mapper.getuser_byid(2); 11 System.out.println(user); 12 mv.addObject("user", user); 13 mv.setViewName("show_user"); 14 return mv; 15 } 16 }