0%

多线程常用方法

1、线程的基础方法

1、wait()

wait()方法为 Object 类中的方法,为 final 方法无法被重写。
调用某个对象的 wait()方法可以让当前线程阻塞,进入等待队列,并且当前线程必须拥有此线程的锁,wait()方法会释放锁。

2、notify()

notify()方法与 wait()方法相似,同样为 Object 类中的 final 方法, 无法被重写。
调用某个对象的 notify()方法,可以唤醒一个正在等待获取当前对象的锁的线程。如果有多个线程在等待时,则会随机唤醒一个。

3、notifyAll()

notifyAll()方法与 notify()方法相似,区别在于 notifyAll()方法会唤醒所有等待当前对象的锁的线程。

4、sleep()

sleep()方法为 Tread 类中的方法,sleep()方法可以让当前线程暂停一段时间,时间结束后继续等待 cpu,获取到 cpu 后继续执行。
sleep()方法与 wait()的区别是,sleep()方法不会释放对象的锁,只是暂时将 cpu 让出来,而 wait()方法则会释放对象的锁。
sleep()方法可以在任何地方使用,而 wait()方法必须在同步代码块内使用。

5、interrupt()

尝试中断线程。
该方法的目的是给线程发送中断信号,但不会真的中断该线程,被中断线程可以决定如何应对中断。
interrupt()方法不会中断一个正在运行的线程。获取锁的过程不能被中断。
线程再调用 wait()、sleep()、join()方法过程中受阻,会清楚中断状态,同时会抛出一个 InterruptedException 异常,用户可以捕获这个异常做一些其他处理。

6、interrupted()

判断当前线程是否已经中断,如果中断,则会清楚中断状态。连续调用两次该方法,第二次必定会返回 false。

7、isInterrupted()

判断线程是否已经中断,线程的中断状态不受此方法的影响。判断调用的线程。

8、join()

是一个同步方法,底层采用 wait()方法实现。线程启动后调用才会有效。
t.join()      必须获取 t 对象的锁,当前线程(当前在 cpu 上运行的线程)暂停(或一定的时间),等待 t 线程执行结束后,当前线程才能继续往下执行。
如果有时间传参,当前线程会等待固定时间,实际等待时间是获取 t 对象的锁的时间加传入的时间。

9、yield()

当对某个线程执行 yield()方法后,该线程会尝试暂停自己,会给同级的线程让道。yield()方法不稳定,无法确定具体的执行时间。

1、线程状态转换图


TreeSet 原理与源码分析

1、原理

2、源码分析

2.1、构造方法

1
2
3
4
//底层采用TreeMap实现
public TreeSet(Comparator<? super E> comparator) {
this(new TreeMap<>(comparator));
}

2.2、构造方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//由于其底层采用TreeMap实现,其底层方法同样使用TreeMap的方法
//TreeSet只采用TreeMap存放key的一列,与HashSet相似
public boolean add(E e) {
return m.put(e, PRESENT)==null;
}
public boolean contains(Object o) {
return m.containsKey(o);
}
public boolean isEmpty() {
return m.isEmpty();
}
public int size() {
return m.size();
}
public boolean remove(Object o) {
return m.remove(o)==PRESENT;
}
public void clear() {
m.clear();
}

TreeMap 原理与源码解析

1、原理

2、源码解析

2.1、构造方法

1
2
3
4
//空参的构造方法,比较器设为空
public TreeMap() {
comparator = null;
}

2.2、put 方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
public V put(K key, V value) {
Entry<K,V> t = root;
if (t == null) {
compare(key, key); // type (and possibly null) check
//放入Map的为第一个元素,为红黑树的跟节点
root = new Entry<>(key, value, null);
size = 1;
modCount++;
return null;
}
int cmp;
Entry<K,V> parent;
// split comparator and comparable paths
//获取设置的比较器
Comparator<? super K> cpr = comparator;
if (cpr != null) {
do {
parent = t;
//使用比较器对key进行比较,沿左右子树向下查询,相同的则匹配掉值
cmp = cpr.compare(key, t.key);
if (cmp < 0)
t = t.left;
else if (cmp > 0)
t = t.right;
else
return t.setValue(value);
} while (t != null);
}
else {
if (key == null)
throw new NullPointerException();
@SuppressWarnings("unchecked")
//使用存入对象实现的比较器进行比较,沿左右子树向下查询,相同的则匹配掉值
Comparable<? super K> k = (Comparable<? super K>) key;
do {
parent = t;
cmp = k.compareTo(t.key);
if (cmp < 0)
t = t.left;
else if (cmp > 0)
t = t.right;
else
return t.setValue(value);
} while (t != null);
}
//构造新节点
Entry<K,V> e = new Entry<>(key, value, parent);
//未在现有节点发现时,插入新节点
if (cmp < 0)
parent.left = e;
else
parent.right = e;
fixAfterInsertion(e);
size++;
modCount++;
return null;
}

2.3、get 方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public V get(Object key) {
Entry<K,V> p = getEntry(key);
return (p==null ? null : p.value);
}
//获取Entry数组
final Entry<K,V> getEntry(Object key) {
// Offload comparator-based version for sake of performance
if (comparator != null)
return getEntryUsingComparator(key);
if (key == null)
throw new NullPointerException();
@SuppressWarnings("unchecked")
//从存入的对象中获取比较器
Comparable<? super K> k = (Comparable<? super K>) key;
Entry<K,V> p = root;
//沿左右子树查找,查找到就返回
while (p != null) {
int cmp = k.compareTo(p.key);
if (cmp < 0)
p = p.left;
else if (cmp > 0)
p = p.right;
else
return p;
}
return null;
}

2.4、containsKey 方法

1
2
3
4
//判断根据key能否获取到Entry对象
public boolean containsKey(Object key) {
return getEntry(key) != null;
}

