springmvc mybatismybatis课堂笔记2_第1页
springmvc mybatismybatis课堂笔记2_第2页
springmvc mybatismybatis课堂笔记2_第3页
springmvc mybatismybatis课堂笔记2_第4页
springmvc mybatismybatis课堂笔记2_第5页
已阅读5页,还剩30页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Mybatis第二天课堂笔记1 复习1.1 Mybatis是什么?Mybatis是持久层框架,是一个不安全的orm框架,是apache的开源项目,是ibatis的升级版本。Myatis是对jdbc一个封装,需要程序员自己编写sql语句,也可以采用mybatis官方提供的逆向工程由数据库表升级sql语句及po类、mapper类等。使用Mybaits3.2.3版本。Mybatis适用与需求不固定变化较大的系统。由于程序员自己写sql提高了系统的灵活性,非常方便对sql语句进行优化。由于mybatis学习入门门槛不高,企业中应用比较广泛。企业中技术选型根据企业自身的资源情况进行选型,根据原则是以低成本换取高回报。宗旨:不管使用什么技术做出的系统都要以满足用户需求为目标!1.2 sqlMapConfig.xml:Mybatis的全局配置文件,SqlMapConfig.xml(名称不固定)加载属性文件别名定义: 单个别名定义 批量别名定义 加载mapper.xml文件(mybatis的映射文件)Mapper.xml中定义了statement(主要是sql语句) 单个mapper.xml文件加载 规则:mapper.xml和mapper.java名称一致且放在一个目录中 批量mapper.xml文件加载 批量扫描包下边所有mapper接口, 规则:mapper.xml和mapper.java名称一致且放在一个目录中 1.3 Mybatsi 开发:原始方式:采用dao接口及dao接口实现开发。动态代理方式:程序员只需要写mapper接口(等于dao接口),由mybatis自动生成接口实现的代理对象。需要程序员开发的两个东西:XXXXXMapper.xml:映射文件XXXXXMapper.java:接口文件Mapper代理对象方式规则:1、 XXXXXMapper.xml中的namespace是mapper.java的全限定名2、 XXXXXMapper.java中方法名和XXXXXMapper.xml的statement的id一致.3、 XXXXXMapper.java中方法输入参数类型和XXXXXMapper.xml的statement的parameterType指定输入参数类型一致4、 XXXXXMapper.java中方法输出参数类型和XXXXXMapper.xml的statement的resultType指定输出参数类型一致生成动态代理对象步骤:1、 创建会话工厂SqlSessionFactorySqlSessionFactory当成单例对象进行使用,和spring整合后由spring管理SqlSessionFactory2、 通过SqlSessionFactory得到SqlSessionSqlSession是一个面向用户接口,是线程不安全的,使用SqlSession最佳场合在方法中。简单理解成在方法中定义一个SqlSession的局部变量进行使用。3、 调用SqlSession的getMapper方法获取动态代理对象(mapper接口实现)4、 调用动态代理对象的方法(相当于调用mapper接口的方法)1.4 动态Sql:#是一个占位符,解决Sql注入,建议使用#$表示拼接sql的一个串,使用$容易引起Sql注入If判断:使用最多的,采用OGNL表达式进行对象属性判断,If判断和sql一块儿作用将查询条件抽取出来组成一个sql让其它statement进行引用。Sql将公用的sql抽取出来!Foreach:对集合进行遍历。1.5 resultType定义sql输出映射的类型定义成简单类型(int,string),需要sql查询结果集只有一条记录且只有一列。定义成pojo类型,需要将sql查询字段名和pojo的属性保持一致才能进行映射成功。2 教学计划resultMap(会用就可以):如果sql查询字段名和pojo属性名不一致,就可以使用resultMap对pojo的属性名和sql查询的字段名作一个映射关系(对应关系)。以案例讲使用mybatis实现综合查询(重点):一对一查询、一对多查询、多对多查询一级缓存(了解)二级缓存(掌握如何使用,在作性能优化时要用)延迟加载(了解)Mybatis和spring进行整合(重点)DaoServiceAction页面逆向工程(掌握,经常使用)采购系统的需求及实现逻辑(掌握)3 resultMap当sql查询列名和pojo中属性名不一致时,如果还要使用该pojo进行映射使用resultType=”pojo”是无法完成映射,需要使用resultMap对列名和属性名作一个对应关系。测试resultMap:1、 编写mapper.xml2、 编写mapper.java3、 在SqlMapconfig.xml配置mapper使用包扫描的方式resultMap在使用时要进行定义:使用resultMap4 案例实现mybatis综合查询4.1 需求:用户购买商品,需要下订单,如果一次购买多个商品用户可以下一个或多个订单。网站的售后根据用户订单去发货。4.2 数据模型:数据库表设计、表与表的关系。用户表:userId:主键Username:用户名称订单表:ordersId:主键user_id:外键,用户idorder_number:订单号外键:user_id商品信息表:Id:商品iditem_name:商品名称item_price:商品定价订单明细表:记录订单的内容(购买信息)Id:主键orders_id:订单id(外键)item_id:商品id(外键)item_num:购买数据item_price:购买价格外键:orders_id外键:item_id一个用户对多个订单一个订单对应一个用户一个订单对应多个明细一个明细对应一个商品一个商品对应多个明细一个订单对应多个商品一个商品对应多个订单总结:订单和商品多对多关系一个明细对应一个订单分析表与表的关系:1、先分析数据库级别的关系(外键关系)2、再分析表与表的业务关系。注意:一对多业务关系、一对一业务关系、多对多业务关系,这些业务关系是建立某种业务意义上。用户-订单一个用户可以下多个订单,一对多关系。一个订单只允许一个用户创建,一对一关系(是多对一关系的特例) 通过订单对查询用户,根据订单表中的外键查询用户,只能查询一条用户记录订单订单明细一个订单可以包括多个明细,一对多关系一个明细只允许在一个订单中,一对一一个订单允许购买多个商品(对应多个明细),多个明细允许在一个订单中,多对一关系订单明细商品一个订单明细对应一个商品,一对一关系 通过订单明细查询商品,根据订单表中的商品id外键查询商品一条记录一个商品对应多个明细,一对多关系订单-商品一个订单可以购买多个商品,一对多关系一个商品可以被多个订单购买,一对多关系总结出:订单和商品之间是多对多关系,两张表在数据库级别没有关系,是通过订单明细表建立业务关系。4.3 一对一关系查询需求:查询订单及订单关联的用户信息设计:写sql语句时先找到主查询表,再找关联查询表。主查询表:订单表关联查询表:用户表查询订单表记录,通过订单表中外键关联查询用户信息Sql:如果通过外键关联,就可以使用内链接,通过外键查询父表会查询出多条记录。SELECT orders.*, user.username, user.birthday, user.sex, user.address FROM orders, USER WHERE orders.user_id = user.id开发:Po类:4.3.1 1种方式:使用resultType作结果集映射Mapper.xml自定义的pojo类:Mapper.java注意:查询列中如果pojo中没有指定的属性,需要扩展pojo类,通常让pojo继承一个包括字段较多的po类。使用resultType对程序开发很直观。4.3.2 2种方式:使用resultMap作结果集映射Sql:SELECT orders.*, user.username, user.birthday, user.sex, user.address FROM orders, USER WHERE orders.user_id = user.id使用resultMap将用户信息映射到po类(Orders)中的User(po)属性。修改Orders.java,添加User属性定义resultMap:确定订单及用户信息最终映射的po类是Orders.java 总结:使用resultMap需要对映射列进行定义,对于程序员开发没有resultType直观简单,所以在企业开发中更常用resultType方式。4.4 一对多关系查询需求:查询订单及订单明细信息分析:主查询表:订单表关联查询表:订单明细信息Sql:在订单及用户基础上去写。SELECT orders.*, user.username, user.birthday, user.sex, user.address, orderdetail.id orderdetail_id, /订单明细的主键 orderdetail.item_id, orderdetail.item_num, orderdetail.item_priceFROM orders, USER, orderdetailWHERE orders.user_id = user.id AND orders.id = orderdetail.orders_id使用resultType还是resultMap。不能使用resultType将sql查询结果集映射成pojo,因为订单和订单明细是一对多,查询结果中订单信息有重复记录。使用resultMap,在Orders类中添加一个List orderDetails属性,通过resultMap将订单明细信息映射到集合属性中。目标:将sql查询结果集映射到orders这个po类,关联明细信息映射到orderdetails这个集合属性中。resultMap定义: SELECT orders.*, user.username, user.birthday, user.sex, user.address, orderdetail.id orderdetail_id, orderdetail.item_id, orderdetail.item_num, orderdetail.item_priceFROM orders, USER, orderdetailWHERE orders.user_id = user.id AND orders.id = orderdetail.orders_id 总结:一对多查询,如果要映射成一个list到po类中,无法使用resultType来完成的。定义resultMap时,可以继承。4.5 多对多查询需求:查询订单及商品信息分析:主查询表:订单表关联查询表:订单明细表,商品表,通过订单明细关联查询商品信息Sql:SELECT orders.*, user.username, user.birthday, user.sex, user.address, orderdetail.id orderdetail_id, #订单明细的主键 orderdetail.item_id, orderdetail.item_num, orderdetail.item_price, #购买价格 items.item_name, items.item_price item_price_price, #定价 items.item_detail FROM orders, USER, orderdetail, items WHERE orders.user_id = user.id AND orders.id = orderdetail.orders_id AND orderdetail.item_id = items.id开发:Mapper.xml使用resultMap映射:将订单明细信息映射到Orders.java中的List orderdetails中,将商品信息映射到Orderdetail中的items。修改Orders.java类,添加List orderdetails属性在Orderdetail中添加items属性定义resultMap:SELECTorders.*,user.username,user.birthday,user.sex,user.address,orderdetail.id orderdetail_id,orderdetail.item_id,orderdetail.item_num,orderdetail.item_price,items.item_name,items.item_price item_price_price,items.item_detailFROMorders,USER,orderdetail,itemsWHERE orders.user_id = user.idAND orders.id = orderdetail.orders_idAND orderdetail.item_id = items.idMapper.java小结:association:关联查询单个对象,定义映射信息collection:关联查询集合对象,定义映射信息定义区别:Association使用javaType指定映射对象的类型Collection使用ofType指定集合List中对象类型5 延迟加载5.1 需求:在进行多表关联查询时,查询单表的速度比多表关联查询要快,在你需要单表数据时应该只查询单表的数据,当需要关联查询其它表数据时这时进行关联查询。案例:查询订单信息,关联查询用户信息 5.2 实现方式1:定义为两个查询,查询订单是一个,关联查询用户是一个在mapper.xml中定义两个statement,l 一个statement查询订单SELECT orders.* FROM Ordersl 一个statement查询用户SELECT * FROM USER WHERE id=#id需要开发两个mapper接口。使用方法:调用第一个statement订单信息,当需要关联查询用户时调用第二个statement查询关联用户信息。5.3 实现方式2:定义statement只查询订单信息SELECT orders.* FROM Orders在association定义延迟加载:指定select关联查询的statement的id(根据用户id查询用户信息)当要关联查询用户信息时,通过column指定的列关联查询findUserById,最终查询到用户信息findUserById定义使用方法:只需要定义一个mapper查询订单信息,mapper内部支持延迟加载用户信息,默认只查询单表数据即订单表的数据,当需要获取用户信息时才关联查询(通过调用findUserById)用户信息获取用户时机:调用Orders.java中getUser方法,此时才会进行加载。配置延迟加载开关:lazyLoadingEnabled:延迟加载的总开关,设置trueaggressiveLazyLoading:积极延迟加载,默认为false,改积极为消极(按需加载),设置fals在SqlMapconfig.xml中setting设置mybatis全局参数。测试延迟加载:只查询单表:调用findOrdersListLazyLoading,只查询订单信息,此时只会发出查询订单表的sql延迟加载关联信息:从订单信息list中获取某个订单的用户信息:调用orders.getUser()方法,此时mybatis才会发出关联查询用户的sql。小结:Mybatis通过resultMap提供延迟加载的配置,可以在association和collection中配置延迟加载。通过association只能延迟加载单个对象,通过collection可以延迟加载集合对象。应用场合在service接口中,service调用mapper,建议将关联查询(需要多表关联)数据mapper,定义成延迟加载。6 一级缓存Mybatis默认使用一级缓存,在同一个SqlSession中,执行相同的查询,进行一级缓存,一级缓存的范围是同一个SqlSession测试:根据用户id查询用户信息第一次调用时发出sql(这时没有缓存)第二次调用相同的sql,从缓存中取出数据Mybatis在每次查询数据库前从缓存中判断是否有缓存数据,如果有就从缓存取。Mybatis保存一级缓存使用数据结构是个Map,key是唯一标识statement,由sql语句,statement的hashcode,sql参数(输入和输出)。组成。Value是sql查询的数据代码;测试结果:刷新一级缓存:对用户进行修改,应该清除一级缓存,第二次查询从数据库查询,避免读取脏数据。在一个Sqlsession中如果执行了sqlSmit(), mybatis会清除一级缓存。测试代码:/ 一级缓存测试,如果commit提交事务,清除一级缓存Testpublic void testFindUserByIdCache1Clear() SqlSession sqlSession = sqlSessionFactory.openSession();/ 得到动态代理对象UserMapper userMapper = sqlSession.getMapper(UserMapper.class);/ 发出一次查询User user1 = userMapper.findUserById(87);System.out.println(user1);/修改用户的信息/更新用户信息User user_update = new User();user_update.setId(87);user_update.setUsername(赵六8);userMapper.updateUserById(user_update);sqlSmit();/提交事务,这时会清除一级缓存/ 发出第二次查询User user2 = userMapper.findUserById(87);System.out.println(user2);sqlSession.close();源代码跟踪:Mybaits在查询数据时,从二级缓存看,再从一级缓存找,如果一级缓存有数据,就直接返回,如果没有则从数据库查询:loalCache就是一级缓存数据结构如果为空从数据库查询;如果localCache中有查询的数据,从缓存取:7 二级缓存(掌握使用场景)二级缓存的缓存范围是一个mapper的相同的namespache。需要开启二级缓存配置,才能使用二级缓存。1. 在核心配置文件SqlMapConfig.xml中加入2、在mapper.xml中开启二级缓存,这个mapper的namespace下的statemnt就可以二级缓存了。在maper.xml不限于一个SqlSession.4、 将输出结果映射的pojo类进行序列化测试步骤:创建两个SqlSession,在不同的SqlSession中执行相同的sql查询。Testpublic void testFindUserByIdCache2() SqlSession sqlSession1 = sqlSessionFactory.openSession();SqlSession sqlSession2 = sqlSessionFactory.openSession();/ 得到动态代理对象UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);/ 发出一次查询User user1 = userMapper1.findUserById(87);System.out.println(user1);sqlSession1.close();/ 发出第二次查询/从二级缓存中查询数据,不发出sqlUser user2 = userMapper2.findUserById(87);System.out.println(user2);sqlSession2.close();测试结果:刷新缓存:用户修改后,执行commit(),mybatis刷新(清除)二级缓存,只会清除该mapper下的二级缓存。Mybatis执行一个配置:flushCache=true在statement定义配置flushCache,默认值为true,只要该mapper下执行statement进行commit()操作都会清除二级缓存。测试:新创建一个SqlSession,执行update操作,这时应该刷新缓存。测试代码:/ 二级缓存测试Testpublic void testFindUserByIdCache2() SqlSession sqlSession1 = sqlSessionFactory.openSession();SqlSession sqlSession2 = sqlSessionFactory.openSession();/ 用于更新SqlSession sqlSession3 = sqlSessionFactory.openSession();/ 得到动态代理对象UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);UserMapper userMapper3 = sqlSession3.getMapper(UserMapper.class);/ 发出一次查询User user1 = userMapper1.findUserById(87);System.out.println(user1);sqlSession1.close();/ 更新用户/ 更新用户信息User user_update = new User();user_update.setId(87);user_update.setUsername(赵六8);userMapper3.updateUserById(user_update);sqlSmit();/ 提交事务,这时会清除二级缓存sqlSession3.close();/ 发出第二次查询/ 上边执行commit操作清除了二级缓存,从二级缓存中查询不到数据,发出sqlUser user2 = userMapper2.findUserById(87);System.out.println(user2);sqlSession2.close();测试结果:二级缓存控制:对mapper下的某个statement不进行二级缓存。在statement定义中设置useCache=false,默认值true二级缓存代码跟踪:Mybatis先从二级缓存中查询数据,如果中则从缓存中取数据,如果没有从数据库查询,Cache就是二级缓存的数据结构使用场景:1、针对复杂的查询或统计的功能,用户不要求每次都查询到最新信息,使用二级缓存,通过刷新间隔flushInterval设置刷新间隔时间,由mybatis自动刷新。比如:实现用户分类统计sql,该查询非常耗费时间。将用户分类统计sql查询结果使用二级缓存,同时设置刷新间隔时间:flushInterval(一般设置时间较长,比如30分钟,60分钟,24小时,根据需求而定)2、针对信息变化频率高,需要显示最新的信息,使用二级缓存。将信息查询的statement与信息的增、删、改定义在一个mapper.xml中,此mapper实现二级缓存,当执行增、删、修改时,由mybatis及时刷新缓存,满足用户从缓存查询到最新的数据。比如:新闻列表显示前10条,该查询非常快,但并发大对数据也有压力。将新闻列表查询前10条的sql进行二级缓存,这里不用刷新间隔时间,当执行新闻添加、删除、修改时及时刷新缓存。8 Mybatis与springmvc整合8.1 整合Dao层:将mybatis和spring整合,让spring管理SqlSessoinFactory及mapper。l 环境准备:Jar包:Spring官方没有提供mybatis的整合包,mybatis官方提供了spring与mybatis的整合包。mybatis-spring-1.2.2.jarmybatis自己的jarspring的jar(包括springmvc的jar)第三方连接池 dbcp数据库驱动 mysql参考:l 配置文件Mybatis的配置文件 SqlMapConfig.xmlSpring的配置文件 applicationContext.xml-配置公用的,加载属性文件,数据源、事务applicationContext-dao.xml-配置SqlSessoinFactory及perties -数据库连接参数perties-日志配置文件l 进行整合开发mapper的过程。方式1:开发dao接口及dao接口实现通过spring管理dao 接口,且将SqlSessionFactory注入到dao接口中。要注入SqlSessionFactory,让dao接口实现类继承SqlSessionDaoSupport,此类中有setSqlsessionFactory()的方法可以注入SqlSessionFactory,可以自动调用getSqlSession()创建一个SqlSession编写dao接口:在applicationContext-dao.xml配置dao测试dao:方式2:mapper接口开发,采用MapperFactoryBean生成动态代理开发mapper接口:在spring容器中配置mapper:让spring通过MapperFactoryBean生成mapper的动态代理对象。配置如下;测试:使用MapperFactoryBean生成动态代理对象,配置繁琐,不建议使用。方式3:mapper接口开发,采用MapperScannerConfigurer扫描mapper开发mapper接口:Mapper.xml和mapper.java同名且在一个目录。在spring容器中配置mapper的自动扫描器,MapperScannerConfigurer测试:建议使用扫描器自动创建mapper动态代理对象。需要掌握第一种方法和第三种方法。8.2 整合service层:让spring管理serivce接口。整合目标:service可以调用mapper接口。对service的方法进行事务控制。Service接口开发;针对service建议在spring容器中手动配置,好处就是方便进行系统管理和维护。创建applicationContext-service.xml用配置service接口。测试:事务控制:企业开发中建议进行aop配置方式管理事务,更好规范程序员的编码,方便项目管理。在applicationContext.xml文件中配置事务。 测试:写一个用于事务测试的service方法,在方法中有两个数据库操作,让其它一个操作异常抛出runtimeExection异常,事务自动回滚。8.3 整合action层:加入springmvc的jar包整合目标:Action类调用serivce方法,将service查询出的信息在页面展示。配置文件:创建springmvc.xml -配置处理器映射器 -配置处理器适配器使用替代映射器适配器 -配置视图解析器在web.xml中配置:加载spring容器contextConfigLocation/WEB-INF/classes/spring/applicationContext.xml,/WEB-INF/classes/spring/applicationContext-*.xmlorg.springframework.web.context.ContextLoaderListenerspr

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论