1、JavaEE 课程 传智播客 java 学院 传智.燕青mybatis 第二天 高级映射 查询缓存 和 spring 整合课程复习:mybatis 是什么?mybatis 是一人持久层框架,mybatis 是一个不完全的 ORM 框架。sql 语句需要程序员自己去编写,但是 mybatis也有映射(输入参数映射、输出结果映射) 。mybatis 入门门槛不高,学习成本低,让程序员把精力放在 sql 语句上,对 sql 语句优化非常方便,适用与需求变化较多项目,比如互联网项目。mybatis 框架执行过程:1、配置 mybatis 的配置文件, SqlMapConfig.xml(名称不固定)2、
2、通过配置文件,加载 mybatis 运行环境,创建 SqlSessionFactory 会话工厂SqlSessionFactory 在实际使用时按单例方式。3、通过 SqlSessionFactory 创建 SqlSessionSqlSession 是一个面向用户接口(提供操作数据库方法) ,实现对象是线程不安全的,建议 sqlSession 应用场合在方法体内。4、调用 sqlSession 的方法去操作数据。如果需要提交事务,需要执行 SqlSession 的 commit()方法。5、释放资源,关闭 SqlSessionmybatis 开发 dao 的方法:1、原始 dao 的方法需要程
3、序员编写 dao 接口和实现类需要在 dao 实现类中注入一个 SqlSessionFactory 工厂。2、 mapper 代理开发方法(建议使用)只需要程序员编写 mapper 接口(就是 dao 接口)程序员在编写 mapper.xml(映射文件)和 mapper.java 需要遵循一个开发规范:1、mapper.xml 中 namespace 就是 mapper.java 的类全路径。2、mapper.xml 中 statement 的 id 和 mapper.java 中方法名一致。3、mapper.xml 中 statement 的 parameterType 指定输入参数的类型和
4、 mapper.java 的方法输入 参数类型一致。4、mapper.xml 中 statement 的 resultType 指定输出结果的类型和 mapper.java 的方法返回值类型一致。SqlMapConfig.xml 配置文件:可以配置 properties 属性、别名、mapper 加载。 。 。输入映射:parameterType:指定输入参数类型可以简单类型、pojo、hashmap。 。对于综合查询,建议 parameterType 使用包装的 pojo,有利于系统 扩展。输出映射:resultType:查询到的列名和 resultType 指定的 pojo 的属性名一致,
5、才能映射成功。reusltMap:JavaEE 课程 传智播客 java 学院 传智.燕青可以通过 resultMap 完成一些高级映射。如果查询到的列名和映射的 pojo 的属性名不一致时,通过 resultMap 设置列名和属性名之间的对应关系(映射关系) 。可以完成映射。高级映射:将关联查询的列映射到一个 pojo 属性中。 (一对一)将关联查询的列映射到一个 List中。 (一对多)动态 sql:(重点)if 判断(掌握)whereforeachsql 片段(掌握)课程安排:对订单商品数据模型进行分析。高级映射:(了解)实现一对一查询、一对多、多对多查询。延迟加载查询缓存一级缓存二级缓
6、存(了解 mybatis 二级缓存使用场景)mybatis 和 spirng 整合(掌握)逆向工程(会用)1 订单商品数据模型1.1 数据模型分析思路1、每张表记录的数据内容分模块对每张表记录的内容进行熟悉,相当 于你学习系统 需求(功能)的过程。2、每张表重要的字段设置非空字段、外键字段3、数据库级别表与表之间的关系外键关系4、表与表之间的业务关系在分析表与表之间的业务关系时一定要建立 在某个业务意义基础上去分析。JavaEE 课程 传智播客 java 学院 传智.燕青1.2 数据模型分析用户表:userid:自增主键订单表:ordersnumber:订单号user_id(外键,用户id)订
7、单明细表:orderdetailorders_id(外键,订单id)items_id(外键,商品 id)商品表:itemsuser_id 外键orders_id外键items_id外键一对一一对多一对一一对多一对一一对多orders items一对多itemsorders:一对多总之:orders 和items 是多对多关系user 和 items是多对多关系用户表 user:记录了购买商品的用户信息订单表:orders记录了用户所创建的订单(购买商品的订单)订单明细表:orderdetail:记录了订单的详细信息即购买商品的信息商品表:itemsJavaEE 课程 传智播客 java 学院
8、传智.燕青记录了商品信息表与表之间的业务关系:在分析表与表之间的业务关系时需要建立 在某个业务意义基础上去分析。先分析数据级别之间有关系的表之间的业务关系:usre 和 orders:user-orders:一个用户可以创建多个订单,一对多orders-user:一个订单只由一个用户创建,一对一orders 和 orderdetail:orders-orderdetail:一个订单可以包括 多个订单明细,因为一个订单可以购买多个商品,每个商品的购买信息在 orderdetail 记录,一对多关系orderdetail orders:一个订单明细只能包括在一个订单中,一对一orderdetail
9、 和 itesm:orderdetail-itesms:一个订单明细只对应一个商品信息,一对一items orderdetail:一个商品可以包括在多个订单明细 ,一对多再分析数据库级别没有关系的表之间是否有业务关系:orders 和 items:orders 和 items 之间可以通过 orderdetail 表建立 关系。2 一对一查询2.1 需求查询订单信息,关联查询创建订单的用户信息2.2 resultTypeJavaEE 课程 传智播客 java 学院 传智.燕青2.2.1 sql 语句确定查询的主表:订单表确定查询的关联表:用户表关联查询使用内链接?还是外链接?由于 orders
10、 表中有一个外键(user_id) ,通过外键关联查询用户表只能查询出一条记录,可以使用内链接。SELECT orders.*,USER.username,USER.sex,USER.address FROMorders,USER WHERE orders.user_id = user.id2.2.2 创建 pojo将上边 sql 查询的结果映射到 pojo 中,pojo 中必须包括所有查询列名。原始的 Orders.java 不能映射全部字段,需要新创建的 pojo。创建 一个 pojo 继承包括查询字段较多的 po 类。JavaEE 课程 传智播客 java 学院 传智.燕青2.2.3 m
11、apper.xml2.2.4 mapper.java2.3 resultMap2.3.1 sql 语句同 resultType 实现的 sql2.3.2 使用 resultMap 映射的思路使用 resultMap 将查询结果中的订单信息映射到 Orders 对象中,在 orders 类中添加 User 属性,将关联查询出来的用户信息映射到 orders 对象中的 user 属性中。JavaEE 课程 传智播客 java 学院 传智.燕青2.3.3 需要 Orders 类中添加 user 属性2.3.4 mapper.xml2.3.4.1 定义 resultMapJavaEE 课程 传智播客
12、java 学院 传智.燕青2.3.4.2 statement 定义2.3.5 mapper.java2.4 resultType 和 resultMap 实现一对一查询小结实现一对一查询:JavaEE 课程 传智播客 java 学院 传智.燕青resultType:使用 resultType 实现较为简单,如果 pojo 中没有包括查询出来的列名,需要增加列名对应的属性,即可完成映射。如果没有查询结果的特殊要求建议使用 resultType。resultMap:需要单独定义 resultMap,实现有点麻烦,如果对查询结果有特殊的要求,使用 resultMap 可以完成将关联查询映射 pojo
13、 的属性中。resultMap 可以实现延迟加载, resultType 无法实现延迟加载。3 一对多查询3.1 需求查询订单及订单明细的信息。3.2 sql 语句确定主查询表:订单表确定关联查询表:订单明细表在一对一查询基础上添加订单明细表关联即可。SELECT orders.*,USER.username,USER.sex,USER.address,orderdetail.id orderdetail_id,orderdetail.items_id,orderdetail.items_num,orderdetail.orders_idFROMorders,USER,orderdetailW
14、HERE orders.user_id = user.id AND orderdetail.orders_id=orders.id3.3 分析使用 resultType 将上边的 查询结果映射到 pojo 中,订单信息的就是重复。JavaEE 课程 传智播客 java 学院 传智.燕青要求:对 orders 映射不能出现重复记录。在 orders.java 类中添加 List orderDetails 属性。最终会将订单信息映射到 orders 中,订单所对应的订单明细映射到 orders 中的 orderDetails 属性中。映射成的 orders 记录数为两条(orders 信息不重复)
15、每个 orders 中的 orderDetails 属性存储了该 订单所对应的订单明细。3.4 在 orders 中添加 list 订单明细属性3.5 mapper.xmlJavaEE 课程 传智播客 java 学院 传智.燕青3.6 resultMap 定义JavaEE 课程 传智播客 java 学院 传智.燕青3.7 mapper.java3.8 小结mybatis 使用 resultMap 的 collection 对关联查询的多条记录映射到一个 list 集合属性中。使用 resultType 实现:将订单明细映射到 orders 中的 orderdetails 中,需要自己处理,使用
16、双重循环遍历,去掉重复记录,将订单明细放在 orderdetails 中。4 多对多查询4.1 需求查询用户及用户购买商品信息。4.2 sql 语句查询主表是:用户表关联表:由于用户和商品没有直接关联,通过订单和订单明细进行关联,所以关联表:orders、orderdetail、itemsSELECT orders.*,USER.username,USER.sex,USER.address,orderdetail.id orderdetail_id,orderdetail.items_id,orderdetail.items_num,orderdetail.orders_id,JavaEE 课
17、程 传智播客 java 学院 传智.燕青items.name items_name,items.detail items_detail,items.price items_priceFROMorders,USER,orderdetail,itemsWHERE orders.user_id = user.id AND orderdetail.orders_id=orders.id AND orderdetail.items_id = items.id4.3 映射思路将用户信息映射到 user 中。在 user 类中添加订单列表属性 List orderslist,将用户创建的订单映射到 orde
18、rslist在 Orders 中添加订单明细列表属性 Listorderdetials,将订单的明细映射到 orderdetials在 OrderDetail 中添加 Items 属性,将订单明细所对应的商品映射到 Items4.4 mapper.xml4.5 resultMap 定义JavaEE 课程 传智播客 java 学院 传智.燕青JavaEE 课程 传智播客 java 学院 传智.燕青4.6 mapper.java4.7 多对多查询总结将查询用户购买的商品信息明细清单, (用户名、用户地址、购买商品名称、购买商品时间、购买商品数量)针对上边的需求就使用 resultType 将查询到
19、的记录映射到一个扩展的 pojo 中,很简单实现明细清单的功能。一对多是多对多的特例,如下需求:查询用户购买的商品信息,用户和商品的关系是多对多关系。需求 1:查询字段:用户账号、用户名称、用户性别、商品名称、商品价格(最常见)企业开发中常见明细列表,用户购买商品明细列表,使用 resultType 将上边查询列映射到 pojo 输出。需求 2:查询字段:用户账号、用户名称、购买商品数量、商品明细(鼠标移上显示明细)使用 resultMap 将用户购买的商品明细列表映射到 user 对象中。总结:使用 resultMap 是针对那些对查询结果映射有特殊要求的功能, ,比如特殊要求映射成 lis
20、t 中包括 多个 list。5 resultMap 总结resultType:作用:将查询结果按照 sql 列名 pojo 属性名一致性映射到 pojo 中。场合:常见一些明细记录的展示,比如用户购买商品明细,将关联查询信息全部展示在页面时,此时可直接使用resultType 将每一条记录映射到 pojo 中,在前端页面遍历 list(list 中是 pojo)即可。resultMap:使用 association 和 collection 完成一对一和一对多高级映射(对结果有特殊的映射要求) 。association:JavaEE 课程 传智播客 java 学院 传智.燕青作用:将关联查询信
21、息映射到一个 pojo 对象中。场合:为了方便查询关联信息可以使用 association 将关联订单信息映射为用户对象的 pojo 属性中,比如:查询订单及关联用户信息。使用 resultType 无法将查询结果映射到 pojo 对象的 pojo 属性中,根据对结果集查询遍历的需要选择使用resultType 还是 resultMap。collection:作用:将关联查询信息映射到一个 list 集合中。场合:为了方便查询遍历关联信息可以使用 collection 将关联信息映射到 list 集合中,比如:查询用户权限范围模块及模块下的菜单,可使用 collection 将模块映射到模块
22、list 中,将菜单列表映射到模块对象的菜单 list 属性中,这样的作的目的也是方便对查询结果集进行遍历查询。如果使用 resultType 无法将查询结果映射到 list 集合中。6 延迟加载6.1 什么是延迟加载resultMap 可以实现高级映射(使用 association、collection 实现一对一及一对多映射) ,association、collection 具备延迟加载功能。需求:如果查询订单并且关联查询用户信息。如果先查询订单信息即可满足要求,当我们需要查询用户信息时再查询用户信息。把对用户信息的按需去查询就是延迟加载。延迟加载:先从单表查询、需要时再从关联表去关联查询
23、,大大提高 数据库性能,因为查询单表要比关联查询多张表速度要快。6.2 使用 association 实现延迟加载6.2.1 需求查询订单并且关联查询用户信息JavaEE 课程 传智播客 java 学院 传智.燕青6.2.2 mapper.xml需要定义两个 mapper 的方法对应的 statement。1、只查询订单信息SELECT * FROM orders在查询订单的 statement 中使用 association 去延迟加载(执行)下边的 satatement(关联查询用户信息)2、关联查询用户信息通过上边查询到的订单信息中 user_id 去关联查询用户信息使用 UserMap
24、per.xml 中的 findUserById上边先去执行 findOrdersUserLazyLoading,当需要去查询用户的时候再去执行 findUserById,通过 resultMap 的定义将延迟加载执行配置起来。6.2.3 延迟加载 resultMap使用 association 中的 select 指定延迟加载去执行的 statement 的 id。6.2.4 mapper.java6.2.5 测试6.2.5.1 测试思路:1、执行上边 mapper 方法(findOrdersUserLazyLoading) ,内部去调用cn.itcast.mybatis.mapper.Ord
25、ersMapperCustom 中的 findOrdersUserLazyLoading 只查询 orders 信息(单表) 。2、在程序中去遍历上一步骤查询出的 List,当我们调用 Orders 中的 getUser 方法时,开始进行延迟加载。3、延迟加载,去调用 UserMapper.xml 中 findUserbyId 这个方法获取用户信息。6.2.5.2 延迟加载配置mybatis 默认没有开启延迟加载,需要在 SqlMapConfig.xml 中 setting 配置。在 mybatis 核心配置文件中配置:lazyLoadingEnabled、aggressiveLazyLoad
26、ing设置项 描述 允许值 默认值JavaEE 课程 传智播客 java 学院 传智.燕青lazyLoadingEnabled全局性设置懒加载。如果设为false,则所有相关联的都会被初始化加载。true | false falseaggressiveLazyLoading当设置为true的时候,懒加载的对象可能被任何懒属性全部加载。否则,每个属性都按需加载。true | false true在 SqlMapConfig.xml 中配置:6.2.5.3 测试代码6.2.6 延迟加载思考不使用 mybatis 提供的 association 及 collection 中的延迟加载功能,如何实现延
27、迟加载?实现方法如下:定义两个 mapper 方法:1、查询订单列表2、根据用户 id 查询用户信息JavaEE 课程 传智播客 java 学院 传智.燕青实现思路:先去查询第一个 mapper 方法,获取订单信息列表在程序中(service) ,按需去调用第二个 mapper 方法去查询用户信息。总之:使用延迟加载方法,先去查询简单的 sql(最好单表,也可以关联查询) ,再去按需要加载关联查询的其它信息。7 查询缓存7.1 什么是查询缓存mybatis 提供查询缓存,用于减轻数据压力,提高数据库性能。mybaits 提供一级缓存,和二级缓存。一级缓存是 SqlSession 级别的缓存。在
28、操作数据库时需要构造 sqlSession 对象,在对象中有一个数据结构(HashMap)用于存储缓存数据。不同的 sqlSession 之间的缓存数据区域(HashMap )是互相不影响的。二级缓存是 mapper 级别的缓存,多个 SqlSession 去操作同一个 Mapper 的 sql 语句,多个 SqlSession 可以共用二级缓存,二级缓存是跨 SqlSession 的。为什么要用缓存?如果缓存中有数据就不用从数据库中获取,大大提高系统性能。JavaEE 课程 传智播客 java 学院 传智.燕青7.2 一级缓存7.2.1 一级缓存工作原理第一次发起查询用户 id 为 1 的用
29、户信息,先去找缓存中是否有 id 为 1 的用户信息,如果没有,从数据库查询用户信息。得到用户信息,将用户信息存储到一级缓存中。如果 sqlSession 去执行 commit 操作(执行插入、更新、删除) ,清空 SqlSession 中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读。第二次发起查询用户 id 为 1 的用户信息,先去找缓存中是否有 id 为 1 的用户信息,缓存中有,直接从缓存中获取用户信息。7.2.2 一级缓存测试mybatis 默认支持一级缓存,不需要在配置文件去配置。按照上边一级缓存原理步骤去测试。Testpublic void testCache1
30、() throws ExceptionSqlSession sqlSession = sqlSessionFactory.openSession();/创建代理对象UserMapper userMapper = sqlSession.getMapper(UserMapper.class);JavaEE 课程 传智播客 java 学院 传智.燕青/下边查询使用一个SqlSession/第一次发起请求,查询id 为1的用户User user1 = userMapper.findUserById(1);System.out.println(user1);/ 如果sqlSession 去执行commi
31、t操作(执行插入、更新、删除),清空SqlSession 中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读。/更新user1的信息user1.setUsername(“测试用户22“);userMapper.updateUser(user1);/执行commit操作去清空缓存sqlSmit();/第二次发起请求,查询id 为1的用户User user2 = userMapper.findUserById(1);System.out.println(user2);sqlSession.close();7.2.3 一级缓存应用正式开发,是将 mybatis 和 spring 进行
32、整合开发,事务控制在 service 中。一个 service 方法中包括 很多 mapper 方法调用。service/开始执行时,开启事务,创建 SqlSession 对象/第一次调用 mapper 的方法 findUserById(1)/第二次调用 mapper 的方法 findUserById(1),从一级缓存中取数据/方法结束,sqlSession 关闭如果是执行两次 service 调用查询相同 的用户信息,不走一级缓存,因为 session 方法结束,sqlSession 就关闭,一级缓存就清空。JavaEE 课程 传智播客 java 学院 传智.燕青7.3 二级缓存7.3.1
33、原理首先开启 mybatis 的二级缓存。sqlSession1 去查询用户 id 为 1 的用户信息,查询到用户信息会将查询数据存储到二级缓存中。如果 SqlSession3 去执行相同 mapper 下 sql,执行 commit 提交,清空该 mapper 下的二级缓存区域的数据。sqlSession2 去查询用户 id 为 1 的用户信息,去缓存中找是否存在数据,如果存在直接从缓存中取出数据。二级缓存与一级缓存区别,二级缓存的范围更大,多个 sqlSession 可以共享一个 UserMapper 的二级缓存区域。UserMapper 有一个二级缓存区域(按 namespace 分)
34、,其它 mapper 也有自己的二级缓存区域(按 namespace分) 。每一个 namespace 的 mapper 都有一个二缓存区域,两个 mapper 的 namespace 如果相同,这两个 mapper 执行sql 查询到数据将存在相同 的二级缓存区域中。7.3.2 开启二级缓存mybaits 的二级缓存是 mapper 范围级别,除了在 SqlMapConfig.xml 设置二级缓存的总开关,还要在具体的mapper.xml 中开启二级缓存。JavaEE 课程 传智播客 java 学院 传智.燕青在核心配置文件 SqlMapConfig.xml 中加入描述 允许值 默认值cac
35、heEnabled 对在此配置文件下的所有 cache 进行全局性开/关设置。 true false true在 UserMapper.xml 中开启二缓存,UserMapper.xml 下的 sql 执行完成会存储到它的缓存区域(HashMap ) 。7.3.3 调用 pojo 类实现序列化接口为了将缓存数据取出执行反序列化操作,因为二级缓存数据存储介质多种多样,不一样在内存。7.3.4 测试方法/ 二级缓存测试Testpublic void testCache2() throws Exception SqlSession sqlSession1 = sqlSessionFactory.op
36、enSession();JavaEE 课程 传智播客 java 学院 传智.燕青SqlSession sqlSession2 = sqlSessionFactory.openSession();SqlSession sqlSession3 = sqlSessionFactory.openSession();/ 创建代理对象UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);/ 第一次发起请求,查询id 为1的用户User user1 = userMapper1.findUserById(1);System.out.p
37、rintln(user1);/这里执行关闭操作,将sqlsession中的数据写到二级缓存区域sqlSession1.close();/使用sqlSession3执行commit() 操作UserMapper userMapper3 = sqlSession3.getMapper(UserMapper.class);User user = userMapper3.findUserById(1);user.setUsername(“张明明“);userMapper3.updateUser(user);/执行提交,清空UserMapper下边的二级缓存sqlSmit();sqlSession3.c
38、lose();UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);/ 第二次发起请求,查询id 为1的用户User user2 = userMapper2.findUserById(1);System.out.println(user2);sqlSession2.close();7.3.5 useCache 配置在 statement 中设置 useCache=false 可以禁用当前 select 语句的二级缓存,即每次查询都会发出 sql 去查询,默认情况是 true,即该 sql 使用二级缓存。总结:针对每次查
39、询都需要最新的数据 sql,要设置成 useCache=false,禁用二级缓存。7.3.6 刷新缓存(就是清空缓存)在 mapper 的同一个 namespace 中,如果有其它 insert、update 、delete 操作数据后需要刷新缓存,如果不执行刷JavaEE 课程 传智播客 java 学院 传智.燕青新缓存会出现脏读。设置 statement 配置中的 flushCache=“true“ 属性,默认情况下为 true 即刷新缓存,如果改成 false 则不会刷新。使用缓存时如果手动修改数据库表中的查询数据会出现脏读。如下:总结:一般下执行完 commit 操作都需要刷新缓存,f
40、lushCache=true 表示刷新缓存,这样可以避免数据库脏读。7.4 mybatis 整合 ehcacheehcache 是一个分布式缓存框架。7.4.1 分布缓存我们系统为了提高系统并发,性能、一般对系统进行分布式部署(集群部署方式)系统工程springmvcmybatis服务器 1系统工程springmvcmybatis服务器 2对缓存数据进行集中管理(redis 集群)使用分布式缓存框架redis、memcached、ehcache。 。不使用分布缓存,缓存的数据在各各服务单独存储,不方便系统 开发。所以要使用分布式缓存对缓存数据进行集中管理。JavaEE 课程 传智播客 java
41、 学院 传智.燕青mybatis 无法实现分布式缓存,需要和其它分布式缓存框架进行整合。7.4.2 整合方法 (掌握)mybatis 提供了一个 cache 接口,如果要实现自己的缓存逻辑,实现 cache 接口开发即可。mybatis 和 ehcache 整合,mybatis 和 ehcache 整合包中提供了一个 cache 接口的实现类。mybatis 默认实现 cache 类是:JavaEE 课程 传智播客 java 学院 传智.燕青7.4.3 加入 ehcache 包7.4.4 整合 ehcache配置 mapper 中 cache 中的 type 为 ehcache 对 cache
42、 接口的实现类型。7.4.5 加入 ehcache 的配置文件在 classpath 下配置 ehcache.xmlJavaEE 课程 传智播客 java 学院 传智.燕青7.5 二级应用场景对于访问多的查询请求且用户对查询结果实时性要求不高,此时可采用 mybatis 二级缓存技术降低数据库访问量,提高访问速度,业务场景比如:耗时较高的统计分析 sql、电话账单查询 sql 等。实现方法如下:通过设置刷新间隔时间,由 mybatis 每隔一段时间自动清空缓存,根据数据变化频率设置缓存刷新间隔 flushInterval,比如设置为 30 分钟、60 分钟、24 小时等,根据需求而定。7.6
43、二级缓存局限性mybatis 二级缓存对细粒度的数据级别的缓存实现不好,比如如下需求:对商品信息进行缓存,由于商品信息查询访问量大,但是要求用户每次都能查询最新的商品信息,此时如果使用 mybatis 的二级缓存就无法实现当一个商品变化时只刷新该商品的缓存信息而不刷新其它商品的信息,因为 mybaits 的二级缓存区域以 mapper 为单位划分,当一个商品信息变化会将所有商品信息的缓存数据全部清空。解决此类问题需要在业务层根据需求对数据有针对性缓存。8 spring 和 mybatis 整合8.1 整合思路需要 spring 通过单例方式管理 SqlSessionFactory。spring
44、 和 mybatis 整合生成代理对象,使用 SqlSessionFactory 创建 SqlSession。 (spring 和 mybatis 整合自动完成)持久层的 mapper 都需要由 spring 进行管理。8.2 整合环境创建一个新的 java 工程(接近实际开发的工程结构)jar 包:mybatis3.2.7 的 jar 包spring3.2.0 的 jar 包JavaEE 课程 传智播客 java 学院 传智.燕青mybatis 和 spring 的整合包:早期 ibatis 和 spring 整合是由 spring 官方提供,mybatis 和 spring 整合由 mybatis 提供。全部 jar 包8.3 sqlSessionFactory在 applicationContext.xml 配置 sqlSessionFactory 和数据源sqlSessionFactory 在 mybatis 和 spring 的整合包下。