2.5、containsValue 方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public boolean containsValue(Object value) {
//从跟节点递归循环遍历,判断值是否相同
for (Entry<K,V> e = getFirstEntry(); e != null; e = successor(e))
if (valEquals(value, e.value))
return true;
return false;
}
//获取红黑树的跟节点,沿左分支查找最终的叶子节点
final Entry<K,V> getFirstEntry() {
Entry<K,V> p = root;
if (p != null)
while (p.left != null)
p = p.left;
return p;
}
static <K,V> TreeMap.Entry<K,V> successor(Entry<K,V> t) {
if (t == null)
return null;
//没有了左子节点,但是却有右子节点
else if (t.right != null) {
Entry<K,V> p = t.right;
while (p.left != null)
p = p.left;
return p;
//t没有右子结点
} else {
Entry<K,V> p = t.parent;
Entry<K,V> ch = t;
//t有右边的兄弟
while (p != null && ch == p.right) {
ch = p;
p = p.parent;
}
return p;
}
}

2.6、remove 方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
public V remove(Object key) {
//根据key获取到Entry数组
Entry<K,V> p = getEntry(key);
if (p == null)
return null;
V oldValue = p.value;
//删除要删除的Entry数组
deleteEntry(p);
return oldValue;
}
//等待仔细分析,红黑树操作
private void deleteEntry(Entry<K,V> p) {
modCount++;
size--;
// If strictly internal, copy successor's element to p and then make p
// point to successor.
if (p.left != null && p.right != null) {
//左方向移动
Entry<K,V> s = successor(p);
p.key = s.key;
p.value = s.value;
p = s;
} // p has 2 children
// Start fixup at replacement node, if it exists.
//替换指针
Entry<K,V> replacement = (p.left != null ? p.left : p.right);
if (replacement != null) {
// Link replacement to parent
replacement.parent = p.parent;
if (p.parent == null)
root = replacement;
else if (p == p.parent.left)
p.parent.left = replacement;
else
p.parent.right = replacement;
// Null out links so they are OK to use by fixAfterDeletion.
p.left = p.right = p.parent = null;
// Fix replacement
if (p.color == BLACK)
fixAfterDeletion(replacement);
} else if (p.parent == null) { // return if we are the only node.
root = null;
} else { // No children. Use self as phantom replacement and unlink.
if (p.color == BLACK)
fixAfterDeletion(p);
if (p.parent != null) {
if (p == p.parent.left)
p.parent.left = null;
else if (p == p.parent.right)
p.parent.right = null;
p.parent = null;
}
}
}

2.7、replace 方法

1
2
3
4
5
6
7
8
9
10
11
public V replace(K key, V value) {
//根据key获取指定Entry数组
Entry<K,V> p = getEntry(key);
//值替换
if (p!=null) {
V oldValue = p.value;
p.value = value;
return oldValue;
}
return null;
}

1、ssm

1.1、认识

ssm 是 spring mvc,spring,mybatis 的集合,是标准的 mvc 模式,将整个系统划分成为表现层,controller 层,service 层,dao 层共四层。
spring mvc 负责请求的转发与视图管理
spring 负责业务对象管理
mybatis 作为数据对象的持久化引擎

1.2、优点

1.2.1、Spring 的优势:

通过 Spring 的 IOC 特性,将对象之间的依赖关系交给了 Spring 控制,方便解耦,简化了开发
             通过 Spring 的 AOP 特性,对重复模块进行集中,实现事务,日志,权限的控制
             提供了对其他优秀开源框架的集成支持

1.2.2、Spring MVC 的优势:

SpringMVC 是使用了 MVC 设计思想的轻量级 web 框架,对 web 层进行解耦,使我们开发更简洁
             与 Spring 无缝衔接
             灵活的数据验证,格式化,数据绑定机制

1.2.3、Mybatis 的优势:

数据库的操作(sql)采用 xml 文件配置,解除了 sql 和代码的耦合
            提供映射标签,支持对象和和数据库 orm 字段关系的映射,支持对象关系映射标签,支持对象关系的组建
            提供了 xml 标签,支持动态的 sql

2、整合案例

2.1、之前

在进行 ssm 整合时,需要建立 maven web 项目
建立之后,首先将 spring 与 mybatis 整合在一起,在将 spring mvc 整合进去。添加一些文件。
spring 与 mybatis 的整合办法请看spring-mybatis
这里主要是将 spring mvc 整合进去。

2.2、新增依赖包

这些包是在原有的基础上新增加的包。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.13</version>
</dependency>
<dependency>
<artifactId>org.springframework</artifactId>
<groupId>spring-aspects</groupId>
<version>3.2.7.RELEASE</version>
</dependency>
<dependency>
<artifactId>org.springframework</artifactId>
<groupId>spring-context</groupId>
<version>3.2.7.RELEASE</version>
</dependency>
<dependency>
<artifactId>org.springframework</artifactId>
<groupId>spring-context-support</groupId>
<version>3.2.7.RELEASE</version>
</dependency>
<dependency>
<artifactId>org.springframework</artifactId>
<groupId>spring-web</groupId>
<version>3.2.7.RELEASE</version>
</dependency>
<dependency>
<artifactId>org.springframework</artifactId>
<groupId>spring-webmvc</groupId>
<version>3.2.7.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>

2.3、controller 层

采用未使用注解方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import bean.LinBook;
import service.ILinBookService;
public class LoginController implements Controller {
ILinBookService linBookService;
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-mybatis.xml");
linBookService = (ILinBookService) applicationContext.getBean("ILinBookService");
int id = Integer.parseInt(request.getParameter("id"));
LinBook linBook = linBookService.getLinBook(id);
ModelAndView mve = new ModelAndView();
mve.addObject("linbook", linBook.getBookId());
mve.setViewName("index");
return mve;
}
}

2.4、前端页面

