();
43 | itemTypes.put("101", "数码");
44 | itemTypes.put("102", "母婴");
45 |
46 | return itemTypes;
47 | }
48 | ```
49 |
50 | 页面上可以得到itemTypes数据。
51 |
52 |
53 | ```jsp
54 | |
55 | 商品名称:
56 | 商品类型:
57 |
62 | |
63 | ```
64 |
65 | 3.使用最简单方法使用model,可以不用`@ModelAttribute`
66 |
67 | ```java
68 | //可以直接使用model将提交pojo回显到页面
69 | //model.addAttribute("items", itemsCustom);
70 | ```
71 |
72 |
73 | ## 简单类型数据回显
74 |
75 | 使用最简单方法使用model
76 |
77 | `model.addAttribute("id", id);`
78 |
79 |
80 |
--------------------------------------------------------------------------------
/springmvc/04 前端控制器.md:
--------------------------------------------------------------------------------
1 | # 04 前端控制器
2 |
3 | 标签: springmvc
4 |
5 | ---
6 |
7 | **Contents**
8 |
9 |
10 |
11 | ---
12 |
13 |
14 | 通过前端控制器源码分析springmvc执行过程
15 |
16 | 1. 前端控制器接收请求
17 |
18 | 调用`doDispatch`方法
19 |
20 | ```java
21 | protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
22 | HttpServletRequest processedRequest = request;
23 | HandlerExecutionChain mappedHandler = null;
24 | boolean multipartRequestParsed = false;
25 |
26 | 。。。。。
27 | }
28 | ```
29 |
30 | 2. 前端控制器调用`HandlerMapping`(处理器映射器)根据url查找Handler
31 |
32 |
33 | ```java
34 | // Determine handler for the current request.
35 | mappedHandler = getHandler(processedRequest);
36 | ```
37 |
38 | ```java
39 | /**
40 | * Return the HandlerExecutionChain for this request.
41 | * Tries all handler mappings in order.
42 | * @param request current HTTP request
43 | * @return the HandlerExecutionChain, or {@code null} if no handler could be found
44 | */
45 | protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
46 | for (HandlerMapping hm : this.handlerMappings) {
47 | if (logger.isTraceEnabled()) {
48 | logger.trace(
49 | "Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
50 | }
51 | HandlerExecutionChain handler = hm.getHandler(request);
52 | if (handler != null) {
53 | return handler;
54 | }
55 | }
56 | return null;
57 | }
58 | ```
59 |
60 | 3. 调用处理器适配器执行Handler,得到执行的结果`ModelAndView mv`
61 |
62 | 在`doDispatch`方法中
63 |
64 | ```java
65 | // Actually invoke the handler.
66 | mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
67 | ```
68 |
69 | 4. 视图渲染,将model数据填充到request域
70 |
71 | `doDispatch`->`processDispatchResult`->`render`
72 |
73 | 在`render`方法中,视图解析得到view
74 |
75 | ```java
76 | // We need to resolve the view name.
77 | view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request);
78 |
79 | ```
80 |
81 | 调用view的渲染方法,将model数据填充到request域
82 |
83 | 在`render`方法中,调用`View`接口的`render`方法
84 |
85 | ```java
86 | view.render(mv.getModelInternal(), request, response);
87 | ```
88 |
89 |
90 | 程序我也没细读,感觉分析比较浅,很多还没弄懂,等我系统阅读源码后会整理一篇好点的。
91 |
--------------------------------------------------------------------------------
/mybatis/02 mybatis概述.md:
--------------------------------------------------------------------------------
1 | # 02 mybatis概述
2 |
3 | 标签: mybatis
4 |
5 | ---
6 |
7 | **Contents**
8 |
9 | - [mybatis 介绍](#mybatis-介绍)
10 | - [框架原理](#框架原理)
11 | - [mybatis框架执行过程](#mybatis框架执行过程)
12 | - [mybatis开发dao的方法](#mybatis开发dao的方法)
13 | - [输入映射和输出映射](#输入映射和输出映射)
14 | - [动态sql](#动态sql)
15 |
16 |
17 |
18 | ---
19 |
20 |
21 | 本文对mybatis做一个简单介绍,包括框架原理,执行过程,开发方法,输入输出映射以及动态sql,我会在后续的系列文章中一一详细说明
22 |
23 | ## mybatis 介绍
24 |
25 | mybatis是一个持久层的框架,是apache下的顶级项目。
26 |
27 | mybatis托管到goolecode下,再后来托管到github下(https://github.com/mybatis/mybatis-3/releases)。
28 |
29 | mybatis让程序将主要精力放在sql上,通过mybatis提供的映射方式,自由灵活生成(半自动化,大部分需要程序员编写sql)满足需要sql语句。
30 |
31 | mybatis可以将向 preparedStatement中的输入参数自动进行输入映射,将查询结果集灵活映射成java对象。(输出映射)
32 |
33 |
34 |
35 |
36 |
37 |
38 | ## 框架原理
39 |
40 | mybatis框架
41 |
42 | 
43 |
44 |
45 | ## mybatis框架执行过程
46 |
47 | 1、配置mybatis的配置文件,SqlMapConfig.xml(名称不固定)
48 |
49 | 2、通过配置文件,加载mybatis运行环境,创建SqlSessionFactory会话工厂(SqlSessionFactory在实际使用时按单例方式)
50 |
51 | 3、通过SqlSessionFactory创建SqlSession。SqlSession是一个面向用户接口(提供操作数据库方法),实现对象是线程不安全的,建议sqlSession应用场合在方法体内。
52 |
53 | 4、调用sqlSession的方法去操作数据。如果需要提交事务,需要执行SqlSession的commit()方法。
54 |
55 | 5、释放资源,关闭SqlSession
56 |
57 |
58 | ## mybatis开发dao的方法
59 |
60 | 1.原始dao 的方法
61 |
62 | - 需要程序员编写dao接口和实现类
63 | - 需要在dao实现类中注入一个SqlSessionFactory工厂
64 |
65 | 2.mapper代理开发方法(建议使用)
66 |
67 | 只需要程序员编写mapper接口(就是dao接口)。
68 | 程序员在编写mapper.xml(映射文件)和mapper.java需要遵循一个开发规范:
69 |
70 | - mapper.xml中namespace就是mapper.java的类全路径。
71 | - mapper.xml中statement的id和mapper.java中方法名一致。
72 | - mapper.xml中statement的parameterType指定输入参数的类型和mapper.java的方法输入参数类型一致
73 | - mapper.xml中statement的resultType指定输出结果的类型和mapper.java的方法返回值类型一致。
74 |
75 |
76 | SqlMapConfig.xml配置文件:可以配置properties属性、别名、mapper加载。
77 |
78 |
79 | ## 输入映射和输出映射
80 |
81 | - 输入映射:
82 | - parameterType:指定输入参数类型可以简单类型、pojo、hashmap。
83 | - 对于综合查询,建议parameterType使用包装的pojo,有利于系统扩展。
84 |
85 | - 输出映射:
86 | - resultType:查询到的列名和resultType指定的pojo的属性名一致,才能映射成功。
87 | - reusltMap:可以通过resultMap 完成一些高级映射。如果查询到的列名和映射的pojo的属性名不一致时,通过resultMap设置列名和属性名之间的对应关系(映射关系)。可以完成映射。
88 | - 高级映射:
89 | 将关联查询的列映射到一个pojo属性中。(一对一)
90 | 将关联查询的列映射到一个List中。(一对多)
91 |
92 |
93 | ## 动态sql
94 |
95 | - 动态sql:(重点)
96 | - if判断(掌握)
97 | - where
98 | - foreach
99 | - sql片段(掌握)
100 |
--------------------------------------------------------------------------------
/course/Mybatis.md:
--------------------------------------------------------------------------------
1 | ## 黑马程序员 Mybatis 学习记录
2 |
3 | 时长:10小时23分钟
4 |
5 | | 章节 | 记录 |
6 | | ------------------------------------------------- | ---- |
7 | | **day-01** | |
8 | | 01 mybatis第一天课程安排 | |
9 | | 02 原生态jdbc编程中的问题总结 | |
10 | | 03 mybatis框架原理 | |
11 | | 04 mybatis入门程序-工程结构 | |
12 | | 05 mybatis入门程序-根据id查询用户-映射文件 | |
13 | | 06 mybatis入门程序-根据id查询用户-程序代码 | |
14 | | 07 mybatis入门程序-根据id查询用户-程序调试 | |
15 | | 08 mybatis入门程序-根据名称查询用户 | |
16 | | 09 mybatis入门程序-查询用户小结 | |
17 | | 10 mybatis入门程序-添加用户 | |
18 | | 11 mybatis入门程序-添加用户-主键返回 | |
19 | | 12 mybatis入门程序-删除用户和更新用户 | |
20 | | 13 mybatis入门程序-小结 | |
21 | | 14 mybatis和hibernate的本质区别和应用场景 | |
22 | | 15 mybatis开发dao方法-sqlSession应用场合 | |
23 | | 16 mybatis开发dao方法-原始dao开发方法 | |
24 | | 17 mybatis开发dao方法-原始dao开发方法-问题总结 | |
25 | | 18 mybatis开发dao方法-mapper代理开发方法-开发规范 | |
26 | | 19 mybatis开发dao方法-mapper代理开发方法-实现 | |
27 | | 20 SqlMapConfig-properties定义 | |
28 | | 21 SqlMapConfig-settings | |
29 | | 22 SqlMapConfig-别名定义 | |
30 | | 23 SqlMapConfig-类型处理器 | |
31 | | 24 SqlMapConfig-mapper加载 | |
32 | | 25 输入映射-pojo包装类型-定义pojo包装类型 | |
33 | | 26 输入映射-pojo包装类型-实现 | |
34 | | 27 输出映射-resultType | |
35 | | 28 输出映射-resultMap | |
36 | | 29 动态sql-if判断 | |
37 | | 30 动态sql-sql片段 | |
38 | | 31 动态sql-foreach | |
39 | | **day-02** | |
40 | | 01 第一天课程复习及第二天课程安排 | |
41 | | 02 订单商品数据模型-分析思路 | |
42 | | 03 订单商品数据模型-分析 | |
43 | | 04 高级映射-一对一查询-使用resultType | |
44 | | 05 高级映射-一对一查询-使用resultMap | |
45 | | 06 高级映射-一对多查询 | |
46 | | 07 高级映射-多对多查询 | |
47 | | 08 高级映射-resultMap总结 | |
48 | | 09 高级映射-延迟加载 | |
49 | | 10 查询缓存-一级缓存原理 | |
50 | | 11 查询缓存-一级缓存测试 | |
51 | | 12 查询缓存-一级缓存实际应用 | |
52 | | 13 查询缓存-二级缓存-二级缓存测试 | |
53 | | 14 查询缓存-二级缓存-整合ehcache | |
54 | | 15 查询缓存-二级缓存-应用场景和局限性 | |
55 | | 16 mybatis和spring整合-sqlSessionFactory配置 | |
56 | | 17 mybatis和spring整合-原始dao开发 | |
57 | | 18 mybatis和spring整合-mapper代理开发 | |
58 | | 19 mybatis逆向工程自动生成代码 | |
--------------------------------------------------------------------------------
/springmvc/17 上传图片.md:
--------------------------------------------------------------------------------
1 | # springmvc学习笔记(17)-上传图片
2 |
3 | 标签: springmvc
4 |
5 | ---
6 |
7 | **Contents**
8 |
9 | - [springmvc中对多部件类型解析](#springmvc中对多部件类型解析)
10 | - [加入上传图片的jar](#加入上传图片的jar)
11 | - [创建图片虚拟目录存储图片](#创建图片虚拟目录存储图片)
12 | - [上传图片代码](#上传图片代码)
13 |
14 |
15 |
16 | ---
17 |
18 |
19 | 本文展示如何在springmvc中上传图片
20 |
21 |
22 | ## springmvc中对多部件类型解析
23 |
24 | 在修改商品页面,添加上传商品图片功能。
25 |
26 | 在页面form中提交`enctype="multipart/form-data"`的数据时,需要springmvc对multipart类型的数据进行解析。
27 |
28 | 在springmvc.xml中配置multipart类型解析器。
29 |
30 | ```xml
31 |
32 |
34 |
35 |
36 | 5242880
37 |
38 |
39 | ```
40 |
41 | ## 加入上传图片的jar
42 |
43 | 添加依赖
44 |
45 | ```xml
46 |
47 |
48 | commons-fileupload
49 | commons-fileupload
50 | 1.3.1
51 |
52 | ```
53 |
54 | 依赖树
55 |
56 | ```
57 | [INFO] \- commons-fileupload:commons-fileupload:jar:1.3.1:compile
58 | [INFO] \- commons-io:commons-io:jar:2.2:compile
59 | ```
60 |
61 | 可以看到,其实还间接依赖了`commons-io:commons-io:jar`
62 |
63 |
64 | ## 创建图片虚拟目录存储图片
65 |
66 | 参考我之前的博文
67 |
68 | > [在intellij IDEA中为web应用创建图片虚拟目录(详细截图)](http://blog.csdn.net/h3243212/article/details/50819218)
69 |
70 |
71 | 也可以直接修改tomcat的配置,在conf/server.xml文件,添加虚拟目录.
72 |
73 | 注意:在图片虚拟目录中,一定将图片目录分级创建(提高i/o性能),一般我们采用按日期(年、月、日)进行分级创建。
74 |
75 | ## 上传图片代码
76 |
77 | - 页面
78 |
79 | ```jsp
80 |
81 | | 商品图片 |
82 |
83 |
84 |
85 |
86 |
87 |
88 | |
89 |
90 | ```
91 |
92 | - controller方法
93 |
94 | 修改:商品修改controller方法:
95 |
96 | ```java
97 | @RequestMapping("/editItemsSubmit")
98 | public String editItemsSubmit(
99 | Model model,
100 | HttpServletRequest request,
101 | Integer id,
102 | @ModelAttribute("items")
103 | @Validated(value = ValidGroup1.class)ItemsCustom itemsCustom,
104 | BindingResult bindingResult,
105 | MultipartFile items_pic
106 | )throws Exception {
107 | ```
108 |
109 | ```java
110 | //原始名称
111 | String originalFilename = items_pic.getOriginalFilename();
112 | //上传图片
113 | if(items_pic!=null && originalFilename!=null && originalFilename.length()>0){
114 |
115 | //存储图片的物理路径
116 | String pic_path = "D:\\tmp\\";
117 |
118 |
119 | //新的图片名称
120 | String newFileName = UUID.randomUUID() + originalFilename.substring(originalFilename.lastIndexOf("."));
121 | //新图片
122 | File newFile = new File(pic_path+newFileName);
123 |
124 | //将内存中的数据写入磁盘
125 | items_pic.transferTo(newFile);
126 |
127 | //将新图片名称写到itemsCustom中
128 | itemsCustom.setPic(newFileName);
129 |
130 | }
131 | ```
132 |
133 |
134 |
--------------------------------------------------------------------------------
/mybatis/06 输入映射.md:
--------------------------------------------------------------------------------
1 | # 06 输入映射
2 |
3 | 标签: mybatis
4 |
5 | ---
6 |
7 | **Contents**
8 |
9 | - [传递pojo的包装对象](#传递pojo的包装对象)
10 |
11 |
12 |
13 | ---
14 |
15 | 本文主要讲解mybatis的输入映射。
16 |
17 |
18 | 通过parameterType指定输入参数的类型,类型可以是
19 |
20 | - 简单类型
21 | - hashmap
22 | - pojo的包装类型
23 |
24 | ## 传递pojo的包装对象
25 |
26 | 需求:完成用户信息的综合查询,需要传入查询条件很复杂(可能包括用户信息、其它信息,比如商品、订单的)
27 |
28 |
29 |
30 | 针对上边需求,建议使用自定义的包装类型的pojo。
31 |
32 | 在包装类型的pojo中将复杂的查询条件包装进去。
33 |
34 | ```java
35 | package com.iot.mybatis.po;
36 |
37 | /**
38 | * Created by Brian on 2016/2/24.
39 | */
40 | public class UserQueryVo {
41 |
42 | //在这里包装所需要的查询条件
43 |
44 | //用户查询条件
45 | private UserCustom userCustom;
46 |
47 | public UserCustom getUserCustom() {
48 | return userCustom;
49 | }
50 |
51 | public void setUserCustom(UserCustom userCustom) {
52 | this.userCustom = userCustom;
53 | }
54 |
55 | //可以包装其它的查询条件,订单、商品
56 | //....
57 |
58 | }
59 | ```
60 |
61 | 其中,UserCustom类继承User
62 |
63 | ```java
64 | public class UserCustom extends User{
65 | }
66 | ```
67 |
68 | - mapper.xml
69 |
70 | 在UserMapper.xml中定义用户信息综合查询(查询条件复杂,通过高级查询进行复杂关联查询)。
71 |
72 | ```xml
73 |
77 |
81 | ```
82 |
83 | 注意不要将`#{userCustom.sex}`中的`userCustom`写成`UserCustom`,前者指属性名(由于使用IDE提示自动补全,所以只是把类型名首字母小写了),后者指类型名,这里是`UserQueryVo`类中的`userCustom`属性,是**属性名**。写错会报如下异常:
84 |
85 | ```
86 | org.apache.ibatis.exceptions.PersistenceException:
87 | ### Error querying database. Cause: org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'UserCustom' in 'class com.iot.mybatis.po.UserQueryVo'
88 | ### Cause: org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'UserCustom' in 'class com.iot.mybatis.po.UserQueryVo'
89 | ```
90 |
91 | - mapper.java
92 |
93 | ```java
94 | //用户信息综合查询
95 | public List findUserList(UserQueryVo userQueryVo) throws Exception;
96 | ```
97 |
98 | - 测试代码
99 |
100 | ```java
101 | //用户信息的综合 查询
102 | @Test
103 | public void testFindUserList() throws Exception {
104 | SqlSession sqlSession = sqlSessionFactory.openSession();
105 | //创建UserMapper对象,mybatis自动生成mapper代理对象
106 | UserMapper userMapper sqlSession.getMapper(UserMapper.class);
107 | //创建包装对象,设置查询条件
108 | UserQueryVo userQueryVo = new UserQueryVo();
109 | UserCustom userCustom = new UserCustom();
110 | //由于这里使用动态sql,如果不设置某个值,条件不会拼接在sql中
111 | userCustom.setSex("1");
112 | userCustom.setUsername("张三");
113 | userQueryVo.setUserCustom(userCustom);
114 | //调用userMapper的方法
115 | List list = userMapper.findUserList(userQueryVo);
116 | System.out.println(list);
117 | }
118 | ```
119 |
--------------------------------------------------------------------------------
/course/SpringMVC.md:
--------------------------------------------------------------------------------
1 | ## 黑马程序员 SpringMVC 学习记录
2 |
3 | 时长:10小时04分钟
4 |
5 |
6 | | 章节 | 记录 |
7 | | ----------------------------------------------------------- | ---- |
8 | | **day01** | |
9 | | 01 spring第一天课程安排 | |
10 | | 02 springmvc架构-mvc设计模式在bs系统下的应用 | |
11 | | 03 springmvc架构-springmvc架构原理分析 | |
12 | | 04 springmvc入门程序-环境搭建 | |
13 | | 05 springmvc入门程序-前端控制器配置 | |
14 | | 06 springmvc入门程序-Handler编写调试 | |
15 | | 07 springmvc入门程序-非注解映射器和适配器 | |
16 | | 08 springmvc入门程序-注解映射器和适配器配置 | |
17 | | 09 springmvc入门程序-注解映射器和适配器 | |
18 | | 10 springmvc入门程序-前端控制器源代码分析 | |
19 | | 11 springmvc入门程序-视图解析器配置前缀和后缀 | |
20 | | 12 springmvc和mybaits整合-整合思路 | |
21 | | 13 springmvc和mybaits整合-工程结构 | |
22 | | 14 springmvc和mybaits整合-商品查询mapper | |
23 | | 15 springmvc和mybaits整合-商品查询service | |
24 | | 16 springmvc和mybaits整合-商品查询controller | |
25 | | 17 springmvc和mybaits整合-商品查询调试 | |
26 | | 18 springmvc注解开发-商品修改功能分析 | |
27 | | 19 springmvc注解开发-商品修改功能开发service | |
28 | | 20 springmvc注解开发-商品修改功能开发controller | |
29 | | 21 springmvc注解开发-RequestMapping注解 | |
30 | | 22 springmvc注解开发-controller方法返回值 | |
31 | | 23 springmvc注解开发-springmvc参数绑定过程 | |
32 | | 24 springmvc注解开发-springmvc参数绑定-简单类型绑定 | |
33 | | 25 springmvc注解开发-springmvc参数绑定-pojo绑定 | |
34 | | 26 springmvc注解开发-springmvc参数绑定-自定义参数绑定 | |
35 | | 27 springmvc和struts2的区别 | |
36 | | | |
37 | | **day02** | |
38 | | 01 springmvc第一天课程复习 | |
39 | | 02 springmvc注解开发-springmvc参数绑定-包装类型pojo参数绑定 | |
40 | | 03 springmvc注解开发-springmvc参数绑定-数组 | |
41 | | 04 springmvc注解开发-springmvc参数绑定-list | |
42 | | 05 springmvc注解开发-validation校验-商品修改校验 | |
43 | | 06 springmvc注解开发-validation校验-分组校验 | |
44 | | 07 springmvc注解开发-数据回显 | |
45 | | 08 springmvc异常处理-全局异常处理器开发 | |
46 | | 09 springmvc异常处理-抛出异常 | |
47 | | 10 springmvc上传图片 | |
48 | | 11 springmvc实现json交互-requestBody和responseBody | |
49 | | 12 springmvc实现json交互-准备环境 | |
50 | | 13 springmvc实现json交互-json交互测试 | |
51 | | 14 springmvc对RESTful支持 | |
52 | | 15 springmvc拦截器-定义和配置 | |
53 | | 16 springmvc拦截器-多拦截器测试 | |
54 | | 17 springmvc拦截器-实现登陆认证 | |
55 |
--------------------------------------------------------------------------------
/springmvc/19 RESTful支持.md:
--------------------------------------------------------------------------------
1 | # springmvc学习笔记(19)-RESTful支持
2 |
3 | 标签: springmvc
4 |
5 | ---
6 |
7 | **Contents**
8 |
9 | - [概念](#概念)
10 | - [REST的例子](#rest的例子)
11 | - [controller](#controller)
12 | - [REST方法的前端控制器配置](#rest方法的前端控制器配置)
13 | - [对静态资源的解析](#对静态资源的解析)
14 |
15 |
16 |
17 | ---
18 |
19 |
20 | 本文介绍RESTful的概念,并通过一个小例子展示如何编写RESTful风格的controller和配置前端控制器,最后展示静态资源的解析
21 |
22 |
23 | ## 概念
24 |
25 | 首先附上两篇博客链接
26 |
27 | >* [理解RESTful架构 - 阮一峰的网络日志](http://zqpythonic.qiniucdn.com/data/20110912210739/index.html)
28 | >* [RESTful API 设计指南- 阮一峰的网络日志](http://www.ruanyifeng.com/blog/2014/05/restful_api.html)
29 |
30 |
31 | RESTful架构,就是目前最流行的一种互联网软件架构。它结构清晰、符合标准、易于理解、扩展方便,所以正得到越来越多网站的采用。
32 |
33 | RESTful(即Representational State Transfer的缩写)其实是一个开发理念,是对http的很好的诠释。
34 |
35 | 1.对url进行规范,写RESTful格式的url
36 |
37 | - 非REST的url:`http://...../queryItems.action?id=001&type=T01`
38 | - REST的url风格:`http://..../items/001`
39 |
40 | 特点:url简洁,将参数通过url传到服务端
41 |
42 | 2.http的方法规范
43 |
44 | 不管是删除、添加、更新,等等。使用url是一致的,如果进行删除,需要设置http的方法为delete,其他同理。
45 |
46 | 后台controller方法:判断http方法,如果是delete执行删除,如果是post执行添加。
47 |
48 | 3.对http的contentType规范
49 |
50 | 请求时指定contentType,要json数据,设置成json格式的type。
51 |
52 |
53 | ## REST的例子
54 |
55 | 查询商品信息,返回json数据。
56 |
57 | ### controller
58 |
59 | 定义方法,进行url映射使用REST风格的url,将查询商品信息的id传入controller .
60 |
61 | 输出json使用`@ResponseBody`将java对象输出json。
62 |
63 | ```java
64 | //查询商品信息,输出json
65 | //itemsView/{id}里边的{id}表示占位符,通过@PathVariable获取占位符中的参数,
66 | //@PathVariable中名称要和占位符一致,形参名无需和其一致
67 | //如果占位符中的名称和形参名一致,在@PathVariable可以不指定名称
68 | @RequestMapping("/itemsView/{id}")
69 | public @ResponseBody ItemsCustom itemsView(@PathVariable("id") Integer items_id)throws Exception{
70 |
71 | //调用service查询商品信息
72 | ItemsCustom itemsCustom = itemsService.findItemsById(items_id);
73 |
74 | return itemsCustom;
75 |
76 | }
77 | ```
78 |
79 | `@RequestMapping(value="/ itemsView/{id}")`:`{×××}`占位符,请求的URL可以是`/viewItems/1`或`/viewItems/2`,通过在方法中使用`@PathVariable`获取{×××}中的×××变量。`@PathVariable`用于将请求URL中的模板变量映射到功能处理方法的参数上。
80 |
81 | 如果`@RequestMapping`中表示为`/itemsView/{id}`,id和形参名称一致,`@PathVariable`不用指定名称。
82 |
83 |
84 | ### REST方法的前端控制器配置
85 |
86 | ```xml
87 |
88 |
89 | springmvc_rest
90 | org.springframework.web.servlet.DispatcherServlet
91 |
92 |
93 | contextConfigLocation
94 | classpath:spring/springmvc.xml
95 |
96 |
97 |
98 |
99 | springmvc_rest
100 | /
101 |
102 | ```
103 |
104 |
105 |
106 |
107 |
108 | ## 对静态资源的解析
109 |
110 | 配置前端控制器的url-parttern中指定`/`,对静态资源的解析会出现问题,报404错误。
111 |
112 |
113 | 在springmvc.xml中添加静态资源解析方法。
114 |
115 | ```xml
116 |
119 |
120 | ```
121 |
122 | 这时访问`http://localhost:8080/ssm1/js/jquery-1.4.4.min.js`,可以在浏览器中看到js的内容
123 |
--------------------------------------------------------------------------------
/springmvc/02 非注解的处理器映射器和适配器.md:
--------------------------------------------------------------------------------
1 | # 02 非注解的处理器映射器和适配器
2 |
3 | 标签: springmvc
4 |
5 | ---
6 |
7 | **Contents**
8 |
9 | - [非注解的处理器映射器](#非注解的处理器映射器)
10 | - [非注解的处理器适配器](#非注解的处理器适配器)
11 |
12 |
13 |
14 | ---
15 |
16 | 本文主要介绍非注解的处理器映射器和适配器配置
17 |
18 |
19 | ## 非注解的处理器映射器
20 |
21 | ```xml
22 |
23 |
24 |
25 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 | itemsController
36 | itemsController
37 |
38 |
39 |
40 | ```
41 |
42 | 多个映射器可并存,前端控制器判断url能让哪些映射器处理就让正确的映射器处理
43 |
44 |
45 | ## 非注解的处理器适配器
46 |
47 | ```
48 |
51 |
52 | ```
53 |
54 | 要求编写的Handler实现`Controller`接口
55 |
56 | ``
57 |
58 | 要求编写的Handler实现`HttpRequestHandler`接口
59 |
60 | ```java
61 | package com.iot.ssm.controller;
62 |
63 | import com.iot.ssm.po.Items;
64 | import org.springframework.web.HttpRequestHandler;
65 |
66 | import javax.servlet.ServletException;
67 | import javax.servlet.http.HttpServletRequest;
68 | import javax.servlet.http.HttpServletResponse;
69 | import java.io.IOException;
70 | import java.util.ArrayList;
71 | import java.util.List;
72 |
73 | /**
74 | * Created by brian on 2016/2/19.
75 | */
76 | public class ItemsController2 implements HttpRequestHandler{
77 | public void handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException {
78 | //调用service查找数据库,查询商品列表,这里使用静态数据模拟
79 | List itemsList = new ArrayList();
80 |
81 | //向list中填充静态数据
82 | Items items_1 = new Items();
83 | items_1.setName("联想笔记本");
84 | items_1.setPrice(6000f);
85 | items_1.setDetail("ThinkPad T430 联想笔记本电脑!");
86 |
87 | Items items_2 = new Items();
88 | items_2.setName("苹果手机");
89 | items_2.setPrice(5000f);
90 | items_2.setDetail("iphone6苹果手机!");
91 |
92 | itemsList.add(items_1);
93 | itemsList.add(items_2);
94 |
95 | //设置模型数据
96 | httpServletRequest.setAttribute("itemsList",itemsList);
97 |
98 | //设置转发的视图
99 | httpServletRequest.getRequestDispatcher("/WEB-INF/jsp/items/itemsList.jsp").forward(httpServletRequest,httpServletResponse);
100 |
101 | }
102 | }
103 | ```
104 |
105 |
106 | `HttpRequestHandler`适配器的`handleRequest`方法返回为`void`,没有返回`ModelAndView`,可通过response修改响应内容,比如返回json数据:
107 |
108 | ```java
109 | response.setCharacterEncoding("utf-8");
110 | response.setContentType("application/json;charset=utf-8");
111 | response.getWriter().write("json串");
112 | ```
113 |
114 |
--------------------------------------------------------------------------------
/mybatis/11 一对多查询.md:
--------------------------------------------------------------------------------
1 | # mybatis学习笔记(11)-一对多查询
2 |
3 | 标签: mybatis
4 |
5 | ---
6 |
7 | **Contents**
8 |
9 | - [示例](#示例)
10 | - [小结](#小结)
11 |
12 |
13 |
14 | ---
15 |
16 |
17 | 本文实现一对多查询,查询订单及订单明细的信息
18 |
19 | ## 示例
20 |
21 | - sql
22 |
23 | 确定主查询表:订单表
24 | 确定关联查询表:订单明细表
25 | 在一对一查询基础上添加订单明细表关联即可。
26 |
27 | ```sql
28 | SELECT
29 | orders.*,
30 | user.username,
31 | user.sex,
32 | user.address,
33 | orderdetail.id orderdetail_id,
34 | orderdetail.items_id,
35 | orderdetail.items_num,
36 | orderdetail.orders_id
37 | FROM
38 | orders,
39 | user,
40 | orderdetail
41 | WHERE orders.user_id = user.id AND orderdetail.orders_id=orders.id
42 | ```
43 |
44 | **注意上面的`orderdetail.id (AS) orderdetail_id`,这里需要取别名,否则由于orders表也有id字段,在后面映射时会冲突**
45 |
46 | - 映射思路
47 |
48 | 使用resultType将上边的查询结果映射到pojo中,订单信息的就是重复。
49 |
50 | 对orders映射不能出现重复记录。
51 |
52 | 在orders.java类中添加`List orderDetails`属性。
53 | 最终会将订单信息映射到orders中,订单所对应的订单明细映射到orders中的orderDetails属性中。
54 |
55 | 映射成的orders记录数为两条(orders信息不重复),每个orders中的orderDetails属性存储了该订单所对应的订单明细。
56 |
57 |
58 | - 在orders中添加list订单明细属性
59 |
60 | ```java
61 | //订单明细
62 | private List orderdetails;
63 | ```
64 |
65 | - mapper.xml
66 |
67 | ```xml
68 |
69 |
85 | ```
86 |
87 | - resultMap定义
88 |
89 | ```xml
90 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
105 |
106 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 | ```
117 |
118 |
119 | - mapper.java
120 |
121 | ```java
122 | //查询订单(关联用户)及订单明细
123 | public List findOrdersAndOrderDetailResultMap()throws Exception;
124 | ```
125 |
126 |
127 | ## 小结
128 |
129 | mybatis使用resultMap的collection对关联查询的多条记录映射到一个list集合属性中。
130 |
131 | 使用resultType实现:将订单明细映射到orders中的orderdetails中,需要自己处理,使用双重循环遍历,去掉重复记录,将订单明细放在orderdetails中。
132 |
133 |
134 | 另外,下面这篇文章对一对多的resultMap机制解释的很清楚:
135 |
136 | > [MyBatis:一对多表关系详解(从案例中解析)](http://blog.csdn.net/xzm_rainbow/article/details/15336933)
137 |
138 |
--------------------------------------------------------------------------------
/springmvc/03 注解的处理器映射器和适配器.md:
--------------------------------------------------------------------------------
1 | # 03 注解的处理器映射器和适配器
2 |
3 | 标签: springmvc
4 |
5 | ---
6 |
7 | **Contents**
8 |
9 | - [默认加载](#默认加载)
10 | - [注解的处理器映射器和适配器](#注解的处理器映射器和适配器)
11 | - [开发注解Handler](#开发注解handler)
12 | - [在spring容器中加载Handler](#在spring容器中加载handler)
13 | - [参考资料](#参考资料)
14 |
15 |
16 |
17 | ---
18 |
19 |
20 | 本文主要介绍注解的处理器映射器和适配器相关配置
21 |
22 |
23 | ## 默认加载
24 |
25 | 前端控制器从`\org\springframework\web\servlet\DispatcherServlet.properties`件中加载处理器映射器、适配器、视图解析器等组件,如果不在springmvc.xml中配置,则使用默认加载的
26 |
27 | 注解的处理器映射器和适配器
28 |
29 | - 在spring3.1之前使用`org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping`注解映射器。
30 | - 在spring3.1之后使用`org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping`注解映射器。
31 | - 在spring3.1之前使用`org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter`注解适配器。
32 | - 在spring3.1之后使用`org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter`注解适配器
33 |
34 |
35 | ## 注解的处理器映射器和适配器
36 |
37 | ```xml
38 |
39 |
40 |
41 |
42 |
43 |
44 | ```
45 |
46 | 或者
47 |
48 | ```xml
49 |
54 |
55 |
56 | ```
57 |
58 | ## 开发注解Handler
59 |
60 | 使用注解的映射器和注解的适配器。(使用注解的映射器和注解的适配器必须配对使用)
61 |
62 | ```java
63 | //使用@Controller来标识它是一个控制器
64 | @Controller
65 | public class ItemsController3 {
66 |
67 | //商品查询列表
68 | @RequestMapping("/queryItems")
69 | //实现 对queryItems方法和url进行映射,一个方法对应一个url
70 | //一般建议将url和方法写成一样
71 | public ModelAndView queryItems() throws Exception{
72 | //调用service查找数据库,查询商品列表,这里使用静态数据模拟
73 | List itemsList = new ArrayList();
74 |
75 | //向list中填充静态数据
76 | Items items_1 = new Items();
77 | items_1.setName("联想笔记本");
78 | items_1.setPrice(6000f);
79 | items_1.setDetail("ThinkPad T430 c3 联想笔记本电脑!");
80 |
81 | Items items_2 = new Items();
82 | items_2.setName("苹果手机");
83 | items_2.setPrice(5000f);
84 | items_2.setDetail("iphone6苹果手机!");
85 |
86 | itemsList.add(items_1);
87 | itemsList.add(items_2);
88 |
89 | //返回ModelAndView
90 | ModelAndView modelAndView = new ModelAndView();
91 | //相当于request的setAttribute方法,在jsp页面中通过itemsList取数据
92 | modelAndView.addObject("itemsList",itemsList);
93 |
94 | //指定视图
95 | modelAndView.setViewName("/WEB-INF/jsp/items/itemsList.jsp");
96 | return modelAndView;
97 | }
98 | }
99 | ```
100 |
101 | ## 在spring容器中加载Handler
102 |
103 | ```xml
104 |
107 |
108 |
111 |
112 | ```
113 |
114 |
115 |
116 | ## 参考资料
117 |
118 | >* [SpringMVC框架】注解的处理器映射器和适配器配置](http://blog.csdn.net/acmman/article/details/46980427)
--------------------------------------------------------------------------------
/springmvc/08 springmvc整合mybatis之service.md:
--------------------------------------------------------------------------------
1 | # springmvc学习笔记(8)-springmvc整合mybatis之service
2 |
3 | 标签: springmvc mybatis
4 |
5 | ---
6 |
7 | **Contents**
8 |
9 | - [定义service接口](#定义service接口)
10 | - [在spring容器配置service](#在spring容器配置service)
11 | - [事务控制](#事务控制)
12 |
13 |
14 |
15 | ---
16 |
17 |
18 | 本文记录如何整合service,包括定义spring接口,在spring容器配置service以及事务控制。让spring管理service接口。
19 |
20 |
21 | ## 定义service接口
22 |
23 | ```java
24 | public interface ItemsService {
25 | //商品查询列表
26 | List findItemsList(ItemsQueryVo itemsQueryVo) throws Exception;
27 |
28 | }
29 | ```
30 |
31 | ```java
32 | public class ItemsServiceImpl implements ItemsService {
33 |
34 | @Autowired
35 | private ItemsMapperCustom itemsMapperCustom;
36 |
37 | public List findItemsList(ItemsQueryVo itemsQueryVo) throws Exception {
38 | return itemsMapperCustom.findItemsList(itemsQueryVo);
39 | }
40 | }
41 | ```
42 |
43 | ## 在spring容器配置service
44 |
45 |
46 | 在`resources/spring`下创建applicationContext-service.xml,文件中配置service。
47 |
48 | ```xml
49 |
52 |
53 |
54 |
55 |
56 |
57 | ```
58 |
59 | ## 事务控制
60 |
61 | 在`resources/spring`下创建applicationContext-transaction.xml,在applicationContext-transaction.xml中使用spring声明式事务控制方法。
62 |
63 | ```xml
64 |
65 |
72 |
73 |
74 |
77 |
78 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 | ```
103 |
--------------------------------------------------------------------------------
/mybatis/01 对原生JDBC程序中的问题总结.md:
--------------------------------------------------------------------------------
1 | # 01 对原生jdbc程序中的问题总结
2 |
3 | 标签:mybatis
4 |
5 | ---
6 |
7 | **Contents**
8 |
9 | - [jdbc编程步骤](#jdbc编程步骤)
10 | - [问题总结](#问题总结)
11 | - [参考代码](#参考代码)
12 |
13 |
14 |
15 | ---
16 |
17 | 本文总结jdbc编程的一般步骤,总结这样编程存在的问题,并附上典型地jdbc示例demo
18 |
19 |
20 | ## jdbc编程步骤
21 |
22 | 1. 加载数据库驱动
23 | 2. 创建并获取数据库链接
24 | 3. 创建jdbc statement对象
25 | 4. 设置sql语句
26 | 5. 设置sql语句中的参数(使用preparedStatement)
27 | 6. 通过statement执行sql并获取结果
28 | 7. 对sql执行结果进行解析处理
29 | 8. 释放资源(resultSet、preparedstatement、connection)
30 |
31 |
32 | ## 问题总结
33 |
34 | 1. 数据库连接,使用时就创建,不使用立即释放,对数据库进行频繁连接开启和关闭,造成数据库资源浪费,影响数据库性能。
35 |
36 | **设想:**使用数据库连接池管理数据库连接。
37 |
38 | 2. 将sql语句硬编码到java代码中,如果sql语句修改,需要重新编译java代码,不利于系统维护。
39 |
40 | **设想:**将sql语句配置在xml配置文件中,即使sql变化,不需要对java代码进行重新编译。
41 |
42 | 3. 向preparedStatement中设置参数,对占位符号位置和设置参数值,硬编码在java代码中,不利于系统维护。
43 |
44 | **设想:**将sql语句及占位符号和参数全部配置在xml中。
45 |
46 | 4. 从resutSet中遍历结果集数据时,存在硬编码,将获取表的字段进行硬编码,不利于系统维护。
47 |
48 | **设想:**将查询的结果集,自动映射成java对象。
49 |
50 |
51 |
52 |
53 |
54 | ## 参考代码
55 |
56 | ```java
57 | package com.iot.mybatis.jdbc;
58 |
59 | //import java.sql.*;
60 | import java.sql.Connection;
61 | import java.sql.DriverManager;
62 | import java.sql.PreparedStatement;
63 | import java.sql.ResultSet;
64 | import java.sql.SQLException;
65 |
66 | /**
67 | * Created by Administrator on 2016/2/21.
68 | */
69 | public class JdbcTest {
70 | public static void main(String[] args) {
71 | //数据库连接
72 | Connection connection = null;
73 | //预编译的Statement,使用预编译的Statement提高数据库性能
74 | PreparedStatement preparedStatement = null;
75 | //结果集
76 | ResultSet resultSet = null;
77 |
78 | try {
79 | //加载数据库驱动
80 | Class.forName("com.mysql.jdbc.Driver");
81 |
82 | //通过驱动管理类获取数据库链接
83 | connection = DriverManager.getConnection("jdbc:mysql://120.25.162.238:3306/mybatis001?characterEncoding=utf-8", "root", "123");
84 | //定义sql语句 ?表示占位符
85 | String sql = "select * from user where username = ?";
86 | //获取预处理statement
87 | preparedStatement = connection.prepareStatement(sql);
88 | //设置参数,第一个参数为sql语句中参数的序号(从1开始),第二个参数为设置的参数值
89 | preparedStatement.setString(1, "王五");
90 | //向数据库发出sql执行查询,查询出结果集
91 | resultSet = preparedStatement.executeQuery();
92 | //遍历查询结果集
93 | while(resultSet.next()){
94 | System.out.println(resultSet.getString("id")+" "+resultSet.getString("username"));
95 | }
96 | } catch (Exception e) {
97 | e.printStackTrace();
98 | }finally{
99 | //释放资源
100 | if(resultSet!=null){
101 | try {
102 | resultSet.close();
103 | } catch (SQLException e) {
104 | // TODO Auto-generated catch block
105 | e.printStackTrace();
106 | }
107 | }
108 | if(preparedStatement!=null){
109 | try {
110 | preparedStatement.close();
111 | } catch (SQLException e) {
112 | // TODO Auto-generated catch block
113 | e.printStackTrace();
114 | }
115 | }
116 | if(connection!=null){
117 | try {
118 | connection.close();
119 | } catch (SQLException e) {
120 | // TODO Auto-generated catch block
121 | e.printStackTrace();
122 | }
123 | }
124 |
125 | }
126 |
127 | }
128 |
129 | }
130 |
131 | ```
132 |
--------------------------------------------------------------------------------
/springmvc/13 springmvc注解开发之集合类型参数绑定.md:
--------------------------------------------------------------------------------
1 | # springmvc学习笔记(13)-springmvc注解开发之集合类型参数绑定
2 |
3 | 标签: springmvc
4 |
5 | ---
6 |
7 | **Contents**
8 |
9 | - [数组绑定](#数组绑定)
10 | - [需求](#需求)
11 | - [表现层实现](#表现层实现)
12 | - [list绑定](#list绑定)
13 | - [需求](#需求)
14 | - [表现层实现](#表现层实现)
15 | - [map绑定](#map绑定)
16 |
17 |
18 |
19 | ---
20 |
21 |
22 | 本文主要介绍注解开发的集合类型参数绑定,包括数组绑定,list绑定以及map绑定
23 |
24 | ## 数组绑定
25 |
26 | ### 需求
27 |
28 | 商品批量删除,用户在页面选择多个商品,批量删除。
29 |
30 | ### 表现层实现
31 |
32 | 关键:将页面选择(多选)的商品id,传到controller方法的形参,方法形参使用数组接收页面请求的多个商品id。
33 |
34 | - controller方法定义:
35 |
36 | ```java
37 | // 批量删除 商品信息
38 | @RequestMapping("/deleteItems")
39 | public String deleteItems(Integer[] items_id) throws Exception
40 | ```
41 |
42 | - 页面定义:
43 |
44 | ```jsp
45 |
46 |
47 | |
48 | ${item.name } |
49 | ${item.price } |
50 | |
51 | ${item.detail } |
52 |
53 | 修改 |
54 |
55 |
56 |
57 | ```
58 |
59 |
60 |
61 | ## list绑定
62 |
63 | ### 需求
64 |
65 | 通常在需要批量提交数据时,将提交的数据绑定到`list`中,比如:成绩录入(录入多门课成绩,批量提交),
66 |
67 | 本例子需求:批量商品修改,在页面输入多个商品信息,将多个商品信息提交到controller方法中。
68 |
69 | ### 表现层实现
70 |
71 | - controller方法定义:
72 | - 1、进入批量商品修改页面(页面样式参考商品列表实现)
73 | - 2、批量修改商品提交
74 |
75 | 使用List接收页面提交的批量数据,通过包装pojo接收,在包装pojo中定义`list`属性
76 |
77 | ```java
78 | public class ItemsQueryVo {
79 |
80 | //商品信息
81 | private Items items;
82 |
83 | //为了系统 可扩展性,对原始生成的po进行扩展
84 | private ItemsCustom itemsCustom;
85 |
86 | //批量商品信息
87 | private List itemsList;
88 | ```
89 |
90 |
91 | ```java
92 | // 批量修改商品提交
93 | // 通过ItemsQueryVo接收批量提交的商品信息,将商品信息存储到itemsQueryVo中itemsList属性中。
94 | @RequestMapping("/editItemsAllSubmit")
95 | public String editItemsAllSubmit(ItemsQueryVo itemsQueryVo) throws Exception {
96 |
97 | return "success";
98 | }
99 | ```
100 |
101 | - 页面定义:
102 |
103 | ```jsp
104 |
105 |
106 |
107 | |
108 | |
109 | "/> |
110 | |
111 |
112 |
113 |
114 | ```
115 |
116 | name的格式:
117 |
118 | **`对应包装pojo中的list类型属性名`[`下标(从0开始)`].`包装pojo中List类型的属性中pojo的属性名`**
119 |
120 | 例子:
121 |
122 | `"name="itemsList[${status.index }].price"`
123 |
124 |
125 | *可以和包装类型的参数绑定归纳对比一下,其实就是在包装类的pojo基础上多了个下标。只不过包装类参数绑定时,要和包装pojo中的pojo类性的属性名一致,而list参数绑定时,要和包装pojo中的list类型的属性名一致。*
126 |
127 |
128 | ## map绑定
129 |
130 | 也通过在包装pojo中定义map类型属性。
131 |
132 | 在包装类中定义Map对象,并添加get/set方法,action使用包装对象接收。
133 |
134 | - 包装类中定义Map对象如下:
135 |
136 | ```java
137 | Public class QueryVo {
138 | private Map itemInfo = new HashMap();
139 | //get/set方法..
140 | }
141 | ```
142 |
143 | - 页面定义如下:
144 |
145 | ```java
146 |
147 | | 学生信息: |
148 |
149 | 姓名:
150 | 年龄:
151 | .. .. ..
152 | |
153 |
154 | ```
155 |
156 |
157 |
158 | - Contrller方法定义如下:
159 |
160 | ```java
161 | public String useraddsubmit(Model model,QueryVo queryVo)throws Exception{
162 | System.out.println(queryVo.getStudentinfo());
163 | }
164 | ```
165 |
166 |
167 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | ## 前言
6 |
7 | 本仓库是 「黑马程序员SpringMVC+MyBatis」学习课程笔记和代码记录
8 |
9 |
10 |
11 | SpringMVC文档:
12 |
13 | - [Spring MVC 4.2.4 RELEASE 中文文档完整翻译稿](https://github.com/linesh-simplicity/translation-spring-mvc-4-documentation)
14 | - [一版有追求的 Spring MVC 中文文档翻译来袭~ - V2EX](https://www.v2ex.com/t/288717)
15 |
16 |
17 |
18 | ## 学习目录
19 |
20 | ### MyBatis
21 | - [01 对原生JDBC程序中的问题总结](mybatis/01%20对原生JDBC程序中的问题总结.md)
22 | - [02 mybatis概述](mybatis/02%20mybatis概述.md)
23 | - [03 入门程序一](mybatis/03%20入门程序一.md)
24 | - [03 入门程序二](mybatis/03%20入门程序二.md)
25 | - [04 开发dao方法](mybatis/04%20开发dao方法.md)
26 | - [05 配置文件](mybatis/05%20配置文件.md)
27 | - [06 输入映射](mybatis/06%20输入映射.md)
28 | - [07 输出映射](mybatis/07%20输出映射.md)
29 | - [08 动态sql](mybatis/08%20动态sql.md)
30 | - [09 订单商品数据模型分析](mybatis/09%20订单商品数据模型分析.md)
31 | - [10 一对一查询](mybatis/10%20一对一查询.md)
32 | - [11 一对多查询](mybatis/11%20一对多查询.md)
33 | - [12 多对多查询](mybatis/12%20多对多查询.md)
34 | - [13 延迟加载](mybatis/13%20延迟加载.md)
35 | - [14 查询缓存之一级缓存](mybatis/14%20查询缓存之一级缓存.md)
36 | - [15 查询缓存之二级缓存](mybatis/15%20查询缓存之二级缓存.md)
37 | - [16 mybatis整合ehcache](mybatis/16%20mybatis整合ehcache.md)
38 | - [17 spring和mybatis整合](mybatis/17%20spring和mybatis整合.md)
39 | - [18 mybatis逆向工程](mybatis/18%20mybatis逆向工程.md)
40 |
41 |
42 |
43 |
44 | #### Spring MVC
45 | - [01 框架原理和入门配置](springmvc/01%20框架原理和入门配置.md)
46 | - [02 非注解的处理器映射器和适配器](springmvc/02%20非注解的处理器映射器和适配器.md)
47 | - [03 注解的处理器映射器和适配器](springmvc/03%20注解的处理器映射器和适配器.md)
48 | - [04 前端控制器](springmvc/04%20前端控制器.md)
49 | - [05 入门程序小结](springmvc/05%20入门程序小结.md)
50 | - [06 springmvc整合mybatis IDEA中通过maven构建](springmvc/06%20springmvc整合mybatis-mvn构建.md)
51 | - [07 springmvc整合mybatis之mapper](springmvc/07%20springmvc整合mybatis之mapper.md)
52 | - [08 springmvc整合mybatis之service](springmvc/08%20springmvc整合mybatis之service.md)
53 | - [09 springmvc整合mybatis之controller](springmvc/09%20springmvc整合mybatis之controller.md)
54 | - [10 springmvc注解开发之商品修改功能](springmvc/10%20springmvc注解开发之商品修改功能.md)
55 | - [11 springmvc注解开发之简单参数绑定](springmvc/11%20springmvc注解开发之简单参数绑定.md)
56 | - [12 springmvc注解开发之包装类型参数绑定](springmvc/12%20springmvc注解开发之包装类型参数绑定.md)
57 | - [13 springmvc注解开发之集合类型参数绑定](springmvc/13%20springmvc注解开发之集合类型参数绑定.md)
58 | - [14 springmvc校验](springmvc/14%20springmvc校验.md)
59 | - [15 数据回显](springmvc/15%20数据回显.md)
60 | - [16 异常处理器](springmvc/16%20异常处理器.md)
61 | - [17 上传图片](springmvc/17%20上传图片.md)
62 | - [18 json数据交互](springmvc/18%20json数据交互.md)
63 | - [19 RESTful支持](springmvc/19%20RESTful支持.md)
64 | - [20 拦截器](springmvc/20%20拦截器.md)
65 |
66 |
67 |
68 | ## 课程链接
69 |
70 | 哔哩哔哩在线:
71 |
72 | - [SpringMvc+Mybatis由浅入深全套视频教程(完整版)](https://www.bilibili.com/video/av27573870)
73 |
74 |
75 |
76 |
77 |
78 | ## 这里有更多后台技术栈
79 |
80 | [frank-lam/fullstack-tutorial 后台技术栈/架构师成长之路,春招/秋招/校招/面试。](https://github.com/frank-lam/fullstack-tutorial)
81 |
82 |
83 |
84 | ## 关于作者 :boy:
85 |
86 |
87 |
88 | 在颠覆世界的同时,也要好好关照自己。
89 |
90 |

91 |

92 |

93 |

94 |
95 |
96 | from zero to hero.
97 |
98 |
99 | 
--------------------------------------------------------------------------------
/springmvc/11 springmvc注解开发之简单参数绑定.md:
--------------------------------------------------------------------------------
1 | # springmvc学习笔记(11)-springmvc注解开发之简单参数绑定
2 |
3 | 标签: springmvc
4 |
5 | ---
6 |
7 | **Contents**
8 |
9 | - [spring参数绑定过程](#spring参数绑定过程)
10 | - [默认支持的类型](#默认支持的类型)
11 | - [简单类型](#简单类型)
12 | - [pojo绑定](#pojo绑定)
13 | - [自定义参数绑定实现日期类型绑定](#自定义参数绑定实现日期类型绑定)
14 | - [springmvc和struts2的区别](#springmvc和struts2的区别)
15 |
16 |
17 |
18 | ---
19 |
20 |
21 | 本文主要介绍注解开发的简单参数绑定,包括简单类型、简单pojo以及自定义绑定实现类型转换
22 |
23 | ## spring参数绑定过程
24 |
25 | 从客户端请求key/value数据,经过参数绑定,将key/value数据绑定到controller方法的形参上。
26 |
27 | springmvc中,接收页面提交的数据是通过方法形参来接收。而不是在controller类定义成员变更接收!!!!
28 |
29 | 
30 |
31 |
32 |
33 |
34 | ## 默认支持的类型
35 |
36 | 直接在controller方法形参上定义下边类型的对象,就可以使用这些对象。在参数绑定过程中,如果遇到下边类型直接进行绑定。
37 |
38 | - `HttpServletRequest`:通过request对象获取请求信息
39 | - `HttpServletResponse`:通过response处理响应信息
40 | - `HttpSession`:通过session对象得到session中存放的对象
41 | - `Model/ModelMap`:model是一个接口,modelMap是一个接口实现。作用:将model数据填充到request域。
42 |
43 |
44 | ## 简单类型
45 |
46 | 通过`@RequestParam`对简单类型的参数进行绑定。如果不使用`@RequestParam`,要求request传入参数名称和controller方法的形参名称一致,方可绑定成功。
47 |
48 | 如果使用`@RequestParam`,不用限制request传入参数名称和controller方法的形参名称一致。
49 |
50 | 通过required属性指定参数是否必须要传入,如果设置为true,没有传入参数,报下边错误:
51 |
52 | 
53 |
54 |
55 |
56 |
57 | ```java
58 | @RequestMapping(value="/editItems",method={RequestMethod.POST,RequestMethod.GET})
59 | //@RequestParam里边指定request传入参数名称和形参进行绑定。
60 | //通过required属性指定参数是否必须要传入
61 | //通过defaultValue可以设置默认值,如果id参数没有传入,将默认值和形参绑定。
62 | public String editItems(Model model,@RequestParam(value="id",required=true) Integer items_id)throws Exception {
63 |
64 | ```
65 |
66 |
67 | ## pojo绑定
68 |
69 | 页面中input的name和controller的pojo形参中的属性名称一致,将页面中数据绑定到pojo。
70 |
71 | 注意:这里只是要求name和形参的**属性名**一致,而不是要求和形参的**名称**一致,这点不要混淆了,框架会进入形参内部自动匹配pojo类的属性名。(我没看源码,但应该是用反射实现的)
72 |
73 |
74 |
75 | 页面定义:
76 |
77 | ```jsp
78 |
79 |
80 | | 商品名称 |
81 | |
82 |
83 |
84 | | 商品价格 |
85 | |
86 |
87 | ```
88 |
89 | controller的pojo形参的定义:
90 |
91 | ```java
92 | public class Items {
93 | private Integer id;
94 |
95 | private String name;
96 |
97 | private Float price;
98 |
99 | private String pic;
100 |
101 | private Date createtime;
102 |
103 | private String detail;
104 | ```
105 |
106 |
107 | ## 自定义参数绑定实现日期类型绑定
108 |
109 | 对于controller形参中pojo对象,如果属性中有日期类型,需要自定义参数绑定。
110 |
111 | 将请求日期数据串传成日期类型,要转换的日期类型和pojo中日期属性的类型保持一致。本文示例中,自定义参数绑定将日期串转成java.util.Date类型。
112 |
113 | 需要向处理器适配器中注入自定义的参数绑定组件。
114 |
115 |
116 | - 自定义日期类型绑定
117 |
118 | ```java
119 | public class CustomDateConverter implements Converter{
120 | public Date convert(String s) {
121 | //实现 将日期串转成日期类型(格式是yyyy-MM-dd HH:mm:ss)
122 |
123 | SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
124 |
125 | try {
126 | //转成直接返回
127 | return simpleDateFormat.parse(s);
128 | } catch (ParseException e) {
129 | // TODO Auto-generated catch block
130 | e.printStackTrace();
131 | }
132 | //如果参数绑定失败返回null
133 | return null;
134 |
135 | }
136 | }
137 | ```
138 |
139 |
140 | - 配置方式
141 |
142 | ```xml
143 |
144 | ```
145 |
146 | ```xml
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 | ```
158 |
159 |
160 | ## springmvc和struts2的区别
161 |
162 | - 1.springmvc基于方法开发的,struts2基于类开发的。
163 |
164 | springmvc将url和controller方法映射。映射成功后springmvc生成一个Handler对象,对象中只包括了一个method。方法执行结束,形参数据销毁。springmvc的controller开发类似service开发。
165 |
166 | - 2.springmvc可以进行单例开发,并且建议使用单例开发,struts2通过类的成员变量接收参数,无法使用单例,只能使用多例。
167 |
168 | - 3.经过实际测试,struts2速度慢,在于使用struts标签,如果使用struts建议使用jstl。
169 |
--------------------------------------------------------------------------------
/mybatis/14 查询缓存之一级缓存.md:
--------------------------------------------------------------------------------
1 | # mybatis学习笔记(14)-查询缓存之一级缓存
2 |
3 | 标签: mybatis
4 |
5 | ---
6 |
7 | **Contents**
8 |
9 | - [查询缓存](#查询缓存)
10 | - [一级缓存](#一级缓存)
11 | - [一级缓存工作原理](#一级缓存工作原理)
12 | - [一级缓存测试](#一级缓存测试)
13 | - [一级缓存应用](#一级缓存应用)
14 |
15 |
16 |
17 | ---
18 |
19 | 本文主要讲mybatis的一级缓存,一级缓存是SqlSession级别的缓存。
20 |
21 |
22 | ## 查询缓存
23 |
24 | mybatis提供查询缓存,用于减轻数据压力,提高数据库性能。
25 |
26 | mybaits提供一级缓存,和二级缓存。
27 |
28 | 
29 |
30 | 一级缓存是SqlSession级别的缓存。在操作数据库时需要构造sqlSession对象,在对象中有一个数据结构(HashMap)用于存储缓存数据。不同的sqlSession之间的缓存数据区域(HashMap)是互相不影响的。
31 |
32 | 二级缓存是mapper级别的缓存,多个SqlSession去操作同一个Mapper的sql语句,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的。
33 |
34 | 为什么要用缓存?
35 |
36 | 如果缓存中有数据就不用从数据库中获取,大大提高系统性能。
37 |
38 |
39 | ## 一级缓存
40 |
41 | ### 一级缓存工作原理
42 |
43 | 
44 |
45 | 第一次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,如果没有,从数据库查询用户信息。得到用户信息,将用户信息存储到一级缓存中。
46 |
47 | 如果sqlSession去执行commit操作(执行插入、更新、删除),清空SqlSession中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读。
48 |
49 | 第二次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,缓存中有,直接从缓存中获取用户信息。
50 |
51 |
52 | ### 一级缓存测试
53 |
54 | mybatis默认支持一级缓存,不需要在配置文件去配置。
55 |
56 | 按照上边一级缓存原理步骤去测试。
57 |
58 | 测试代码
59 |
60 | ```java
61 | // 一级缓存测试
62 | @Test
63 | public void testCache1() throws Exception {
64 | SqlSession sqlSession = sqlSessionFactory.openSession();// 创建代理对象
65 | UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
66 |
67 | // 下边查询使用一个SqlSession
68 | // 第一次发起请求,查询id为1的用户
69 | User user1 = userMapper.findUserById(1);
70 | System.out.println(user1);
71 |
72 | // 如果sqlSession去执行commit操作(执行插入、更新、删除),清空SqlSession中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读。
73 |
74 | // 更新user1的信息
75 | // user1.setUsername("测试用户22");
76 | // userMapper.updateUser(user1);
77 | // //执行commit操作去清空缓存
78 | // sqlSession.commit();
79 |
80 | // 第二次发起请求,查询id为1的用户
81 | User user2 = userMapper.findUserById(1);
82 | System.out.println(user2);
83 |
84 | sqlSession.close();
85 |
86 | }
87 | ```
88 |
89 |
90 |
91 | 1.不执行更新操作,输出:
92 |
93 | ```
94 | DEBUG [main] - Opening JDBC Connection
95 | DEBUG [main] - Created connection 110771485.
96 | DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@69a3d1d]
97 | DEBUG [main] - ==> Preparing: SELECT * FROM user WHERE id=?
98 | DEBUG [main] - ==> Parameters: 1(Integer)
99 | DEBUG [main] - <== Total: 1
100 | User [id=1, username=王五, sex=2, birthday=null, address=null]
101 | User [id=1, username=王五, sex=2, birthday=null, address=null]
102 | DEBUG [main] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@69a3d1d]
103 | DEBUG [main] - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@69a3d1d]
104 | DEBUG [main] - Returned connection 110771485 to pool.
105 | ```
106 |
107 | 2.取消测试代码中更新的的注释,输出:
108 |
109 | ```
110 | DEBUG [main] - Opening JDBC Connection
111 | DEBUG [main] - Created connection 110771485.
112 | DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@69a3d1d]
113 | DEBUG [main] - ==> Preparing: SELECT * FROM user WHERE id=?
114 | DEBUG [main] - ==> Parameters: 1(Integer)
115 | DEBUG [main] - <== Total: 1
116 | User [id=1, username=王五, sex=2, birthday=null, address=null]
117 | DEBUG [main] - ==> Preparing: update user set username=?,birthday=?,sex=?,address=? where id=?
118 | DEBUG [main] - ==> Parameters: 测试用户22(String), null, 2(String), null, 1(Integer)
119 | DEBUG [main] - <== Updates: 1
120 | DEBUG [main] - Committing JDBC Connection [com.mysql.jdbc.JDBC4Connection@69a3d1d]
121 | DEBUG [main] - ==> Preparing: SELECT * FROM user WHERE id=?
122 | DEBUG [main] - ==> Parameters: 1(Integer)
123 | DEBUG [main] - <== Total: 1
124 | User [id=1, username=测试用户22, sex=2, birthday=null, address=null]
125 | DEBUG [main] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@69a3d1d]
126 | DEBUG [main] - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@69a3d1d]
127 | DEBUG [main] - Returned connection 110771485 to pool.
128 | ```
129 |
130 |
131 |
132 | ### 一级缓存应用
133 |
134 | 正式开发,是将mybatis和spring进行整合开发,事务控制在service中。
135 |
136 | 一个service方法中包括 很多mapper方法调用。
137 |
138 | ```
139 | service{
140 | //开始执行时,开启事务,创建SqlSession对象
141 | //第一次调用mapper的方法findUserById(1)
142 |
143 | //第二次调用mapper的方法findUserById(1),从一级缓存中取数据
144 | //方法结束,sqlSession关闭
145 | }
146 | ```
147 |
148 | 如果是执行两次service调用查询相同的用户信息,不走一级缓存,因为session方法结束,sqlSession就关闭,一级缓存就清空。
149 |
--------------------------------------------------------------------------------
/mybatis/07 输出映射.md:
--------------------------------------------------------------------------------
1 | # mybatis学习笔记(7)-输出映射
2 |
3 | 标签: mybatis
4 |
5 | ---
6 |
7 | **Contents**
8 |
9 | - [resultType](#resulttype)
10 | - [输出简单类型](#输出简单类型)
11 | - [输出pojo对象和pojo列表](#输出pojo对象和pojo列表)
12 | - [resultMap](#resultmap)
13 | - [resultMap使用方法](#resultmap使用方法)
14 | - [小结](#小结)
15 |
16 |
17 |
18 | ---
19 |
20 | 本文主要讲解mybatis的输出映射。
21 |
22 |
23 | 输出映射有两种方式
24 |
25 | - `resultType`
26 | - `resultMap`
27 |
28 |
29 | ## resultType
30 |
31 | - 使用 `resultType` 进行输出映射,只有查询出来的列名和 pojo 中的属性名一致,该列才可以映射成功。
32 | - 如果查询出来的列名和 pojo 中的属性名全部不一致,没有创建 pojo 对象。
33 | - 只要查询出来的列名和 pojo 中的属性有一个一致,就会创建 pojo 对象。
34 |
35 |
36 |
37 | ### 输出简单类型
38 |
39 | 需求:用户信息的综合查询列表总数,通过查询总数和上边用户综合查询列表才可以实现分页。
40 |
41 |
42 |
43 |
44 | - mapper.xml
45 |
46 | ```xml
47 |
51 |
54 | ```
55 |
56 | - mapper.java
57 |
58 | ```java
59 | //用户信息综合查询总数
60 | @Test
61 | public void testFindUserCount() throws Exception {
62 |
63 | SqlSession sqlSession = sqlSessionFactory.openSession();
64 |
65 | //创建UserMapper对象,mybatis自动生成mapper代理对象
66 | UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
67 |
68 | //创建包装对象,设置查询条件
69 | UserQueryVo userQueryVo = new UserQueryVo();
70 | UserCustom userCustom = new UserCustom();
71 | //由于这里使用动态sql,如果不设置某个值,条件不会拼接在sql中
72 | userCustom.setSex("1");
73 | userCustom.setUsername("小");
74 | userQueryVo.setUserCustom(userCustom);
75 | //调用userMapper的方法
76 | int count = userMapper.findUserCount(userQueryVo);
77 | System.out.println(count);
78 | }
79 | ```
80 |
81 |
82 | - 小结
83 |
84 | 查询出来的结果集只有一行且一列,可以使用简单类型进行输出映射。
85 |
86 |
87 |
88 |
89 | ### 输出pojo对象和pojo列表
90 |
91 | 不管是输出的pojo单个对象还是一个列表(list中包括pojo),在mapper.xml中 `resultType` 指定的类型是一样的。
92 |
93 | 在mapper.java指定的方法返回值类型不一样:
94 |
95 | - 输出单个pojo对象,方法返回值是单个对象类型
96 |
97 | ```java
98 | //根据id查询用户信息
99 | public User findUserById(int id) throws Exception;
100 | ```
101 |
102 | - 输出pojo对象list,方法返回值是List
103 |
104 | ```java
105 | //根据用户名列查询用户列表
106 | public List findUserByName(String name) throws Exception;
107 | ```
108 |
109 |
110 | 生成的动态代理对象中是根据mapper方法的返回值类型确定是调用`selectOne`(返回单个对象调用)还是`selectList` (返回集合对象调用 ).
111 |
112 |
113 |
114 | ## resultMap
115 |
116 | mybatis中使用resultMap完成高级输出结果映射。(一对多,多对多)
117 |
118 |
119 | ### resultMap使用方法
120 |
121 | 如果查询出来的列名和pojo的属性名不一致,通过定义一个resultMap对列名和pojo属性名之间作一个映射关系。
122 |
123 | 1.定义resultMap
124 |
125 | 2.使用resultMap作为statement的输出映射类型
126 |
127 | - 定义reusltMap
128 |
129 | ```xml
130 |
136 |
137 |
142 |
143 |
149 |
150 |
151 | ```
152 |
153 | - 使用resultMap作为statement的输出映射类型
154 |
155 | ```xml
156 |
159 |
162 |
163 | ```
164 |
165 | - mapper.java
166 |
167 | ```java
168 | //根据id查询用户信息,使用resultMap输出
169 | public User findUserByIdResultMap(int id) throws Exception;
170 | ```
171 |
172 | - 测试代码
173 |
174 | ```java
175 | @Test
176 | public void testFindUserByIdResultMap() throws Exception {
177 | SqlSession sqlSession = sqlSessionFactory.openSession();
178 | //创建UserMapper对象,mybatis自动生成mapper代理对象
179 | UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
180 | //调用userMapper的方法
181 | User user = userMapper.findUserByIdResultMap(1);
182 | System.out.println(user);
183 | }
184 | ```
185 |
186 |
187 | ### 小结
188 |
189 | 使用resultType进行输出映射,只有查询出来的列名和pojo中的属性名一致,该列才可以映射成功。
190 |
191 | 如果查询出来的列名和pojo的属性名不一致,通过定义一个resultMap对列名和pojo属性名之间作一个映射关系。
192 |
--------------------------------------------------------------------------------
/springmvc/05 入门程序小结.md:
--------------------------------------------------------------------------------
1 | # springmvc学习笔记(5)-入门程序小结
2 |
3 | 标签: springmvc
4 |
5 | ---
6 |
7 | **Contents**
8 |
9 | - [入门程序配置小结](#入门程序配置小结)
10 | - [非注解的完整的配置文件](#非注解的完整的配置文件)
11 | - [注解的完整配置文件](#注解的完整配置文件)
12 |
13 |
14 |
15 | ---
16 |
17 |
18 | 通过入门程序理解springmvc前端控制器、处理器映射器、处理器适配器、视图解析器用法。并附上入门程序的非注解的完整的配置文件,注解的完整配置文件。
19 |
20 | ## 入门程序配置小结
21 |
22 | 前端控制器配置:
23 |
24 | - 第一种:`*.action`,访问以`.action`结尾 由`DispatcherServlet`进行解析
25 | - 第二种:`/`,所以访问的地址都由`DispatcherServlet`进行解析,对于静态文件的解析需要配置不让`DispatcherServlet`进行解析,使用此种方式可以实现RESTful风格的url
26 |
27 | 处理器映射器:
28 |
29 | - 非注解处理器映射器(了解)
30 | - 注解的处理器映射器(掌握)
31 | - 对标记 `@Controller` 类中标识有 `@RequestMapping` 的方法进行映射。在 `@RequestMapping` 里边定义映射的 url 。使用注解的映射器不用在 xml 中配置 url 和 Handler 的映射关系。
32 |
33 | 处理器适配器:
34 |
35 | - 非注解处理器适配器(了解)
36 | - 注解的处理器适配器(掌握)
37 | - 注解处理器适配器和注解的处理器映射器是**配对使用**。理解为不能使用非注解映射器进行映射。
38 |
39 |
40 |
41 | ```xml
42 |
43 | ```
44 |
45 | 可以代替下边的配置:
46 |
47 | ```xml
48 |
49 |
50 |
51 |
52 | ```
53 |
54 |
55 |
56 | ## 非注解的完整的配置文件
57 |
58 | `src/main/resources/springmvc.xml`
59 |
60 | ```xml
61 |
68 |
69 |
70 |
71 |
72 |
75 |
76 |
77 |
80 |
81 |
82 |
85 |
86 |
87 |
88 | ```
89 |
90 |
91 |
92 | ## 注解的完整配置文件
93 |
94 | ```xml
95 |
102 |
103 |
106 |
107 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
124 |
125 |
126 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 | ```
138 |
139 |
--------------------------------------------------------------------------------
/mybatis/12 多对多查询.md:
--------------------------------------------------------------------------------
1 | # mybatis学习笔记(12)-多对多查询
2 |
3 | 标签: mybatis
4 |
5 | ---
6 |
7 | **Contents**
8 |
9 | - [示例](#示例)
10 | - [多对多查询总结](#多对多查询总结)
11 | - [resultMap总结](#resultmap总结)
12 |
13 |
14 |
15 | ---
16 |
17 |
18 | 本文实现多对多查询,查询用户及用户购买商品信息。
19 |
20 | ## 示例
21 |
22 | 查询主表是:用户表
23 |
24 | 关联表:由于用户和商品没有直接关联,通过订单和订单明细进行关联,所以关联表:orders、orderdetail、items
25 |
26 |
27 | - sql
28 |
29 | ```sql
30 | SELECT
31 | orders.*,
32 | user.username,
33 | user.sex,
34 | user.address,
35 | orderdetail.id orderdetail_id,
36 | orderdetail.items_id,
37 | orderdetail.items_num,
38 | orderdetail.orders_id,
39 | items.name items_name,
40 | items.detail items_detail,
41 | items.price items_price
42 | FROM
43 | orders,
44 | user,
45 | orderdetail,
46 | items
47 | WHERE orders.user_id = user.id AND orderdetail.orders_id=orders.id AND orderdetail.items_id = items.id
48 | ```
49 |
50 |
51 | - 映射思路
52 |
53 | 将用户信息映射到user中。
54 |
55 | 在user类中添加订单列表属性`List orderslist`,将用户创建的订单映射到orderslist
56 |
57 | 在Orders中添加订单明细列表属性`Listorderdetials`,将订单的明细映射到orderdetials
58 |
59 | 在OrderDetail中添加`Items`属性,将订单明细所对应的商品映射到Items
60 |
61 |
62 | - mapper.xml
63 |
64 | ```xml
65 |
66 |
86 | ```
87 |
88 | - resultMap
89 |
90 | ```xml
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 | ```
133 |
134 | - mapper.java
135 |
136 | ```java
137 | //查询用户购买商品信息
138 | public List findUserAndItemsResultMap()throws Exception;
139 | ```
140 |
141 | ## 多对多查询总结
142 |
143 | 将查询用户购买的商品信息明细清单,(用户名、用户地址、购买商品名称、购买商品时间、购买商品数量)
144 |
145 | 针对上边的需求就使用resultType将查询到的记录映射到一个扩展的pojo中,很简单实现明细清单的功能。
146 |
147 | 一对多是多对多的特例,如下需求:
148 |
149 | 查询用户购买的商品信息,用户和商品的关系是多对多关系。
150 |
151 | - 需求1:
152 |
153 | 查询字段:用户账号、用户名称、用户性别、商品名称、商品价格(最常见)
154 |
155 | 企业开发中常见明细列表,用户购买商品明细列表,
156 |
157 | 使用resultType将上边查询列映射到pojo输出。
158 |
159 | - 需求2:
160 |
161 | 查询字段:用户账号、用户名称、购买商品数量、商品明细(鼠标移上显示明细)
162 |
163 | 使用resultMap将用户购买的商品明细列表映射到user对象中。
164 |
165 | 总结:
166 |
167 | 使用resultMap是针对那些对查询结果映射有特殊要求的功能,比如特殊要求映射成list中包括多个list。
168 |
169 |
170 |
171 | ## resultMap总结
172 |
173 | - resultType
174 | - 作用:将查询结果按照sql列名pojo属性名一致性映射到pojo中。
175 | - 场合:常见一些明细记录的展示,比如用户购买商品明细,将关联查询信息全部展示在页面时,此时可直接使用resultType将每一条记录映射到pojo中,在前端页面遍历list(list中是pojo)即可。
176 |
177 | - resultMap
178 |
179 | 使用association和collection完成一对一和一对多高级映射(对结果有特殊的映射要求)。
180 |
181 | association:
182 |
183 | - 作用:将关联查询信息映射到一个pojo对象中。
184 | - 场合:为了方便查询关联信息可以使用association将关联订单信息映射为用户对象的pojo属性中,比如:查询订单及关联用户信息。
185 |
186 | 使用resultType无法将查询结果映射到pojo对象的pojo属性中,根据对结果集查询遍历的需要选择使用resultType还是resultMap。
187 |
188 | collection:
189 |
190 | - 作用:将关联查询信息映射到一个list集合中。
191 | - 场合:为了方便查询遍历关联信息可以使用collection将关联信息映射到list集合中,比如:查询用户权限范围模块及模块下的菜单,可使用collection将模块映射到模块list中,将菜单列表映射到模块对象的菜单list属性中,这样的作的目的也是方便对查询结果集进行遍历查询。如果使用resultType无法将查询结果映射到list集合中。
192 |
--------------------------------------------------------------------------------
/springmvc/16 异常处理器.md:
--------------------------------------------------------------------------------
1 | # springmvc学习笔记(16)-异常处理器
2 |
3 | 标签: springmvc
4 |
5 | ---
6 |
7 | **Contents**
8 |
9 | - [异常处理思路](#异常处理思路)
10 | - [自定义异常类](#自定义异常类)
11 | - [全局异常处理器](#全局异常处理器)
12 | - [错误页面](#错误页面)
13 | - [在springmvc.xml配置全局异常处理器](#在springmvcxml配置全局异常处理器)
14 | - [异常测试](#异常测试)
15 |
16 |
17 |
18 | ---
19 |
20 |
21 | 本文主要介绍springmvc中异常处理的思路,并展示如何自定义异常处理类以及全局异常处理器的配置
22 |
23 |
24 | ## 异常处理思路
25 |
26 | 系统中异常包括两类:
27 |
28 | - 预期异常
29 | - 运行时异常RuntimeException
30 |
31 | 前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发、测试通过手段减少运行时异常的发生。
32 |
33 | 系统的dao、service、controller出现都通过throws Exception向上抛出,最后由springmvc前端控制器交由异常处理器进行异常处理,如下图:
34 |
35 | 
36 |
37 | springmvc提供全局异常处理器(一个系统只有一个异常处理器)进行统一异常处理。
38 |
39 |
40 | ## 自定义异常类
41 |
42 | 对不同的异常类型定义异常类,继承Exception。
43 |
44 | ```java
45 | package com.iot.learnssm.firstssm.exception;
46 |
47 | /**
48 | * Created by brian on 2016/3/7.
49 | *
50 | * 系统 自定义异常类,针对预期的异常,需要在程序中抛出此类的异常
51 | */
52 | public class CustomException extends Exception{
53 | //异常信息
54 | public String message;
55 |
56 | public CustomException(String message){
57 | super(message);
58 | this.message = message;
59 | }
60 |
61 | public String getMessage() {
62 | return message;
63 | }
64 |
65 | public void setMessage(String message) {
66 | this.message = message;
67 | }
68 | }
69 | ```
70 |
71 | ## 全局异常处理器
72 |
73 | 思路:
74 |
75 | 系统遇到异常,在程序中手动抛出,dao抛给service、service给controller、controller抛给前端控制器,前端控制器调用全局异常处理器。
76 |
77 | 全局异常处理器处理思路:
78 |
79 | 解析出异常类型
80 |
81 | - 如果该异常类型是系统自定义的异常,直接取出异常信息,在错误页面展示
82 | - 如果该异常类型不是系统自定义的异常,构造一个自定义的异常类型(信息为“未知错误”)
83 |
84 | springmvc提供一个`HandlerExceptionResolver`接口
85 |
86 |
87 | ```java
88 | public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
89 | //handler就是处理器适配器要执行Handler对象(只有method)
90 | //解析出异常类型
91 | //如果该 异常类型是系统 自定义的异常,直接取出异常信息,在错误页面展示
92 | //String message = null;
93 | //if(ex instanceof CustomException){
94 | //message = ((CustomException)ex).getMessage();
95 | //}else{
96 | ////如果该 异常类型不是系统 自定义的异常,构造一个自定义的异常类型(信息为“未知错误”)
97 | //message="未知错误";
98 | //}
99 |
100 | //上边代码变为
101 | CustomException customException;
102 | if(ex instanceof CustomException){
103 | customException = (CustomException)ex;
104 | }else{
105 | customException = new CustomException("未知错误");
106 | }
107 |
108 | //错误信息
109 | String message = customException.getMessage();
110 |
111 | ModelAndView modelAndView = new ModelAndView();
112 |
113 | //将错误信息传到页面
114 | modelAndView.addObject("message", message);
115 |
116 | //指向错误页面
117 | modelAndView.setViewName("error");
118 |
119 | return modelAndView;
120 |
121 | }
122 | }
123 | ```
124 |
125 | ## 错误页面
126 |
127 | ```jsp
128 | <%--
129 | Created by IntelliJ IDEA.
130 | User: Brian
131 | Date: 2016/3/4
132 | Time: 10:51
133 | To change this template use File | Settings | File Templates.
134 | --%>
135 | <%@ page contentType="text/html;charset=UTF-8" language="java" %>
136 |
137 |
138 | 错误提示
139 |
140 |
141 | ${message}
142 |
143 |
144 | ```
145 |
146 | ## 在springmvc.xml配置全局异常处理器
147 |
148 | ```xml
149 |
152 |
153 | ```
154 |
155 | 全局异常处理器只有一个,配置多个也没用。
156 |
157 |
158 |
159 | ## 异常测试
160 |
161 | 在controller、service、dao中任意一处需要手动抛出异常。如果是程序中手动抛出的异常,在错误页面中显示自定义的异常信息,如果不是手动抛出异常说明是一个运行时异常,在错误页面只显示“未知错误”。
162 |
163 | - 在商品修改的controller方法中抛出异常 .
164 |
165 | ```java
166 | public String editItems(Model model,@RequestParam(value="id",required=true) Integer items_id)throws Exception {
167 |
168 | //调用service根据商品id查询商品信息
169 | ItemsCustom itemsCustom = itemsService.findItemsById(items_id);
170 |
171 | //判断商品是否为空,根据id没有查询到商品,抛出异常,提示用户商品信息不存在
172 | if(itemsCustom == null){
173 | throw new CustomException("修改的商品信息不存在!");
174 | }
175 |
176 | //通过形参中的model将model数据传到页面
177 | //相当于modelAndView.addObject方法
178 | model.addAttribute("items", itemsCustom);
179 |
180 | return "items/editItems";
181 | }
182 | ```
183 |
184 | - 在service接口中抛出异常:
185 |
186 | ```java
187 | public ItemsCustom findItemsById(Integer id) throws Exception {
188 | Items items = itemsMapper.selectByPrimaryKey(id);
189 | if(items==null){
190 | throw new CustomException("修改的商品信息不存在!");
191 | }
192 | //中间对商品信息进行业务处理
193 | //....
194 | //返回ItemsCustom
195 | ItemsCustom itemsCustom = null;
196 | //将items的属性值拷贝到itemsCustom
197 | if(items!=null){
198 | itemsCustom = new ItemsCustom();
199 | BeanUtils.copyProperties(items, itemsCustom);
200 | }
201 |
202 | return itemsCustom;
203 | }
204 | ```
205 |
206 |
207 | - 如果与业务功能相关的异常,建议在service中抛出异常。
208 | - 与业务功能没有关系的异常,建议在controller中抛出。
209 |
210 | 上边的功能,建议在service中抛出异常。
211 |
--------------------------------------------------------------------------------
/mybatis/10 一对一查询.md:
--------------------------------------------------------------------------------
1 | # mybatis学习笔记(10)-一对一查询
2 |
3 | 标签: mybatis
4 |
5 | ---
6 |
7 | **Contents**
8 |
9 | - [resultType实现](#resulttype实现)
10 | - [resultMap实现](#resultmap实现)
11 | - [resultType和resultMap实现一对一查询小结](#resulttype和resultmap实现一对一查询小结)
12 |
13 |
14 |
15 | ---
16 |
17 |
18 | 本文使用两种方式(resultType和resultMap)实现一对一查询,查询订单信息,关联查询创建订单的用户信息
19 |
20 |
21 | ## resultType实现
22 |
23 | - sql语句
24 |
25 |
26 | 确定查询的主表:订单表
27 |
28 | 确定查询的关联表:用户表
29 |
30 | 关联查询使用内连接?还是外连接?
31 |
32 | 由于orders表中有一个外键(user_id),通过外键关联查询用户表只能查询出一条记录,可以使用内连接。
33 |
34 | ```sql
35 | SELECT
36 | orders.*,
37 | USER.username,
38 | USER.sex,
39 | USER.address
40 | FROM
41 | orders,
42 | USER
43 | WHERE orders.user_id = user.id
44 | ```
45 |
46 | - 创建pojo
47 |
48 | 将上边sql查询的结果映射到pojo中,pojo中必须包括所有查询列名。
49 |
50 | 原始的Orders.java不能映射全部字段,需要新创建的pojo。
51 |
52 | 创建一个pojo继承包括查询字段较多的po类。
53 |
54 | 对应数据表的几个pojo类(Items,Orderdetail,Orders)就是把该类的属性名设为和数据表列字段名相同,并为这些属性添加getter和setter,在这里就不贴代码了,只贴出对应于关联查询的自定义pojo类`OrdersCustom`的代码
55 |
56 | ```java
57 | package com.iot.mybatis.po;
58 |
59 | /**
60 | *
61 | * Title: OrdersCustom
62 | * Description: 订单的扩展类
63 | */
64 | //通过此类映射订单和用户查询的结果,让此类继承包括 字段较多的pojo类
65 | public class OrdersCustom extends Orders{
66 |
67 | //添加用户属性
68 | /*USER.username,
69 | USER.sex,
70 | USER.address */
71 |
72 | private String username;
73 | private String sex;
74 | private String address;
75 |
76 |
77 | public String getUsername() {
78 | return username;
79 | }
80 | public void setUsername(String username) {
81 | this.username = username;
82 | }
83 |
84 | public String getSex() {
85 | return sex;
86 | }
87 | public void setSex(String sex) {
88 | this.sex = sex;
89 | }
90 |
91 | public String getAddress() {
92 | return address;
93 | }
94 | public void setAddress(String address) {
95 | this.address = address;
96 | }
97 |
98 | }
99 |
100 | ```
101 |
102 |
103 |
104 | - mapper.xml
105 |
106 | ```xml
107 |
108 |
119 | ```
120 |
121 |
122 | - mapper.java
123 |
124 | ```java
125 | //查询订单关联查询用户信息
126 | public List findOrdersUser()throws Exception;
127 | }
128 | ```
129 |
130 |
131 |
132 | ## resultMap实现
133 |
134 | 使用resultMap将查询结果中的订单信息映射到Orders对象中,在orders类中添加User属性,将关联查询出来的用户信息映射到orders对象中的user属性中。
135 |
136 | - 定义resultMap
137 |
138 |
139 | ```xml
140 |
143 |
144 |
145 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
159 |
160 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 | ```
172 |
173 |
174 | - statement定义
175 |
176 |
177 | ```xml
178 |
179 |
190 | ```
191 |
192 | - mapper.java
193 |
194 | ```java
195 | //查询订单关联查询用户使用resultMap
196 | public List findOrdersUserResultMap()throws Exception;
197 | ```
198 |
199 | - 测试代码
200 |
201 | ```java
202 | @Test
203 | public void testFindOrdersUserResultMap() throws Exception {
204 |
205 | SqlSession sqlSession = sqlSessionFactory.openSession();
206 | // 创建代理对象
207 | OrdersMapperCustom ordersMapperCustom = sqlSession
208 | .getMapper(OrdersMapperCustom.class);
209 |
210 | // 调用maper的方法
211 | List list = ordersMapperCustom.findOrdersUserResultMap();
212 |
213 | System.out.println(list);
214 |
215 | sqlSession.close();
216 | }
217 | ```
218 |
219 | ## resultType和resultMap实现一对一查询小结
220 |
221 | 实现一对一查询:
222 |
223 | - resultType:使用resultType实现较为简单,如果pojo中没有包括查询出来的列名,需要增加列名对应的属性,即可完成映射。如果没有查询结果的特殊要求建议使用resultType。
224 | - resultMap:需要单独定义resultMap,实现有点麻烦,如果对查询结果有特殊的要求,使用resultMap可以完成将关联查询映射pojo的属性中。
225 | - resultMap可以实现延迟加载,resultType无法实现延迟加载。
226 |
227 |
228 |
--------------------------------------------------------------------------------
/springmvc/06 springmvc整合mybatis-mvn构建.md:
--------------------------------------------------------------------------------
1 | # springmvc学习笔记(6)-springmvc整合mybatis(IDEA中通过maven构建)
2 |
3 | 标签: springmvc mybatis
4 |
5 | ---
6 |
7 | **Contents**
8 |
9 | - [整合思路](#整合思路)
10 | - [工程结构](#工程结构)
11 | - [添加依赖](#添加依赖)
12 | - [建包](#建包)
13 |
14 |
15 |
16 | ---
17 |
18 |
19 | 本文主要展示如何在intellij IDEA中通过maven构建springmvc+mybatis框架的开发环境。
20 |
21 |
22 |
23 | 需求:使用springmvc和mybatis完成商品列表查询
24 |
25 | ## 整合思路
26 |
27 | 
28 |
29 |
30 | - 第一步:整合dao层
31 | - mybatis和spring整合,通过spring管理mapper接口。
32 | - 使用mapper的扫描器自动扫描mapper接口在spring中进行注册。
33 |
34 | - 第二步:整合service层
35 | - 通过spring管理service接口。
36 | - 使用配置方式将service接口配置在spring配置文件中。
37 | - 实现事务控制。
38 |
39 | - 第三步:整合springmvc
40 | - 由于springmvc是spring的模块,不需要整合。
41 |
42 |
43 |
44 | ## 工程结构
45 |
46 | 不同于[《mybatis学习笔记(17)-spring和mybatis整合》](http://blog.csdn.net/h3243212/article/details/50778934)中的示例demo,**本文的整合采用maven构建**。
47 |
48 | 如何创建使用maven构建的web应用可以参考前面的一篇[《springmvc学习笔记(1)-框架原理和入门配置》](http://blog.csdn.net/h3243212/article/details/50828141#环境搭建)
49 |
50 | `new->project->maven`,建一个裸的maven工程,手动建webapp的目录
51 |
52 | 在`src/main`下新建文件夹`webapp`
53 |
54 | ### 添加依赖
55 |
56 | pom.xml文件
57 |
58 | ```xml
59 |
60 |
63 | 4.0.0
64 |
65 | com.iot.learnssm
66 | learnssm-firstssm
67 | 1.0-SNAPSHOT
68 | war
69 |
70 |
71 | UTF-8
72 |
73 | 4.2.4.RELEASE
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 | org.springframework
82 | spring-webmvc
83 | ${spring.version}
84 |
85 |
86 |
87 | org.springframework
88 | spring-core
89 | ${spring.version}
90 |
91 |
92 |
93 | org.springframework
94 | spring-orm
95 | ${spring.version}
96 |
97 |
98 |
99 | org.springframework
100 | spring-aspects
101 | ${spring.version}
102 |
103 |
104 |
105 | org.springframework
106 | spring-test
107 | ${spring.version}
108 |
109 |
110 |
111 | org.springframework
112 | spring-jdbc
113 | ${spring.version}
114 |
115 |
116 |
117 |
118 | mysql
119 | mysql-connector-java
120 | 5.1.38
121 |
122 |
123 | org.mybatis
124 | mybatis
125 | 3.3.1
126 |
127 |
128 | org.mybatis
129 | mybatis-spring
130 | 1.2.4
131 |
132 |
133 | log4j
134 | log4j
135 | 1.2.17
136 |
137 |
138 |
139 | org.slf4j
140 | slf4j-api
141 | 1.7.18
142 |
143 |
144 |
145 | commons-dbcp
146 | commons-dbcp
147 | 1.4
148 |
149 |
150 |
151 |
152 | javax.servlet
153 | jstl
154 | 1.2
155 |
156 |
157 | taglibs
158 | standard
159 | 1.1.2
160 |
161 |
162 |
163 |
164 | ```
165 |
166 | 这里添加的依赖可能有多的,但总比少包好,我开始就是引少了依赖(springframework的依赖只引用了spring-mvc,连spring-core都没引),导致报错,以后会出一篇博客专门讲这个系列笔记中debug相关问题。
167 |
168 |
169 | ### 建包
170 |
171 | 在java目录下建各个package,按照maven的命名习惯:
172 |
173 | `com.公司名.项目名.模块名`
174 |
175 | 这里我的包为:
176 |
177 | `com.iot.learnssm.firstssm`
178 |
179 | 包含几个子包:
180 |
181 | - controller
182 | - mapper
183 | - po
184 | - service
185 | - impl
186 |
187 |
188 | 后面几篇笔记会依次记录mapper,service,controller各个部分的整合
189 |
190 | ----
191 |
192 |
193 |
194 |
195 |
196 |
--------------------------------------------------------------------------------
/mybatis/16 mybatis整合ehcache.md:
--------------------------------------------------------------------------------
1 | # mybatis学习笔记(16)-mybatis整合ehcache
2 |
3 | 标签: mybatis
4 |
5 | ---
6 |
7 | **Contents**
8 |
9 | - [分布缓存](#分布缓存)
10 | - [整合方法(掌握)](#整合方法掌握)
11 | - [整合ehcache](#整合ehcache)
12 | - [加入ehcache的配置文件](#加入ehcache的配置文件)
13 |
14 |
15 |
16 | ---
17 |
18 | ehcache是一个分布式缓存框架
19 |
20 | ## 分布缓存
21 |
22 | 我们系统为了提高系统并发,性能、一般对系统进行分布式部署(集群部署方式)
23 |
24 | 
25 |
26 |
27 | 不使用分布缓存,缓存的数据在各各服务单独存储,不方便系统开发。所以要使用分布式缓存对缓存数据进行集中管理。
28 |
29 | mybatis无法实现分布式缓存,需要和其它分布式缓存框架进行整合。
30 |
31 |
32 | ## 整合方法(掌握)
33 |
34 | mybatis提供了一个`cache`接口,如果要实现自己的缓存逻辑,实现`cache`接口开发即可。
35 |
36 | mybatis和ehcache整合,mybatis和ehcache整合包中提供了一个cache接口的实现类。
37 |
38 |
39 | ```java
40 | package org.apache.ibatis.cache;
41 |
42 | import java.util.concurrent.locks.ReadWriteLock;
43 |
44 | /**
45 | * SPI for cache providers.
46 | *
47 | * One instance of cache will be created for each namespace.
48 | *
49 | * The cache implementation must have a constructor that receives the cache id as an String parameter.
50 | *
51 | * MyBatis will pass the namespace as id to the constructor.
52 | *
53 | *
54 | * public MyCache(final String id) {
55 | * if (id == null) {
56 | * throw new IllegalArgumentException("Cache instances require an ID");
57 | * }
58 | * this.id = id;
59 | * initialize();
60 | * }
61 | *
62 | *
63 | * @author Clinton Begin
64 | */
65 |
66 | public interface Cache {
67 |
68 | /**
69 | * @return The identifier of this cache
70 | */
71 | String getId();
72 |
73 | /**
74 | * @param key Can be any object but usually it is a {@link CacheKey}
75 | * @param value The result of a select.
76 | */
77 | void putObject(Object key, Object value);
78 |
79 | /**
80 | * @param key The key
81 | * @return The object stored in the cache.
82 | */
83 | Object getObject(Object key);
84 |
85 | /**
86 | * Optional. It is not called by the core.
87 | *
88 | * @param key The key
89 | * @return The object that was removed
90 | */
91 | Object removeObject(Object key);
92 |
93 | /**
94 | * Clears this cache instance
95 | */
96 | void clear();
97 |
98 | /**
99 | * Optional. This method is not called by the core.
100 | *
101 | * @return The number of elements stored in the cache (not its capacity).
102 | */
103 | int getSize();
104 |
105 | /**
106 | * Optional. As of 3.2.6 this method is no longer called by the core.
107 | *
108 | * Any locking needed by the cache must be provided internally by the cache provider.
109 | *
110 | * @return A ReadWriteLock
111 | */
112 | ReadWriteLock getReadWriteLock();
113 |
114 | }
115 | ```
116 |
117 |
118 | mybatis默认实现cache类是:
119 |
120 | ```java
121 | package org.apache.ibatis.cache.impl;
122 |
123 | import java.util.HashMap;
124 | import java.util.Map;
125 | import java.util.concurrent.locks.ReadWriteLock;
126 |
127 | import org.apache.ibatis.cache.Cache;
128 | import org.apache.ibatis.cache.CacheException;
129 |
130 | /**
131 | * @author Clinton Begin
132 | */
133 | public class PerpetualCache implements Cache {
134 |
135 | private String id;
136 |
137 | private Map