|
"\u003Cdiv\u003E\u003Cdiv class=\"pgc-img\"\u003E\u003Cimg src=\"http:\u002F\u002Fp9.pstatp.com\u002Flarge\u002Fdfic-imagehandler\u002F92a6c20c-e4ed-490b-84b2-a36199882449\" img_width=\"1200\" img_height=\"800\" alt=\"Mybatis动态sql及性能优化\" inline=\"0\"\u003E\u003Cp class=\"pgc-img-caption\"\u003E\u003C\u002Fp\u003E\u003C\u002Fdiv\u003E\u003Cp\u003E\u003Cstrong\u003E内容\u003C\u002Fstrong\u003E\u003C\u002Fp\u003E\u003Cpre\u003E1.回顾\u003Cbr\u003E2.动态sql\u003Cbr\u003E3.性能优化\u003Cbr\u003E 懒加载机制\u003Cbr\u003E 一级缓存\u003Cbr\u003E 二级缓存\u003Cbr\u003E\u003C\u002Fpre\u003E\u003Cp\u003E\u003Cstrong\u003E一.回顾\u003C\u002Fstrong\u003E\u003C\u002Fp\u003E\u003Cpre\u003E\u003Cbr\u003E1.config文件常用标签\u003Cbr\u003E properties标签:引入外部properties文件资源。\u003Cbr\u003E settings标签:设置mybatis全局行为。\u003Cbr\u003E typeAlias标签:减少mapper文件配置,给模型类起别名。\u003Cbr\u003E transactionManager标签:配置mybatis的事务行为(JDBC|MANAGED)\u003Cbr\u003E dataSource标签:配置mybatis数据源(POOLED|UNPOOLED|JNDI)\u003Cbr\u003E mappers标签:引入Mapper文件或接口(url|resources|class|package)\u003Cbr\u003E2.Mapper文件常用标签\u003Cbr\u003E a. resultMap标签:对查询的结果进行封装处理\u003Cbr\u003E 简单pojo类型处理,只需处理表中字段和对像中属性映射处理。\u003Cbr\u003E 包装pojo类型处理,使用Collection处理包装集合类型的对像,association处理包含单个pojo对像。\u003Cbr\u003E Collection处理的两种方式:\u003Cbr\u003E 1.连接查询join\u003Cbr\u003E 2.通过多条select查询的方式。\u003Cbr\u003E association处理两种方式:\u003Cbr\u003E 1.连接查询join\u003Cbr\u003E 2.通过多条select查询的方式。\u003Cbr\u003E \u003Cbr\u003E discriminor鉴别器:根据查询结果中某个字段作为标识符,根据其查询的值,进行分类封装处理。\u003Cbr\u003E \u003Cbr\u003E b.主键映射策略:如果主键由数据库生成,而不是手动指定,怎么获取该主键的问题。\u003Cbr\u003E 一般使用selectKey标签处理。\u003Cbr\u003E 3.自定义封装结果集(了解):\u003Cbr\u003E 按照自已定义方式把数据库返回结果封装成自己想要的类型。\u003Cbr\u003E 一般自己建立结果的处理类,实现ResultHandler接口,重写里面的方法。\u003Cbr\u003E 一般在select(\"statementId\",params,ResultHandler实现类对像)\u003Cbr\u003E\u003C\u002Fpre\u003E\u003Cp\u003E\u003Cstrong\u003E二.动态Sql\u003C\u002Fstrong\u003E\u003C\u002Fp\u003E\u003Cp\u003E\u003Cstrong\u003E1.解决什么样问题\u003C\u002Fstrong\u003E\u003C\u002Fp\u003E\u003Cpre\u003E\u003Cbr\u003E用来解决sql语句where后条件的拼接问题,\u003Cbr\u003E使用流程控制标签来完成条件的拼接:if标签,where标签,foreach标签。。。。\u003Cbr\u003E\u003C\u002Fpre\u003E\u003Cp\u003E\u003Cstrong\u003E2.常用动态sql标签\u003C\u002Fstrong\u003E\u003C\u002Fp\u003E\u003Cpre\u003E\u003Cbr\u003E1.if标签\u003Cbr\u003E2.choose when otherwise标签\u003Cbr\u003E3.trim标签\u003Cbr\u003E4.foreache标签\u003Cbr\u003E5.where标签\u003Cbr\u003E6.set标签\u003Cbr\u003E\u003C\u002Fpre\u003E\u003Cp\u003E\u003Cstrong\u003E2.1 if标签\u003C\u002Fstrong\u003E\u003C\u002Fp\u003E\u003Cpre\u003E\u003Cbr\u003E和java中的if语句类似。\u003Cbr\u003E \u003Cbr\u003E select * from USER \u003Cbr\u003E where 1=1\u003Cbr\u003E \u003Cbr\u003E \u003Cbr\u003E and id = #{id}\u003Cbr\u003E \u003Cbr\u003E \u003Cbr\u003E and username=#{username}\u003Cbr\u003E \u003Cbr\u003E \u003Cbr\u003E and password=#{password}\u003Cbr\u003E \u003Cbr\u003E \u003Cbr\u003E and address=#{address}\u003Cbr\u003E \u003Cbr\u003E \u003Cbr\u003E\u003C\u002Fpre\u003E\u003Cp\u003E\u003Cstrong\u003E2.2 where标签\u003C\u002Fstrong\u003E\u003C\u002Fp\u003E\u003Cpre\u003E\u003Cbr\u003E根据查询条件是否存在,来决定是否生成where字符串。\u003Cbr\u003E可以去除where后面紧跟的sql关键字, 如or或and\u003Cbr\u003E\u003Cbr\u003E \u003Cbr\u003E select * from USER\u003Cbr\u003E \u003Cbr\u003E \u003Cbr\u003E and id = #{id}\u003Cbr\u003E \u003Cbr\u003E \u003Cbr\u003E and username=#{username}\u003Cbr\u003E \u003Cbr\u003E \u003Cbr\u003E and password=#{password}\u003Cbr\u003E \u003Cbr\u003E \u003Cbr\u003E and address=#{address}\u003Cbr\u003E \u003Cbr\u003E \u003Cbr\u003E \u003Cbr\u003E\u003C\u002Fpre\u003E\u003Cp\u003E\u003Cstrong\u003E2.3 choose when otherwise\u003C\u002Fstrong\u003E\u003C\u002Fp\u003E\u003Cpre\u003E\u003Cbr\u003E和java中switch case作用类似。\u003Cbr\u003E不管有多少条件满足,只拼接其中一个条件。\u003Cbr\u003E\u003Cbr\u003E \u003Cbr\u003E \u003Cbr\u003E select * from USER\u003Cbr\u003E \u003Cbr\u003E \u003Cbr\u003E \u003Cbr\u003E and id = #{id}\u003Cbr\u003E \u003Cbr\u003E \u003Cbr\u003E and username=#{username}\u003Cbr\u003E \u003Cbr\u003E \u003Cbr\u003E and password=#{password}\u003Cbr\u003E \u003Cbr\u003E \u003Cbr\u003E and address=#{address}\u003Cbr\u003E \u003Cbr\u003E \u003Cbr\u003E and 1=1\u003Cbr\u003E \u003Cbr\u003E \u003Cbr\u003E \u003Cbr\u003E \u003Cbr\u003E\u003C\u002Fpre\u003E\u003Cp\u003E\u003Cstrong\u003E2.4 Set标签\u003C\u002Fstrong\u003E\u003C\u002Fp\u003E\u003Cpre\u003E\u003Cbr\u003Eset用法和上面where用法一致。\u003Cbr\u003E可以生成update语句中的set关键字,也可去除sql关键字,如逗号(set标签中sql字符串最后的逗号)\u003Cbr\u003E\u003Cbr\u003E update USER\u003Cbr\u003E \u003Cbr\u003E \u003Cbr\u003E username = #{username},\u003Cbr\u003E \u003Cbr\u003E \u003Cbr\u003E password=#{password},\u003Cbr\u003E \u003Cbr\u003E \u003Cbr\u003E address=#{address},\u003Cbr\u003E \u003Cbr\u003E \u003Cbr\u003E where id = #{id}\u003Cbr\u003E \u003Cbr\u003E\u003C\u002Fpre\u003E\u003Cp\u003E\u003Cstrong\u003E2.5 foreach标签\u003C\u002Fstrong\u003E\u003C\u002Fp\u003E\u003Cpre\u003E\u003Cbr\u003E类似于java中的foreach迭代。把传入sql语句中的数组类型或集合类型数据进行遍历操作。\u003Cbr\u003E \u003Cbr\u003E \u003Cbr\u003E select * from USER \u003Cbr\u003E \u003Cbr\u003E #{id}\u003Cbr\u003E \u003Cbr\u003E \u003Cbr\u003E\u003Cbr\u003E \u003Cbr\u003E \u003Cbr\u003E select * from USER \u003Cbr\u003E \u003Cbr\u003E #{id}\u003Cbr\u003E \u003Cbr\u003E \u003Cbr\u003E\u003C\u002Fpre\u003E\u003Cp\u003E\u003Cstrong\u003E2.6 trim标签\u003C\u002Fstrong\u003E\u003C\u002Fp\u003E\u003Cpre\u003E\u003Cbr\u003E可以删除sql语句指定的字符串。\u003Cbr\u003E\u003Cbr\u003E\u003Cbr\u003E\u003Cbr\u003E update USER\u003Cbr\u003E \u003Cbr\u003E \u003Cbr\u003E ,username = #{username}\u003Cbr\u003E \u003Cbr\u003E \u003Cbr\u003E ,password=#{password}\u003Cbr\u003E \u003Cbr\u003E \u003Cbr\u003E ,address=#{address}\u003Cbr\u003E \u003Cbr\u003E \u003Cbr\u003E where id = #{id}\u003Cbr\u003E \u003Cbr\u003E \u003Cbr\u003E \u003Cbr\u003E update USER\u003Cbr\u003E \u003Cbr\u003E \u003Cbr\u003E username = #{username},\u003Cbr\u003E \u003Cbr\u003E \u003Cbr\u003E password=#{password},\u003Cbr\u003E \u003Cbr\u003E \u003Cbr\u003E address=#{address},\u003Cbr\u003E \u003Cbr\u003E \u003Cbr\u003E where id = #{id}\u003Cbr\u003E \u003Cbr\u003E\u003C\u002Fpre\u003E\u003Cp\u003E\u003Cstrong\u003E三.性能优化\u003C\u002Fstrong\u003E\u003C\u002Fp\u003E\u003Cp\u003E\u003Cstrong\u003E1.懒加载机制(lazy)\u003C\u002Fstrong\u003E\u003C\u002Fp\u003E\u003Cpre\u003E\u003Cbr\u003E当进行多表关联查询时,如果关联中数据暂时用不到,可以不去查询,当用到的时候,再发送sql语句去数据库关联出来。\u003Cbr\u003E目的是:减少与数据库的交互行为,即减少数据库的开消。\u003Cbr\u003E注意:\u003Cbr\u003Ejoin查询不支持lazy,多条select查询才支持lazy!\u003Cbr\u003E\u003C\u002Fpre\u003E\u003Cp\u003E\u003Cstrong\u003E2.步骤\u003C\u002Fstrong\u003E\u003C\u002Fp\u003E\u003Cpre\u003E\u003Cbr\u003E1.在setting标签中设置lazy开关\u003Cbr\u003E \u003Cbr\u003E \u003Cbr\u003E \u003Cbr\u003E \u003Cbr\u003E2.使用select方式进行关联查询\u003Cbr\u003E\u003C\u002Fpre\u003E\u003Cp\u003E\u003Cstrong\u003EModel类\u003C\u002Fstrong\u003E\u003C\u002Fp\u003E\u003Cpre\u003E\u003Cbr\u003E\u002F\u002FUser类\u003Cbr\u003Epublic class User {\u003Cbr\u003E\u003Cbr\u003E private Integer id;\u003Cbr\u003E private String username;\u003Cbr\u003E private String password;\u003Cbr\u003E private String address;\u003Cbr\u003E \u003Cbr\u003E private List list;\u003Cbr\u003E}\u003Cbr\u003E \u003Cbr\u003E\u002F\u002FOrders类\u003Cbr\u003Epublic class Orders {\u003Cbr\u003E \u003Cbr\u003E private int id;\u003Cbr\u003E private String oname;\u003Cbr\u003E private int oprice;\u003Cbr\u003E \u003Cbr\u003E}\u003Cbr\u003E\u003C\u002Fpre\u003E\u003Cp\u003E\u003Cstrong\u003EUserMapper接口\u003C\u002Fstrong\u003E\u003C\u002Fp\u003E\u003Cpre\u003E\u003Cbr\u003Epublic interface UserMapper { \u003Cbr\u003E public User selectById(User user);\u003Cbr\u003E}\u003Cbr\u003E\u003C\u002Fpre\u003E\u003Cp\u003E\u003Cstrong\u003EUserMapper.xml\u003C\u002Fstrong\u003E\u003C\u002Fp\u003E\u003Cpre\u003E\u003Cbr\u003E\u003Cbr\u003E\u003Cbr\u003E \u003Cbr\u003E \u003Cbr\u003E \u003Cbr\u003E \u003Cbr\u003E \u003Cbr\u003E \u003Cbr\u003E \u003Cbr\u003E \u003Cbr\u003E \u003Cbr\u003E select * from USER where id = #{id}\u003Cbr\u003E \u003Cbr\u003E \u003Cbr\u003E\u003Cbr\u003E\u003C\u002Fpre\u003E\u003Cp\u003E\u003Cstrong\u003EOrdersMapper接口\u003C\u002Fstrong\u003E\u003C\u002Fp\u003E\u003Cpre\u003E\u003Cbr\u003Epublic interface OrdersMapper {\u003Cbr\u003E public List selectByUid(int uid);\u003Cbr\u003E}\u003Cbr\u003E\u003Cbr\u003E\u003C\u002Fpre\u003E\u003Cp\u003E\u003Cstrong\u003EOrdersMapper.xml\u003C\u002Fstrong\u003E\u003C\u002Fp\u003E\u003Cpre\u003E\u003Cbr\u003E\u003Cbr\u003E\u003Cbr\u003E \u003Cbr\u003E select * from orders where uid = #{uid}\u003Cbr\u003E \u003Cbr\u003E\u003Cbr\u003E\u003Cbr\u003E\u003C\u002Fpre\u003E\u003Cp\u003E\u003Cstrong\u003EUserService类\u003C\u002Fstrong\u003E\u003C\u002Fp\u003E\u003Cpre\u003E\u003Cbr\u003Epublic class UserService {\u003Cbr\u003E\u003Cbr\u003E public User findById(User user) {\u003Cbr\u003E\u003Cbr\u003E SqlSession session = MybatisUtil.findSqlSession();\u003Cbr\u003E\u003Cbr\u003E UserMapper mapper = session.getMapper(UserMapper.class);\u003Cbr\u003E\u003Cbr\u003E User findUser = mapper.selectById(user);\u003Cbr\u003E\u003Cbr\u003E session.close();\u003Cbr\u003E\u003Cbr\u003E return findUser;\u003Cbr\u003E\u003Cbr\u003E }\u003Cbr\u003E\u003Cbr\u003E}\u003Cbr\u003E\u003C\u002Fpre\u003E\u003Cp\u003E\u003Cstrong\u003ETest类\u003C\u002Fstrong\u003E\u003C\u002Fp\u003E\u003Cpre\u003E\u003Cbr\u003Epublic class TestLazy {\u003Cbr\u003E\u003Cbr\u003E UserService ser = new UserService();\u003Cbr\u003E \u003Cbr\u003E @Test\u003Cbr\u003E public void testLazy(){\u003Cbr\u003E \u003Cbr\u003E User user = new User();\u003Cbr\u003E user.setId(1);\u003Cbr\u003E User findUser = ser.findById(user);\u003Cbr\u003E \u002F\u002F当只使用User表中数据时,只发送一条查询User表的sql语句。\u003Cbr\u003E System.out.println(findUser.getUsername());\u003Cbr\u003E \u002F\u002F当主动使用关联表中数据时,mybaits才再次发送查询语句去查询关联表。如果不使用,则该条sql将不会发送给数据库。\u003Cbr\u003E \u002F\u002FSystem.out.println(findUser.getList());\u003Cbr\u003E }\u003Cbr\u003E}\u003Cbr\u003E\u003C\u002Fpre\u003E\u003Cp\u003E\u003Cstrong\u003E3.一级缓存\u003C\u002Fstrong\u003E\u003C\u002Fp\u003E\u003Cp\u003E\u003Cstrong\u003E3.1缓存概念\u003C\u002Fstrong\u003E\u003C\u002Fp\u003E\u003Cpre\u003E\u003Cbr\u003E目的,减少与数据库的交互行为,当读取同一条数据时,优先从内存中的缓存中读取,如果能读到数据(命中数据),则就不需要交互数据库,如果读不到,则会交互数据库,查寻内容,放在缓存中,以备下一次查询时,在缓存中能命中数据,提高程序响应速度。\u003Cbr\u003E\u003C\u002Fpre\u003E\u003Cp\u003E\u003Cstrong\u003E3.2 mybatis的一级缓存\u003C\u002Fstrong\u003E\u003C\u002Fp\u003E\u003Cpre\u003E\u003Cbr\u003E1.一级缓存是默认使用的。\u003Cbr\u003E2.一级缓存指的就是sqlsession范围内缓存,在sqlsession中有一个数据区域,是map结构,这个区域就是一级缓存区\u003Cbr\u003E域。一级缓存中的key是由sql语句、条件、statement等信息组成一个唯一值。一级缓存中的value,就是查询出的结果\u003Cbr\u003E对象。\u003Cbr\u003E3.当数据库对应表发生增删改时,并执行commit操作时,默认会刷新一级缓存。\u003Cbr\u003E如下图所示:\u003Cbr\u003E\u003C\u002Fpre\u003E\u003Cdiv class=\"pgc-img\"\u003E\u003Cimg src=\"http:\u002F\u002Fp1.pstatp.com\u002Flarge\u002Fpgc-image\u002F40ef149a23d042a7a823a5ee9d725d4f\" img_width=\"584\" img_height=\"381\" alt=\"Mybatis动态sql及性能优化\" inline=\"0\"\u003E\u003Cp class=\"pgc-img-caption\"\u003E\u003C\u002Fp\u003E\u003C\u002Fdiv\u003E\u003Cpre\u003E\u003Cbr\u003E第一次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,如果没有,从数据库查询用户信\u003Cbr\u003E息。得到用户信息,将用户信息存储到一级缓存中。\u003Cbr\u003E如果sqlSession去执行commit操作(执行插入、更新、删除),清空SqlSession中的一级缓存,这样做的目的为\u003Cbr\u003E了让缓存中存储的是最新的信息,避免脏读。\u003Cbr\u003E第二次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,缓存中有,直接从缓存中获取用户\u003Cbr\u003E信息\u003Cbr\u003E\u003C\u002Fpre\u003E\u003Cp\u003E\u003Cstrong\u003E3.3缓存测试\u003C\u002Fstrong\u003E\u003C\u002Fp\u003E\u003Cp\u003E\u003Cstrong\u003EUserMapper.xml\u003C\u002Fstrong\u003E\u003C\u002Fp\u003E\u003Cpre\u003E\u003Cbr\u003E\u003Cbr\u003E \u003Cbr\u003E select * from USER where id = #{id}\u003Cbr\u003E \u003Cbr\u003E\u003Cbr\u003E\u003C\u002Fpre\u003E\u003Cp\u003E\u003Cstrong\u003EUserMapper接口\u003C\u002Fstrong\u003E\u003C\u002Fp\u003E\u003Cpre\u003E\u003Cbr\u003Epublic interface UserMapper {\u003Cbr\u003E public User selectById(User user);\u003Cbr\u003E}\u003Cbr\u003E\u003Cbr\u003E\u003C\u002Fpre\u003E\u003Cp\u003E\u003Cstrong\u003EUserService类\u003C\u002Fstrong\u003E\u003C\u002Fp\u003E\u003Cpre\u003E\u003Cbr\u003Epublic class UserService {\u003Cbr\u003E\u003Cbr\u003E public User findById(User user) {\u003Cbr\u003E\u003Cbr\u003E SqlSession session = MybatisUtil.findSqlSession();\u003Cbr\u003E\u003Cbr\u003E UserMapper mapper = session.getMapper(UserMapper.class);\u003Cbr\u003E\u003Cbr\u003E \u002F\u002F查询两次\u003Cbr\u003E User findUser = mapper.selectById(user);\u003Cbr\u003E System.out.println(findUser.getUsername());\u003Cbr\u003E \u003Cbr\u003E \u002F\u002F如果不执行commit(),则发现执行两次查询时,只发送一条sql到数据库,则验证一级缓存存在。\u003Cbr\u003E \u002F\u002F当执行commit()操作时,mybatis上下文会默认你进行增删改数据了,则会清空一级缓存;\u003Cbr\u003E session.commit(true);\u003Cbr\u003E \u003Cbr\u003E User findUser2 = mapper.selectById(user);\u003Cbr\u003E \u003Cbr\u003E System.out.println(findUser+\"====\"+findUser2.getUsername());\u003Cbr\u003E\u003Cbr\u003E session.close();\u003Cbr\u003E\u003Cbr\u003E return null;\u003Cbr\u003E\u003Cbr\u003E }\u003Cbr\u003E\u003Cbr\u003E}\u003Cbr\u003E\u003C\u002Fpre\u003E\u003Cp\u003E\u003Cstrong\u003E作业\u003C\u002Fstrong\u003E\u003C\u002Fp\u003E\u003Cpre\u003E1.掌握动态sql语法\u003Cbr\u003E2.掌握lazy机制\u003Cbr\u003E3.掌握一级缓存\u003Cbr\u003E\u003C\u002Fpre\u003E\u003Cdiv class=\"tt-column-card\" data-content='{\"thumb_url\":\"http:\u002F\u002Fp9.pstatp.com\u002Flarge\u002Fpgc-image\u002F1553579882114eb7404555d\",\"title\":\"java语言基础篇\",\"author_description\":\"KuangXiang\",\"price\":98,\"share_price\":23.52,\"sold\":1,\"column_id\":\"6672575843560063239\",\"distribution_user_id\":1626311779265543,\"new_thumb_url\":\"http:\u002F\u002Fsf3-ttcdn-tos.pstatp.com\u002Fimg\u002Fpgc-image\u002F1553579882114eb7404555d\"}'\u003E\u003Cp class=\"column-placeholder\"\u003E\u003C\u002Fp\u003E\u003C\u002Fdiv\u003E\u003C\u002Fdiv\u003E"'.slice(6, -6), groupId: '6703859578909491716
' R# B8 X4 L, e9 i6 W来源:https://www.toutiao.com/a6703859578909491716/
% M P* {, c' p) l) |! Q免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |
|