index.jsp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" import="java.util.*"%> <%@ taglib
uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <%@ page
isELIgnored="false"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Insert title here</title>
</head>
<body>
<h1>输入用户:${linbook }</h1>
</body>
</html>

login.jsp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Insert title here</title>
</head>
<body>
<form action="login.do" method="post">
<table>
<tr>
<td>id:</td>
<td><input type="text" name="id" /></td>
</tr>
<tr>
<td>班级</td>
<td><input type="text" name="clazz" /></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="提交" /></td>
</tr>
</table>
</form>
</body>
</html>

2.5、spring-mvc.xml

需要建立 spring mvc 配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!--避免IE执行AJAX时,返回JSON出现下载文件 -->
<bean id="mappingJacksonHttpMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/html;charset=UTF-8</value>
</list>
</property>
</bean>
<!-- 将url映射到具体的业务控制器 -->
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="login.do">login</prop>
</props>
</property>
</bean>
<bean id="login" class="controller.LoginController"></bean>
<!-- 配置视图解析器 -->
<!-- InternalResourceViewResolver:用于支持servlet,jsp的解析 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 当jsp模板需要使用jstl标签库时,需要配置,没有则不需要配置 -->
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"></property>
<!-- 查找视图页面的前缀和后缀 -->
<property name="prefix" value="/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
</beans>

2.6、web.xml

web 工程配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mybatis.xml</param-value>
</context-param>
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 防止Spring内存溢出监听器 -->
<listener>
<listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
</listener>
<!-- 前端控制器 -->
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>

2.7、测试

到此,就将 spring mvc,spring,mybatis 整合好了
测试时在浏览器输入网址 localhost:8080/ssm1/login.jsp 即可

3、其他

3.1、说明

整合也可以采用注解的方式

3.2、controller

对于 controller 使用注解@Controller
其中的方法采用注解@RequestMapping(value=”***“,method=RequestMethod.GET/POST)

1
2
3
4
5
6
7
@Controller
public class LinBookController {
private LinBookService linBookService;
@RequestMapping(value = "/toindex", method = RequestMethod.POST)
public ModelAndView toindex(HttpServletRequest request) {
}
}

3.3、修改 spring-mvc.xml

加入

1
2
3
4
5
6
7
8
9
10
11
12
13
<!-- 扩充了注解驱动,可以将请求参数绑定到控制器参数 -->
<mvc:annotation-driven />
<!-- 自动扫描该包,使SpringMVC认为包下用了@controller注解的类是控制器 -->
<context:component-scan base-package="controller" />
<mvc:default-servlet-handler />
<!-- 启动SpringMVC的注解功能,完成请求和注解POJO的映射 -->
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="mappingJacksonHttpMessageConverter" />
</list>
</property>
</bean>

删除

1
2
3
4
5
6
7
8
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="login.do">login</prop>
</props>
</property>
</bean>
<bean id="login" class="controller.LinBookController"></bean>

3.4、修改 web.xml 文件

加入

1
2
3
<!-- Spring监听器 --><listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener> -->

修改

1
2
3
4
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

不能配成

1
2
3
4
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>

3.5、问题

目前还无法完成对 controller 中的 service 实现注解注入,有待解决。

1、整合方式共有四种,这里总结了三种。

2、通用配置

2.1、依赖包:

在导依赖包时,不能导入

1
2
3
4
5
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm</artifactId>
<version>5.0.3</version>
</dependency>

此包,否则会报方法找不到的异常,其实是 jar 包中的类冲突。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.lin</groupId>
<artifactId>spring-mybatis</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<!-- spring -->
<dependency>
<artifactId>org.springframework</artifactId>
<groupId>spring-jdbc</groupId>
<version>3.2.7.RELEASE</version>
</dependency>
<dependency>
<artifactId>org.springframework</artifactId>
<groupId>spring-core</groupId>
<version>3.2.7.RELEASE</version>
</dependency>
<dependency>
<artifactId>org.springframework</artifactId>
<groupId>spring-context</groupId>
<version>3.2.7.RELEASE</version>
</dependency>
<dependency>
<artifactId>org.springframework</artifactId>
<groupId>spring-beans</groupId>
<version>3.2.7.RELEASE</version>
</dependency>
<dependency>
<artifactId>org.springframework</artifactId>
<groupId>spring-tx</groupId>
<version>3.2.7.RELEASE</version>
</dependency>
<dependency>
<artifactId>org.springframework</artifactId>
<groupId>spring-expression</groupId>
<version>3.2.7.RELEASE</version>
</dependency>
<dependency>
<artifactId>org.springframework</artifactId>
<groupId>spring-aop</groupId>
<version>3.2.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aopalliance</groupId>
<artifactId>com.springsource.org.aopalliance</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.12</version>
</dependency>
<!-- mybatis-spring桥接 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.2.2</version>
</dependency>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.2.6</version>
</dependency>
<!-- mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.8</version>
</dependency>
<!-- c3p0连接池 -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
<dependency>
<groupId>com.mchange</groupId>
<artifactId>mchange-commons-java</artifactId>
<version>0.2.15</version>
</dependency>
<dependency>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
<version>1.1</version>
</dependency>
</dependencies>
</project>

2.2、spring-mybatis.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/jdbc
http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 开启spring注解扫描 -->
<context:component-scan base-package="service"></context:component-scan>
<!-- 配置数据源,使用c3p0连接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://192.168.20.40:3306/swan?characterEncoding=utf-8"></property>
<property name="user" value="devswan"></property>
<property name="password" value="DEVswan123!"></property>
</bean>
</beans>

2.3、Service 接口

1
2
3
4
5
package service;
public interface ILinBookService {
LinBook getLinBook();
void addBook(LinBook linBook);
}

2.4、实体类

1
2
3
4
5
6
7
package bean;
public class LinBook {
private int bookId;
private String bookName;
private int bookNum;
private String bookCategory;
}

2.5、测试类

1
2
3
4
5
6
7
8
9
10
11
12
13
public class JTest {
ILinBookService bean =null;
@Before
public void fun() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-mybatis.xml");
bean = (ILinBookService) applicationContext.getBean("ILinBookService");
}
@Test
public void fun1() {
LinBook linBook2 = bean.getLinBook();
System.out.println(linBook2);
}
}

3、第一种:使用 org.mybatis.spring.mapper.MapperScannerConfigurer

3.1、创建 sqlSessionFactory

1
2
3
4
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="mapperLocations" value="dao/ILinBook.xml"></property>
</bean>

3.2、sqlSession

1
2
3
4
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="dao" />
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
</bean>

3.3、ILinBook.xml 文件

1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="dao.ILinBook">
<select id="getBookById" parameterType="Integer" resultType="bean.LinBook" statementType="PREPARED">
select * from linbook where bookid=#{v}
</select>
<insert id="addLinBook" parameterType="bean.LinBook">
insert into linbook values(#{bookId},#{bookName},#{bookNum},#{bookCategory})
</insert>
</mapper>

3.4、Service 类

1
2
3
4
5
6
7
8
9
10
11
12
13
package service;
@Component("ILinBookService")
public class LinBookService implements ILinBookService {
// MapperScannerConfigurer
@Resource
private ILinBook ilinbook;
public LinBook getLinBook() {
return ilinbook.getBookById(1);
}
public void addBook(LinBook linBook) {
ilinbook.addLinBook(linBook);
}
}

3.5、Dao 层接口

1
2
3
4
5
6
package dao;
@MapperScan
public interface ILinBook {
LinBook getBookById(int bookId);
void addLinBook(LinBook linBook);
}

4、第二种:采用 org.mybatis.spring.mapper.MapperFactoryBean

4.1、创建 sqlSessionFactory

1
2
3
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
</bean>

4.2、sqlSession

1
2
3
4
<bean id="ILinBook" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="dao.ILinBook" />
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>

4.3、Service 类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package service;
@Component("ILinBookService")
public class LinBookService implements ILinBookService {
// MapperFactoryBean
@Resource
private ILinBook ilinbook;
public LinBook getLinBook() {
return ilinbook.getBookById(1);
}
// @Transactional(rollbackFor=Throwable.class)
public void addBook(LinBook linBook) {
ilinbook.addLinBook(linBook);
}
}

4.4、Dao 层接口

1
2
3
4
5
6
7
8
package dao;
@MapperScan
public interface ILinBook {
// 注解用于第二种,不需要xml文件
@Select("select * from linbook where bookid=#{v}")
LinBook getBookById(@Param("v") int bookId);
void addLinBook(LinBook linBook);
}

5、第三种:采用 org.mybatis.spring.SqlSessionTemplate

5.1、创建 sqlSessionFactory

1
2
3
4
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="mapperLocations" value="dao/ILinBook.xml"></property>
</bean>

5.2、sqlSession

1
2
3
<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory"></constructor-arg>
</bean>

5.3、ILinBook.xml

1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="dao.ILinBook">
<select id="getBookById" parameterType="Integer" resultType="bean.LinBook" statementType="PREPARED">
select * from linbook where bookid=#{v}
</select>
<insert id="addLinBook" parameterType="bean.LinBook">
insert into linbook values(#{bookId},#{bookName},#{bookNum},#{bookCategory})
</insert>
</mapper>

5.4、Service 类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package service;
@Component("ILinBookService")
public class LinBookService implements ILinBookService {
// SqlSessionTemplate
@Resource
private SqlSessionTemplate sqlSessionTemplate;
public LinBook getLinBook() {
//以下二选一
return sqlSessionTemplate.getMapper(ILinBook.class).getBookById(1);
return sqlSessionTemplate.selectOne("dao.ILinBook.getBookById", 1);
}
// @Transactional(rollbackFor=Throwable.class)
public void addBook(LinBook linBook) {
ilinbook.addLinBook(linBook);
}
}

5.5、Dao 层接口

1
2
3
4
5
6
package dao;
@MapperScan
public interface ILinBook {
LinBook getBookById(int bookId);
void addLinBook(LinBook linBook);
}

6、总结

三种方式采用不同的 spring 提供的工厂,生成 sqlSession,使得集成后的 spring 和 mybatis 中,mybatis 又将一些东西交由 spring 管理。

6.1、事务

6.1.1、spring-mybatis.xml

加入

1
2
3
4
<!-- 配置事务控制器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>

6.1.2、不使用注解时

1
2
3
4
5
6
7
8
9
10
11
12
13
<!-- 不使用注解,aop控制事务 -->
<tx:advice id="iccardTxAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!-- read-only:只读事务,事务中没有对数据库修改,mysql会进行优化 -->
<!-- propagetion:事务传播, -->
<tx:method name="add*" rollback-for="java.lang.Exception" read-only="false" propagation="REQUIRED" />
</tx:attributes>
</tx:advice>
<!-- 把事务控制在service层 -->
<aop:config>
<aop:pointcut id="iccardTerm" expression="execution(public * service.*.*(..))" />
<aop:advisor pointcut-ref="iccardTerm" advice-ref="iccardTxAdvice" />
</aop:config>

6.1.3、使用注解时

1
2
<!-- 使用注解事务 -->
<tx:annotation-driven transaction-manager="transactionManager" />

需要在 service 中的方法上加入注解,如:
rollbackFor 是回滚情况

1
2
3
4
@Transactional(rollbackFor=Throwable.class)
public void addBook(LinBook linBook) {
ilinbook.addLinBook(linBook);
}

1.Spring mvc

1.1、概念

spring mvc 是一个基于 java 实现了 web mvc 的轻量级 web 框架。

1.2、优点

简单,容易上手
灵活,容易扩展
性能优异

1.3、处理流程

2、spring mvc 入门案列

2.1、说明

spring mvc 案例需要建立的是 maven web 项目

2.1、依赖包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<artifactId>org.springframework</artifactId>
<groupId>spring-aop</groupId>
<version>3.2.7.RELEASE</version>
</dependency>
<dependency>
<artifactId>org.springframework</artifactId>
<groupId>spring-aspects</groupId>
<version>3.2.7.RELEASE</version>
</dependency>
<dependency>
<artifactId>org.springframework</artifactId>
<groupId>spring-beans</groupId>
<version>3.2.7.RELEASE</version>
</dependency>
<dependency>
<artifactId>org.springframework</artifactId>
<groupId>spring-context</groupId>
<version>3.2.7.RELEASE</version>
</dependency>
<dependency>
<artifactId>org.springframework</artifactId>
<groupId>spring-context-support</groupId>
<version>3.2.7.RELEASE</version>
</dependency>
<dependency>
<artifactId>org.springframework</artifactId>
<groupId>spring-core</groupId>
<version>3.2.7.RELEASE</version>
</dependency>
<dependency>
<artifactId>org.springframework</artifactId>
<groupId>spring-expression</groupId>
<version>3.2.7.RELEASE</version>
</dependency>
<dependency>
<artifactId>org.springframework</artifactId>
<groupId>spring-web</groupId>
<version>3.2.7.RELEASE</version>
</dependency>
<dependency>
<artifactId>org.springframework</artifactId>
<groupId>spring-webmvc</groupId>
<version>3.2.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aopalliance</groupId>
<artifactId>com.springsource.org.aopalliance</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
<version>1.1</version>
</dependency>
<!-- jstl标签包 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>

2.3、controller 层

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
public class LoginController implements Controller {
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
String username = request.getParameter("username");
ModelAndView mve = new ModelAndView();
mve.addObject("username", username);
mve.setViewName("index");
return mve;
}
}

2.4、spring mvc 配置文件

spring 建议命名规则****-servlet.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- 将url映射到具体的业务控制器 -->
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="login.do">login</prop>
</props>
</property>
</bean>
<bean id="login" class="controller.LoginController"></bean>
<!-- 配置视图解析器 -->
<!-- InternalResourceViewResolver:用于支持servlet,jsp的解析 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 当jsp模板需要使用jstl标签库时,需要配置,没有则不需要配置 -->
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"></property>
<!-- 查找视图页面的前缀和后缀 -->
<property name="prefix" value="/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
</beans>

2.5、web.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<!-- spring mvc提供了防止乱码的过滤器 -->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 前端控制器 -->
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 默认情况下,DispatcherServlet会寻找WEB-INF下命名规范为[servlet-name]-servlet.xml的文件。 -->
<!-- 如果需要修改,就需要在servlet中添加<init-param></init-param> -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>

2.6、前端页面

login.jsp、一个简单的表单

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<body>
<form action="login.do" method="post">
<table>
<tr>
<td>用户名:</td>
<td><input type="text" name="username" /></td>
</tr>
<tr>
<td>班级</td>
<td><input type="text" name="clazz" /></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="提交" /></td>
</tr>
</table>
</form>
</body>

index.jsp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" import="java.util.*"%>
<!-- 导入jstl标签库 -->
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!-- 开启el表达式 -->
<%@ page isELIgnored="false"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Insert title here</title>
</head>
<body>
<h1>输入用户:${username }</h1>
</body>
</html>

2.7、测试及结果


1、spring

1.1、概念

spring 是一个轻量级 java 开源框架,有着去耦合的作用。

1.2、优点

spring 就是一个大容器,可以将对象创建和依赖关系交给 spring 管理。Spring 默认单例。
spring 支持面向切面编程。支持事务管理,仅需要简单的配置。方便集成各种开源框架。
spring 封装了很多难以使用的 java Apl,降低了使用难度。

1.3、结构

2、spring 入门案列

2.1、依赖 jar 包

maven 工程,pom.xml 文件

2.2、实体类 Book

2.3、Service 接口及实现类

2.4、Dao 接口及实现类


2.5、配置文件

2.6、spring 容器不仅可以管理 bean,还可以对 bean 的属性进行各种参数注入,装配 bean,如下配置:

2.7、测试类

2.8、结果

3、基于注解

spring 可以使用注解替换 xml 中 bean 的配置,进行 bean 的管理

3.1、配置

1
<context:component-scan base-package="~~~~~"></context:component-scan>

3.2、替换规则

3.2.1、

使用@Component(“~~~~~”)替换,通用于 Dao,Service,等。

3.2.2、

@Component 有三个衍生注解@Service,用于 Service 层;@Repository,用于 Dao 层;@Controller,用于 view。

3.2.3、

使用@Autowired,按照类型进行注入

3.2.4、

@Autowired,@Qualifier(“~~~~~”)组合使用,按照名称注入

3.2.5、

@Value(“~~~~~”)可进行值的注入

1、MyBatis

1.1、概念

MyBatis 是一个开源的持久层的框架。

1.2、优点

使用 xml 文件将一些参数配置起来,将 jdbc 过程封装起来,使开发者只关注 sql 本身。
程序员自己编写 sql 语句,可控制 sql 语句性能,灵活性高。
使用数据库连接池,解决了 jdbc 频繁连接对数据库资源的浪费。
MyBatis 将 sql 语句配置在 xml 文件中,并将 java 对象和 sql 语句映射生成最终执行的 sql 语句。
解决了原来将 sql 语句写在 java 代码中的硬编码问题。
与 Hibernate 相比,不用考虑复杂的实体间关系问题。

1.3、缺点

不能象 Hibernate 一样自动生成 sql 语句,开发人员工作量大。
数据库无关性差,不能像 Hibernate 一样只需要换驱动,MyBatis 需要重写 sql 语句。

1.4、结构


2、入门案例

2.1、依赖包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
<dependencies>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.2.7</version>
</dependency>
<!-- mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.8</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
</dependency>
<!-- 日志 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.7</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.7</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.6</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.6</version>
</dependency>

<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.1</version>
</dependency>
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.18.2-GA</version>
</dependency>
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm</artifactId>
<version>5.0.3</version>
</dependency>
</dependencies>

2.2、数据库表

1
2
3
4
5
6
7
CREATE TABLE `linbook` (
`bookid` int(11) NOT NULL,
`bookname` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`booknum` int(11) NULL DEFAULT NULL,
`bookcategory` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`bookid`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;

2.3、实体类

1
2
3
4
5
6
public class LinBook {
private Integer BookId;
private String BookName;
private Integer BookNum;
private String BookCategory;
}

2.4、Dao 层接口

接口动态开发,可不使用该种开发方法,此方式实现类由动态代理生成。
此种方式要求 BookDao.xml 文件与接口位于同一包下,且文件名相同。
xml 文件中的每一个 sql 语句标签和接口中的一个方法对应。其标签 id 和接口中的方法名相同。
xml 文件中的 namespace 的值与接口全类名相同。

1
2
3
4
5
6
7
8
9
10
11
public interface BookDao {
//使用注解等同于下面的xml文件配置
@Select("select * from linbook where bookid=#{v}")
LinBook getBookById(@Param("v")int bookId);
public LinBook findBookById(Integer id);
public List<LinBook> findBookByName(String name);
public void insertBook(LinBook linbook);
public void updateBook(LinBook linbook);
public void deleteBook(LinBook linbook);
public int count();
}

2.5、BookDao.xml,该 xml 中配置 sql 语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace:命名空间,用于隔离sql, 命名空间 user.findUserById -->
<mapper namespace="com.lin.dao.BookDao">
<!-- resultMap:定义结果集映射,result:一列 -->
<resultMap type="com.lin.bean.LinBook" id="LinBookResultMap" >
<!-- id:主键;property:主键,column:列名 -->
<id property="BookId" column="bookid" />
<result property="BookNum" column="booknum" />
<result property="BookName" column="bookname" />
<result property="BookCategory" column="bookcategory" />
</resultMap>
<!-- parameterMap :定义参数集映射 -->
<parameterMap type="com.lin.bean.LinBook" id="BookParameterMap">
<parameter property="bookId" resultMap="LinBookResultMap" />
<parameter property="bookNum" resultMap="LinBookResultMap" />
<parameter property="bookName" resultMap="LinBookResultMap" />
<parameter property="bookCategory" resultMap="LinBookResultMap" />
</parameterMap>
<!-- 配置sql语句,parameterType:参数类型;resultType:返回值类型 -->
<!-- #{}:占位符,传入的是值类型或者pojo,不会导致sql注入 -->
<!-- ${}:用于字符串拼接,不会转义,会导致潜在的sql注入,不推荐使用。 -->
<!-- parameterType:参数类型。resultType:返回值类型。statementType:statement类型,STATEMENT,PREPARED,CALLABLE,默认值CALLABLE -->
<!-- useGeneratedKeys="true" keyProperty="id" :配合设置自增主键 -->
<select id="findBookById" parameterType="Integer" resultMap="LinBookResultMap" statementType="PREPARED">
select * from linbook where bookid=#{v}
</select>
<select id="findBookByName" parameterType="String" resultType="com.lin.bean.LinBook">
select * from linbook where bookname like "%"#{v}"%"
</select>
<insert id="insertBook" parameterType="com.lin.bean.LinBook">
insert into linbook values(#{BookId},#{BookName},#{BookNum},#{BookCategory})
</insert>
<update id="updateBook" parameterType="com.lin.bean.LinBook">
update linbook set bookname=#{BookName} where bookid=#{BookId}
</update>
<delete id="deleteBook" parameterType="com.lin.bean.LinBook">
delete from linbook where bookid=#{BookId}
</delete>
<select id="count" resultType="java.lang.Integer">
select count(*) from linbook
</select>
</mapper>

同时可以在其中为 sql 语句配置超时时间,需要在 sqlMapConfig.xml 文件中,加入一段;
也可以在每个 sql 语句标签中独立配置,使用 timeout 属性。

1
2
3
<select id="count" resultType="java.lang.Integer" timeout="10000" >
select count(*) from linbook
</select>

2.6、sqlMapConfig.xml 配置文件,位于项目根目录下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 此处为全局属性配置 -->
<settings>
<!-- 配置sql语句默认超时时间 -->
<setting name="defaultStatementTimeout" value="10000" />
</settings>
<environments default="development">
<environment id="development">
<!-- 事务管理 -->
<!-- JDBC:使用jdbc提供的事务控制 -->
<!-- MANAGE:使用容器提供的事务控制,MyBatis自己不提供事务控制 -->
<transactionManager type="JDBC" />
<!-- 数据库连接池 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://192.168.20.40:3306/swan?characterEncoding=utf-8" />
<property name="username" value="devswan" />
<property name="password" value="DEVswan123!" />
</dataSource>
</environment>
</environments>
<!-- 引入sql语句映射 -->
<mappers>
<!-- 三种方式,任选其一 -->
<mapper resource="com/lin/dao/BookDao.xml" />
<!-- 批量加载该包下的所有映射文件,且文件名与接口名相同,位于同一位置 -->
<!-- <package name="com.lin.dao" /> -->
<!-- 要求文件名与接口名相同,位于同一位置 -->
<!-- <mapper class="com.lin.dao.BookDao" /> -->
</mappers>
</configuration>

2.7、日志配置

1
2
3
4
5
6
# Global logging configuration
log4j.rootLogger=DEBUG, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

2.8、测试类

有两种方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Test
public void testMybatis1() {
String resource = "sqlMapConfig.xml";
try {
//以流的方式拿到配置文件
InputStream resourceAsStream = Resources.getResourceAsStream(resource);
//创建SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
//创建SqlSession
SqlSession session = sqlSessionFactory.openSession();
//~~1~~执行Sql语句
LinBook book = session.selectOne("com.lin.dao.BookDao.findBookById", 1);
//~~2~~拿到Dao层对象,调用方法执行sql语句
BookDao bookDao = session.getMapper(BookDao.class);
LinBook Book = bookDao.findBookById(1);
//更新,插入,删除操作后需要进行事务提交
session.commit();
System.out.println(book);
} catch (IOException e) {
e.printStackTrace();
}
}

第一种方式:来源于 MyBatis 的前身 iBatis
第二种方式:getMapper()方法,通过动态代理的方法,拿到接口的实例,再调用方法。

Mybatis 多表关系

mybatis 中多表关联,主要修改 mapper.xml 文件和 eitity 实体。
mapper.xml 文件中通过 resultmap 配置返回映射,eitity 实体中通过对象引用定义关系。
spring-mybatis.xml 文件与 pom.xml 文件与spring-mybatis中相同,选择其中第一种整合方式。

1、数据库执行脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for item
-- ----------------------------
DROP TABLE IF EXISTS `item`;
CREATE TABLE `item` (
`itemid` int(11) NOT NULL AUTO_INCREMENT,
`itemname` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
PRIMARY KEY (`itemid`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of item
-- ----------------------------
INSERT INTO `item` VALUES (1, '里斯');
INSERT INTO `item` VALUES (2, '嗡嗡嗡');
INSERT INTO `item` VALUES (3, '迭代');
-- ----------------------------
-- Table structure for order
-- ----------------------------
DROP TABLE IF EXISTS `order`;
CREATE TABLE `order` (
`orderid` int(11) NOT NULL,
`userid` int(11) NULL DEFAULT NULL,
PRIMARY KEY (`orderid`) USING BTREE,
INDEX `userid`(`userid`) USING BTREE,
CONSTRAINT `userid` FOREIGN KEY (`userid`) REFERENCES `user` (`userid`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of order
-- ----------------------------
INSERT INTO `order` VALUES (1, 1);
-- ----------------------------
-- Table structure for orderitem
-- ----------------------------
DROP TABLE IF EXISTS `orderitem`;
CREATE TABLE `orderitem` (
`orderitemid` int(11) NOT NULL,
`orderid` int(11) NULL DEFAULT NULL,
`itemid` int(11) NULL DEFAULT NULL,
PRIMARY KEY (`orderitemid`) USING BTREE,
INDEX `orderid`(`orderid`) USING BTREE,
INDEX `itemid`(`itemid`) USING BTREE,
CONSTRAINT `itemid` FOREIGN KEY (`itemid`) REFERENCES `item` (`itemid`) ON DELETE RESTRICT ON UPDATE RESTRICT,
CONSTRAINT `orderid` FOREIGN KEY (`orderid`) REFERENCES `order` (`orderid`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of orderitem
-- ----------------------------
INSERT INTO `orderitem` VALUES (1, 1, 1);
INSERT INTO `orderitem` VALUES (2, 1, 2);
-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`userid` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
PRIMARY KEY (`userid`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (1, 'lin');
INSERT INTO `user` VALUES (2, '苏');
SET FOREIGN_KEY_CHECKS = 1;

2、数据模型分析,


用户表:user,记录了用户信息。
订单表:order,记录了用户的订单信息。
订单项表:orderitem,记录订单中,每个商品项的购买情况。
商品表:item,记录了商品信息。

2.1、表与表之间业务分析:

user 与 orer:
user—>order:一个用户可以创建多个订单
order—>user:一个订单只属于一个用户
order 与 orderitem:
order—>orderitem:一个订单包含多个订单项
orderitem—>order:一个订单项属于一个订单
orderitem 与 item:
orderitem—>item:一个订单项包含一个商品
item—>orderitem:一个商品可以属于多个订单项
user 与 item:
user—>item:一个用户可以购买多个商品
item—>user:一个商品被多个用户购买
画出图:

3、实体类

1、user.java

1
2
3
4
5
public class User {
private Integer userId;
private String userName;
// 外键引用,一个用户可以创建多个订单 private List<Order> orders;
}

2、order.java

1
2
3
4
5
public class Order {
private Integer orderId;
// 一个订单包含多个订单项 private List<OrderItem> orderItems;
// 一个订单属于一个用户 private User user;
}

3、orderitem.java

1
2
3
4
5
public class OrderItem {
private Integer orderItemId;
// 一个订单项属于一个订单 private Order order;
// 一个订单项包含一个商品 private Item item;
}

4、item.java

1
2
3
4
public class Item {
private Integer itemId;
private String itemName;
}

4、Service 及 Dao

接口 UserDao:

1
2
3
4
5
@MapperScan
public interface UserDao {
User findUserById(User user);
User findUserAndOrderById(User user);
}

接口 UserService:

1
2
3
4
public interface UserService {
User findUserById(User user);
User findUserAndOrderById(User user);
}

实现类 UserServiceImpl:

1
2
3
4
5
6
7
8
9
10
11
@Component("UserService")
public class UserServiceImpl implements UserService {
@Resource
private UserDao userdao;
public User findUserById(User user) {
return userdao.findUserById(user);
}
public User findUserAndOrderById(User user) {
return userdao.findUserAndOrderById(user);
}
}

5、多表关系

多表关系主要用于查询,mybatis 中在 mapper.xml 文件中配置 resultMap 来配置多表关系,用于返回映射。
mapper.xml 中配置了一对一,一对多,多对多关系。
userMapper.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-// mybatis.org//DTD Mapper 3.0//EN"
" http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.lin.dao.UserDao">
<!-- 配置一对一,一对多,多对一关系时,实体类中在双方加入引用,配置文件中在一方加入即可 --> <!-- collection:表示一对多关系,实体类中通常用集合表示 --> <!-- ofType:一对多中,多的实体类型 --> <!-- association:表示一对一关系,实体类中为引用 --> <!-- javaType:一对一中另一个一的实体类型 --> <!-- 将多对多关系,可以拆分成2个一对多关系,与数据库表一样 --> <!-- 用户 --> <resultMap type="com.lin.bean.User" id="UserResultMap">
<id property="userId" column="userid" />
<result property="userName" column="username" />
<!-- 一个用户拥有多个订单,表示一对多关系 --> <collection property="orders" ofType="com.lin.bean.Order" fetchType="lazy">
<!-- 订单和商品为多对多关系,将其拆分为订单,订单项,商品三张表 --> <!-- 1、一个订单包含多个订单项 - --> <!-- 2、一个订单项包含一个商品 --> <!-- 3、一个订单项属于一个订单 - --> <!-- 4、一个商品属于多个订单项(商品中不添加订单项的引用) --> <!-- 采用1和2可完成多对多的配置 --> <id property="orderId" column="orderid" />
<!-- 每个订单中包含多个订单项,一对多关系 --> <collection property="orderItems" fetchType="lazy" ofType="com.lin.bean.OrderItem">
<id property="orderItemId" column="orderitemid" />
<!-- 每个订单项包含一个商品,一对一关系 --> <!-- 嵌套结果方式 --> <!-- <association property="item" javaType="com.lin.bean.Item"> <id property="itemId"
column="itemid" /> <result property="itemName" column="itemname" /> </association> -->
<!-- 嵌套查询方式 --> <!-- column:外键字段名称:select语句参数 --> <association property="item" javaType="com.lin.bean.Item" column="itemid" select="findItemById"></association>
</collection>
</collection>
</resultMap>
<select id="findItemById" parameterType="integer" resultType="com.lin.bean.Item">
select itemid,itemname from item where itemid=#{v}
</select>
<select id="findUserAndOrderById" parameterType="com.lin.bean.User" resultMap="UserResultMap">
select
u.userid,u.username,o.orderid,or.orderitemid,i.itemid,i.itemname from
user u,`order` o,orderitem `or`,item i where o.userid=u.userid and
o.orderid=or.orderid and i.itemid=or.itemid;
</select>
<select id="findUserById" parameterType="com.lin.bean.User" resultType="com.lin.bean.User">
select * from user where userid = #{userId}
</select>
</mapper>

6、测试

1
2
3
4
5
6
7
8
9
10
11
public class App {
public static void main(String[] args) {
User user = new User();
user.setUserId(1);
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-mybatis.xml");
UserService userServie = (UserService) applicationContext.getBean("UserService");
System.out.println(userServie.findUserById(user));
System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
System.out.println(userServie.findUserAndOrderById(user));
}
}

7、结果

LinkedList 原理与源码解析

1、原理

2、源码解析

2.1、构造方法

1
2
3
//空参构造方法
public LinkedList() {
}

2.2、linkFirst 方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
private void linkFirst(E e) {
final Node<E> f = first;
//构造新节点
final Node<E> newNode = new Node<>(null, e, f);
//链表头节点为新节点
first = newNode;
//后继为空,即链表插入后只有一个元素,那么尾节点也是新节点
if (f == null)
last = newNode;
else
f.prev = newNode;
size++;
modCount++;
}

2.3、linkLast 方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void linkLast(E e) {
final Node<E> l = last;
//构造新节点
final Node<E> newNode = new Node<>(l, e, null);
//新节点为尾节点
last = newNode;
//原链表为空时,新节点也为头节点
if (l == null)
first = newNode;
else
//不为空时,将新节点加在原链表后面
l.next = newNode;
size++;
modCount++;
}

2.4、linkBefore 方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//往某节点前插入元素
void linkBefore(E e, Node<E> succ) {
// assert succ != null;
//查出前驱节点
final Node<E> pred = succ.prev;
//构造新节点
final Node<E> newNode = new Node<>(pred, e, succ);
//某节点之前为新节点
succ.prev = newNode;
//往链表头部插入
if (pred == null)
first = newNode;
else
//新节点加入前驱节点后面
pred.next = newNode;
size++;
modCount++;
}

2.5、unlinkFirst 方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
private E unlinkFirst(Node<E> f) {
// assert f == first && f != null;
//获取要删除的节点得值
final E element = f.item;
//获取要删除的节点的后继节点
final Node<E> next = f.next;
f.item = null;
f.next = null; // help GC
//后继节点设置为头节点
first = next;
//链表只有一个元素时,无后继节点
if (next == null)
last = null;
else
next.prev = null;
size--;
modCount++;
return element;
}

2.6、unlinkLast 方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
private E unlinkLast(Node<E> l) {
// assert l == last && l != null;
//获取要删除的节点的值
final E element = l.item;
//获取到倒数第二个节点
final Node<E> prev = l.prev;
l.item = null;
l.prev = null; // help GC
//倒数第二个设置为为节点
last = prev;
//删除后链表为空的情况
if (prev == null)
first = null;
else
prev.next = null;
size--;
modCount++;
return element;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
E unlink(Node<E> x) {
// assert x != null;
//获取到要删除的节点
final E element = x.item;
//获取到后继节点
final Node<E> next = x.next;
//获取到前驱节点
final Node<E> prev = x.prev;
//删除的是头节点的情况
if (prev == null) {
first = next;
} else {
//前驱的后继设置为后继
prev.next = next;
x.prev = null;
}
//删除的是尾节点的情况
if (next == null) {
last = prev;
} else {
//后继的前驱设置为前驱
next.prev = prev;
x.next = null;
}
x.item = null;
size--;
modCount++;
return element;
}