# spring-learn
**Repository Path**: hrbu-2022/spring-learn
## Basic Information
- **Project Name**: spring-learn
- **Description**: spring-learn
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2025-03-07
- **Last Updated**: 2025-03-13
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# 使用XML方式管理Bean
- 添加依赖
- 工厂的配置文件 spring-bean.xml
- 创建一个Bean(DeptDao)
- 将DeptDao 配置到工厂中,用于创建对象
- 从工厂中获取 DeptDao
## 添加依赖
spring-01-xml-helloworld
```xml
4.0.0
com.neuedu.spring
spring-01-xml-helloworld
1.0-SNAPSHOT
17
17
5.3.39
junit
junit
4.13.1
test
org.springframework
spring-beans
${spring.version}
org.springframework
spring-context
${spring.version}
org.springframework
spring-core
${spring.version}
org.springframework
spring-expression
${spring.version}
```
## 工厂的配置文件 spring-beans.xml
resoueces/spring-beans.xml
```xml
```
## 创建一个Bean(DeptDao)
```java
package com.neuedu.spring.dao;
/**
* @author 金山
* 项目:spring-learn
* site: https://blog.fulfill.com.cn
* 描述
* @data 2025/3/714:05
*/
public class DeptDao {
public void selectList(){
System.out.println("Dao的查询方法");
}
}
```
## 将DeptDao 配置到工厂中,用于创建对象
```xml
```
从工厂中获取 DeptDao
```java
package com.neuedu.spring.dao;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author 金山
* 项目:spring-learn
* site: https://blog.fulfill.com.cn
* 描述
* @data 2025/3/714:08
*/
public class SpringTest {
@Test
public void test(){
String configLocation = "spring-beans.xml";
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(configLocation);
//从容器中后去一个对象
// DeptDao deptDao = (DeptDao) context.getBean("deptDao");
DeptDao deptDao = context.getBean("deptDao",DeptDao.class);
//调用方法
deptDao.selectList();
}
}
```
## 依赖注入
DeptService 依赖于 DeptDao ,传统的方式 自己new , 使用Spring的方式 则需要用到依赖注入 维护 依赖的关系
```java
package com.neuedu.spring.service;
import com.neuedu.spring.dao.DeptDao;
/**
* @author 金山
* 项目:spring-learn
* site: https://blog.fulfill.com.cn
* 描述
* @data 2025/3/714:52
*/
public class DeptService {
DeptDao deptDao;
public void queryList(){
System.out.println("service");
deptDao.selectList();
}
public void setDeptDao(DeptDao deptDao) {
this.deptDao = deptDao;
}
}
```

### spring-beans.xml 工厂配置文件
```xml
```

测试
```java
package com.neuedu.spring.dao;
import com.neuedu.spring.service.DeptService;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author 金山
* 项目:spring-learn
* site: https://blog.fulfill.com.cn
* 描述
* @data 2025/3/714:08
*/
public class SpringTest {
@Test
public void test(){
String configLocation = "spring-beans.xml";
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(configLocation);
//从容器中获取一个对象
// DeptDao deptDao = (DeptDao) context.getBean("deptDao");
DeptService deptService = context.getBean("deptService", DeptService.class);
DeptDao deptDao = context.getBean("deptDao",DeptDao.class);
deptService.queryList();
//调用方法
// deptDao.selectList();
}
}
```

### 构造方法注入
### 依赖注入的数据类型
- 自定义的数据类型
- List、Map、String、int、Set
```java
package com.neuedu.spring.dao;
import com.neuedu.spring.po.Dept;
import java.util.List;
import java.util.Map;
/**
* @author 金山
* 项目:spring-learn
* site: https://blog.fulfill.com.cn
* 描述
* @data 2025/3/714:05
*/
public class DeptDao {
//String 类型
private String url;
private String username;
private Map mapInfo;
private List infoList;
private List deptList;
public void selectList(){
System.out.println("Dao的查询方法");
System.out.println(url);
System.out.println(username);
System.out.println("mapInfo = " + mapInfo);
infoList.forEach(System.out::println);
System.out.println("-------------------------------------------------");
deptList.forEach(System.out::println);
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Map getMapInfo() {
return mapInfo;
}
public void setMapInfo(Map mapInfo) {
this.mapInfo = mapInfo;
}
public List getInfoList() {
return infoList;
}
public void setInfoList(List infoList) {
this.infoList = infoList;
}
public List getDeptList() {
return deptList;
}
public void setDeptList(List deptList) {
this.deptList = deptList;
}
}
```
```xml
abc
def
```
# 包扫描的方式注册
- 原来使用 bean 标签 在xml中注册bean,会越来越多,可以使用注解\
1. 创建项目
2. 添加spirng的依赖
3. bean(DeptDao)
1. 在类上面添加注解 @Component bean对象的名字(ID) 就是类名的首字母小写
2. @Component("MyDeptDao") 可以使用value 值 自定义 Bean的名字
```java
package com.neuedu.spring.dao;
import org.springframework.stereotype.Component;
/**
* @author 金山
* 项目:spring-learn
* site: https://blog.fulfill.com.cn
* 描述
* @data 2025/3/714:05
*/
@Component
public class DeptDao {
public void selectList(){
System.out.println("Dao的查询方法");
}
}
```
4. 创建ioc容器 的配置文件 beans
5. 扫描包的方式注册Bean对象
```xml
```
## 使用注解的方式实现DI
- Autowired
- Resource
@Autowired:默认按照类型在Spring容器寻找对象,并注入到属性中。 所以此时要注意:UserDao接口的实现类只能有一个。
##### @Autowired和@Resource的区别:
1. @Autowired只按type装配,@Resource默认是按name装配
2. @Autowired和@Resource都可以用来装配bean,都可以写在字段或setter方法上
3. @Autowired默认按照类型装配,默认情况下必须要求依赖对象存在,如果要允许null值,可以设置它的required属性为false,如果想使用名称装配可以结合@Qualifier注解进行使用
@Resource默认安装名称装配,名称可以通过name属性进行指定,如果没有指 定name属性,当注解写在字段上时,默认取字段名进行名称查找,如果注解 写在setter方法上默认取属性名进行装配。当找不到与名称匹配的bean时才按 照类型进行装配。但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。
> 除了@Component这个泛指组件的注解外,Spring还提供了与@Component功能相同的三个语义化注解。
>
> 1. @Service 业务层组件
> 2. @Controller 控制层组件
> 3. @Repository 数据层组件
# Bean的作用范围
什么时机创建新对象
- xml
```
```
- 注解
- ```
@Scope("prototype")
```
# JavaConfig
javaConfig,是在 Spring 3.0 开始从一个独立的项目并入到 Spring 中的。javaConfig 可以看成一个用于完成 Bean 装配的 Spring 配置文件,即 Spring 容器,只不过该容器不是 XML文件,而是由程序员使用 java 自己编写的 java 类。
一个类中只要标注了@Configuration注解,这个类就可以为spring容器提供Bean定义的信息了,或者说这个类就成为一个spring容器了。
标注了@Configuration和标注了@Component的类一样是一个Bean,可以被Spring的 context:component-scan 标签扫描到。类中的每个标注了@Bean的方法都相当于提供了一个Bean的定义信息。
使用@Bean 声明Bean对象 默认的 bean 的ID 就是 方法名字(或者是通过@Bean("deptService") value值定义bean的名字),一般用于 声明第三方包、类库下的 Bean对象
```
@Configuration
@ComponentScan("com.neuedu.spirng")
public class MyJavaConifig {
//
/**
* @Bean 在容器中使用 注册一些 非自定义的类
* @return
*/
@Bean
public String appName(){
return new String("Spring");
}
}
```
### 
@Bean声明的Bean方法入参类型可以自动的从容器中获取对象
```
/**
* 在容器中 声明一个 DeptService
* @return
*/
@Bean("deptService")
public DeptService getDeptService(DeptDao deptDao){
return new DeptService(deptDao);
}
```
# BeanFactroy和ApplicationContext

获取Spring容器也可以使用BeanFactory接口。BeanFactory与ApplicationContext的区别是:
1. BeanFactory
Bean工厂(org.springframework.beans.factory.BeanFactory)是Spring框架最核心的接口,提供了IoC的配置机制,使管理不同类型的Java对象成为可能。特点是:采用延迟加载Bean,直到第一次使用Bean实例时才会创建Bean。
2. ApplicationContext
应用上下文(org.springframework.context.ApplicationContext),继承自BeanFactory,提供了更多面向应用的功能,比如国际化支持、框架事件体系,更易于创建实际应用。
应用时,我们一般称BeanFactory为IoC容器,ApplicationContext为应用上下文:
1. BeanFactory是Spring框架的基础设施,面向Spring本身;
2. ApplicationContext面向使用Spring框架的开发者;
3. 几乎所有的应用场合都可以直接使用ApplicationContext而非底层的BeanFactory;
# 单元测试
使用 Spring-Test库 实现单元测试
```xml
org.springframework
spring-test
${spring.version}
```
1. **@RunWith(SpringJUnit4ClassRunner.class)**
2. 使用SpringJUnit4ClassRunner扩展 juint


# AOP面相切面编程

想要在 com.neuedu.spirng.service.*xxxxService.insert
1. 执行之前 开启事务
2. 执行 xxxxService.insert方法
3. 提交事务
使用AOP框架 实际执行的时候 XXXService的代理对象
- UserService---Proxy(包含UserService.insert)
- 执行之前 开启事务
- 包含UserService.insert
- 提交事务
- DeptService---Proxy(包含DeptService.insert)
- 执行之前 开启事务
- 包含DeptService.insert
- 提交事务
## 连接点(Joinpoint)
连接点是在应用执行过程中能够插入切面的一个点,Spring仅支持方法的连接点,即仅能在方法调用前,方法调用后,方法抛出异常时及方法调用前后插入切面代码。 .
举例:如果在insert之前执行扩展(增强、通知),简单理解insert这个方法可以称之为连接点。
连接点: 1 Com.neuedu.service.UserService.insert()
连接点: 2 Com.neuedu.service.DeptService.insert()
## 切点(Pointcut)
execution(<修饰符模式>?<返回类型模式><方法名模式>(<参数模式>)<异常模式>?)
execution(public * com.neuedu.service.*Service.insert(); )
切点匹配:Com.neuedu.service.*Impl.insert(..);
表达式:
Execution表达式语法
execution(<修饰符模式>?<返回类型模式><方法名模式>(<参数模式>)<异常模式>?)
除了返回类型模式、方法名模式和参数模式外,其它项都是可选的。
execution(public * *(..))
匹配所有目标类的public方法,第一个*代表返回类型,第二个*代表方法名,而..代表任意入参的方法;
execution(* *To(..))
匹配目标类所有以To为后缀的方法,第一个*代表返回类型,而*To代表任意以To为后缀的方法;
execution(* com.neuedu.UserService.*(..))
匹配UserService接口的所有方法,第一个*代表返回任意类型,com.neuedu.UserService.*代表UserService接口中的所有方法;
execution(* com.neuedu.*(..))
匹配com.neuedu包下所有类的所有方法
execution(* com.neuedu..*(..))
匹配com.neuedu包、子孙包下所有类的所有方法,“..”出现在类名中时,后面必须跟“*”,表示包、子孙包下的所有类;
execution(* com..*.*Dao.find*(..))
匹配包名前缀为com的任何包下类名后缀为Dao的方法,方法名必须以find为前缀
一、execution:使用“execution(方法表达式)”匹配方法执行;
| 模式 | 描述 |
| -------------------------------------------------------- | ------------------------------------------------------------ |
| public * *(..) | 任何公共方法的执行 |
| * cn.javass..IPointcutService.*() | cn.javass包及所有子包下IPointcutService接口中的任何无参方法 |
| * cn.javass..*.*(..) | cn.javass包及所有子包下任何类的任何方法 |
| * cn.javass..IPointcutService.*(*) | cn.javass包及所有子包下IPointcutService接口的任何只有一个参数方法 |
| * (!cn.javass..IPointcutService+).*(..) | 非“cn.javass包及所有子包下IPointcutService接口及子类型”的任何方法 |
| * cn.javass..IPointcutService+.*() | cn.javass包及所有子包下IPointcutService接口及子类型的的任何无参方法 |
| * cn.javass..IPointcut*.test*(Java.util.Date) | cn.javass包及所有子包下IPointcut前缀类型的的以test开头的只有一个参数类型为java.util.Date的方法,注意该匹配是根据方法签名的参数类型进行匹配的,而不是根据执行时传入的参数类型决定的 |
| | 如定义方法:public void test(Object obj);即使执行时传入java.util.Date,也不会匹配的; |
| * cn.javass..IPointcut*.test*(..) throws | cn.javass包及所有子包下IPointcut前缀类型的的任何方法,且抛出IllegalArgumentException和ArrayIndexOutOfBoundsException异常 |
| IllegalArgumentException, ArrayIndexOutOfBoundsException | |
| * (cn.javass..IPointcutService+ | 任何实现了cn.javass包及所有子包下IPointcutService接口和java.io.Serializable接口的类型的任何方法 |
| && java.io.Serializable+).*(..) | |
| @java.lang.Deprecated * *(..) | 任何持有@java.lang.Deprecated注解的方法 |
| @java.lang.Deprecated @cn.javass..Secure * *(..) | 任何持有@java.lang.Deprecated和@cn.javass..Secure注解的方法 |
| @(java.lang.Deprecated \|\| cn.javass..Secure) * *(..) | 任何持有@java.lang.Deprecated或@ cn.javass..Secure注解的方法 |
| (@cn.javass..Secure *) *(..) | 任何返回值类型持有@cn.javass..Secure的方法 |
| * (@cn.javass..Secure *).*(..) | 任何定义方法的类型持有@cn.javass..Secure的方法 |
| * *(@cn.javass..Secure (*) , @cn.javass..Secure (*)) | 任何签名带有两个参数的方法,且这个两个参数都被@ Secure标记了, |
| | 如public void test(@Secure String str1, |
| | @Secure String str1); |
| * *((@ cn.javass..Secure *))或 | 任何带有一个参数的方法,且该参数类型持有@ cn.javass..Secure; |
| * *(@ cn.javass..Secure *) | 如public void test(Model model);且Model类上持有@Secure注解 |
| * *( | 任何带有两个参数的方法,且这两个参数都被@ cn.javass..Secure标记了;且这两个参数的类型上都持有@ cn.javass..Secure; |
| @cn.javass..Secure (@cn.javass..Secure *) , | |
| @ cn.javass..Secure (@cn.javass..Secure *)) | |
| * *( | 任何带有一个java.util.Map参数的方法,且该参数类型是以< cn.javass..Model, cn.javass..Model >为泛型参数;注意只匹配第一个参数为java.util.Map,不包括子类型; |
| java.util.Map | 如public void test(HashMap map, String str);将不匹配,必须使用“* *( |
| , ..) | java.util.HashMap |
| | , ..)”进行匹配; |
| | 而public void test(Map map, int i);也将不匹配,因为泛型参数不匹配 |
| * *(java.util.Collection<@cn.javass..Secure *>) | 任何带有一个参数(类型为java.util.Collection)的方法,且该参数类型是有一个泛型参数,该泛型参数类型上持有@cn.javass..Secure注解; |
| | 如public void test(Collection collection);Model类型上持有@cn.javass..Secure |
| * *(java.util.Set extends HashMap>) | 任何带有一个参数的方法,且传入的参数类型是有一个泛型参数,该泛型参数类型继承与HashMap; |
| | Spring AOP目前测试不能正常工作 |
| * *(java.util.List super HashMap>) | 任何带有一个参数的方法,且传入的参数类型是有一个泛型参数,该泛型参数类型是HashMap的基类型;如public voi test(Map map); |
| | Spring AOP目前测试不能正常工作 |
| * *(*<@cn.javass..Secure *>) | 任何带有一个参数的方法,且该参数类型是有一个泛型参数,该泛型参数类型上持有@cn.javass..Secure注解; |
| | Spring AOP目前测试不能正常工作 |
## 通知(Advice)、增强
- 前置通知
```java
开启识事务
connection.setAutoCommit(false)
```
- 后置通知
````java
commit()
````
等等
切面的工作被成为通知,定义了切面是什么及何时使用。除了描述切面要完成的工作,通知还解决了何时执行这个工作的问题,它应该在某个方法被调用之前?之后?等。
举例:额外定义一个方法想要在连接点上进行扩展的功能
#### Spring切面可以应用5种类型的通知:
前置通知(Before)在目标方法被调用之前调用通知功能;
后置通知(After)在目标方法被完成之后调用通知功能,不关心方法的输出是什么;
环绕通知(Around advice)通知包裹了目标方法,在目标方法调用之前和之后执行自定义的行为;
异常通知(After-throwing)在目标方法抛出异常后调用通知;
返回通知(After-returning)在目标方法成功执行之后调用通知;
## 切面
将 切点+通知配合一起使用
切面是切点和通知组成,通知和切点共同定义了切面的全部内容即:它是什么,在何时何处完成其功能;
举例:将pointcut和Advice配置整合的过程切面
## 目标对象(Target)
通知逻辑的织入目标类。如果没有AOP,那么目标业务类需要自己实现所有的逻辑,在AOP的帮助下,目标类只需要实现那些非横切逻辑的程序逻辑,而比如事务管理等这些横切逻辑就可以使用AOP动态织入特定的连接点上。
举例:两个Service即是目标对象
## 代理(Proxy)
一个类被AOP织入通知后,就产生一个结果类,它是融合了原类和通知逻辑的代理类。根据不同的代理方式,代理类既可能是和原类具有相同接口的类,也可能就是原类的子类,所以可以采用与调用原类相同的方式调用代理类。
举例:IOC容器创建的两个Service类型对象
## 引入(Introduction)
引介是一种特殊的通知,为类添加一些属性和方法。这样,即使一个业务类原本没有实现某个接口,通过AOP的引介功能,也可以动态地为该业务类添加接口的实现逻辑,使业务类成为这个接口的实现类。
几乎由框架完成,我们可以暂时透明
## 织入(Weaving)
织入是将通知添加到目标类的具体连接点上的过程.AOP就像一台织布机,将目标类,通知或引介编织到一起。 AOP有三种织入方式: ①编译期织入:切面在目标类编译时被织入,需要特殊的编译器; ②类装载期织入:切面在目标类加载到JVM时被织入,需要特殊的类装载器; ③动态代理织入:切面在应用运行的某个时刻呗织入,AOP容器会为目标对象动态创建一个代理对象;
## 编程的重点
- 目标对象 xxxService
- 通知
- 切面: 配置一个下 切点+通知
- 剩下的功能交给AOP框架
# 使用AOP框架-Java配置类
- com.neuedu.aop.service.UserService
- insert
- com.neuedu.aop.service.DeptService
- insert
需求: 在所有的Service的 insert方法开始调用之前 打印一下 日志的功能, 2025年3月11日14:02:13 调用了xxxx方法
## 创建项目
## 添加依赖
```xml
4.0.0
org.example
spring-09-aop-log
1.0-SNAPSHOT
17
17
5.3.39
junit
junit
4.13.1
test
org.springframework
spring-test
${spring.version}
org.springframework
spring-beans
${spring.version}
org.springframework
spring-context
${spring.version}
org.springframework
spring-core
${spring.version}
org.springframework
spring-expression
${spring.version}
org.springframework
spring-aop
${spring.version}
org.aspectj
aspectjweaver
1.8.7
```
## 编写Serivce类
```java
package com.neuedu.aop.service;
import org.springframework.stereotype.Service;
/**
* @author 金山
* 项目:spring-learn
* site: https://blog.fulfill.com.cn
* 描述
* @data 2025/3/1114:09
*/
@Service //使用容器 管理 UserService
public class DeptService {
public void insert(){
System.out.println("DeptService.insert调用");
}
}
```
```java
package com.neuedu.aop.service;
import org.springframework.stereotype.Service;
/**
* @author 金山
* 项目:spring-learn
* site: https://blog.fulfill.com.cn
* 描述
* @data 2025/3/1114:09
*/
@Service //使用容器 管理 UserService
public class UserService {
public void insert(){
System.out.println("UserService.insert调用");
}
}
```
配置类
用于包扫描,在容器中注册 两个Service的Bean对象
```java
package com.neuedu.aop;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
/**
* @author 金山
* 项目:spring-learn
* site: https://blog.fulfill.com.cn
* 描述
* @data 2025/3/1114:10
*/
@Configuration
@ComponentScan("com.neuedu.aop")
public class AopApp {
}
```
## 测试Bean的方法执行
```java
package com.neuedu.aop.service;
import com.neuedu.aop.AopApp;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import static org.junit.Assert.*;
/**
* @author 金山
* 项目:spring-learn
* site: https://blog.fulfill.com.cn
* 描述
* @data 2025/3/1114:11
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AopApp.class)
public class DeptServiceTest {
@Autowired
DeptService deptService;
@Test
public void insert() {
deptService.insert();
}
}
```

## 定义切面、通知
编写 用于输出 “ 2025年3月11日14:02:13 调用了xxxx方法”的代码
```java
package com.neuedu.aop.adivce;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Component
@Aspect //@Aspect定义此类为方面代码,即是一个通知。
public class MyAdvice {
/**
* execution(* com.neuedu.aop.service.*.insert(..))
* 第一个* 代表 类型
* insert 代表 这些类中所有 insert方法
*
* 前置通知
* @param joinpoint
*/
@Before("execution(* com.neuedu.aop.service.*.insert(..))")
public void beforeMethod(JoinPoint joinpoint){
System.out.println("【前置通知日志】" + joinpoint.toString());
}
}
```
## 激活动态代理
在配置类上添加@EnableAspectJAutoProxy直接,激活包含@Aspect注解的切面使之生效
```java
package com.neuedu.aop;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@EnableAspectJAutoProxy
@Configuration
@ComponentScan("com.neuedu.aop")
public class AopApp {
}
```
## 测试
获取 Serivce的代理对象 getBean(UserService.java) 执行insert方法
```java
package com.neuedu.aop.service;
import com.neuedu.aop.AopApp;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import static org.junit.Assert.*;
/**
* @author 金山
* 项目:spring-learn
* site: https://blog.fulfill.com.cn
* 描述
* @data 2025/3/1114:11
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AopApp.class)
public class DeptServiceTest {
@Autowired
DeptService deptService;
@Test
public void insert() {
deptService.insert();
}
}
```
```java
package com.neuedu.aop.service;
import com.neuedu.aop.AopApp;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* @author 金山
* 项目:spring-learn
* site: https://blog.fulfill.com.cn
* 描述
* @data 2025/3/1114:11
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AopApp.class)
public class UserServiceTest {
@Autowired
UserService userService;
@Test
public void insert() {
userService.insert();
}
}
```
# 使用AOP框架-纯XML
- com.neuedu.aop.service.UserService
- insert
- com.neuedu.aop.service.DeptService
- insert
需求: 在所有的Service的 insert方法开始调用之前 打印一下 日志的功能, 2025年3月11日14:02:13 调用了xxxx方法
## 创建项目
spring-10-aop-log-only-xml
## 添加依赖
```xml
4.0.0
org.example
spring-09-aop-log
1.0-SNAPSHOT
17
17
5.3.39
junit
junit
4.13.1
test
org.springframework
spring-test
${spring.version}
org.springframework
spring-beans
${spring.version}
org.springframework
spring-context
${spring.version}
org.springframework
spring-core
${spring.version}
org.springframework
spring-expression
${spring.version}
org.springframework
spring-aop
${spring.version}
org.aspectj
aspectjweaver
1.8.7
```
## 编写Serivce类
```java
package com.neuedu.aop.service;
import org.springframework.stereotype.Service;
/**
* @author 金山
* 项目:spring-learn
* site: https://blog.fulfill.com.cn
* 描述
* @data 2025/3/1114:09
*/
@Service //使用容器 管理 UserService
public class DeptService {
public void insert(){
System.out.println("DeptService.insert调用");
}
}
```
```java
package com.neuedu.aop.service;
import org.springframework.stereotype.Service;
/**
* @author 金山
* 项目:spring-learn
* site: https://blog.fulfill.com.cn
* 描述
* @data 2025/3/1114:09
*/
@Service //使用容器 管理 UserService
public class UserService {
public void insert(){
System.out.println("UserService.insert调用");
}
}
```
## 配置文件
使用Bean标签 注册两个 Bean
spring-aop.xml
```xml
```
## 测试Bean的方法执行
```java
package com.neuedu.aop.service;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import static org.junit.Assert.*;
/**
* @author 金山
* 项目:spring-learn
* site: https://blog.fulfill.com.cn
* 描述
* @data 2025/3/129:12
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:spring-aop.xml")
public class DeptServiceTest {
@Autowired
DeptService deptService;
@Test
public void insert() {
deptService.insert();
}
}
```

## 定义切面、通知
编写 用于输出 “ 2025年3月11日14:02:13 调用了xxxx方法”的代码
```java
package com.neuedu.aop.advice;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
import java.util.Date;
public class MyAdvice {
public void beforeMethod(JoinPoint joinpoint){
String info = String.format("%s 调用了%s方法",
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()),
joinpoint.getSignature().toString()
);
System.out.println(info);
}
}
```
在xml文件中配置
- 在sprin-aop.xml文件中注册 MyAdvice Bean(myAdvice)
- 定义切面
- 在那些方法上 切点 execution('com.neuedu.aop.,service.*.insert(..)')
- 使用哪个通知 myAdvice.beforeMethod
```xml
```
## 测试
获取 Serivce的代理对象 getBean(UserService.java) 执行insert方法
```java
package com.neuedu.aop.service;
import com.neuedu.aop.AopApp;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import static org.junit.Assert.*;
/**
* @author 金山
* 项目:spring-learn
* site: https://blog.fulfill.com.cn
* 描述
* @data 2025/3/1114:11
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AopApp.class)
public class DeptServiceTest {
@Autowired
DeptService deptService;
@Test
public void insert() {
deptService.insert();
}
}
```

# 5种通知
方面代码一般也称为通知:定义一个“切面”要实现的功能。通知有五种:
1. 前置通知:在某连接点(JoinPoint 就是要织入的业务方法)之前执行的通知。
2. 后置通知:当某连接点退出时执行的通知(不论是正常结束还是发生异常)。
3. 返回通知:(最终通知)在这里可以得到业务方法的返回值。但在发生异常时无法得到返回值。
4. 环绕通知:包围一个连接点的通知,也就是在业务方法执行前和执行后执行的通知。
5. 异常通知:在业务方法发生异常时执行的通知。
## 定义了一个切点(Service)
```java
package com.neuedu.aop.service;
import com.neuedu.aop.po.Dept;
import org.springframework.stereotype.Service;
/**
* @author 金山
* 项目:spring-learn
* site: https://blog.fulfill.com.cn
* 描述
* @data 2025/3/1114:09
*/
@Service //使用容器 管理 UserService
public class DeptService {
public void insert(){
System.out.println("DeptService.insert调用");
}
public void update(int numa,int numb){
System.out.println("DeptService.update调用");
int result = numa / numb;
}
public Dept selectById(int numa,int numb){
System.out.println("DeptService.selectById调用");
int result = numa / numb;
//模拟从数据库查询到的
Dept dept = new Dept("1001","开发","2701");
return dept;
}
public boolean save(int numa,int numb){
System.out.println("DeptService.save调用");
int result = numa / numb;
//模拟从数据库查询到的
System.out.println(result);
return true;
}
}
```
## 配置各种通知
- Pointcut
- 通知
- Before
- After
- AfterReturning
- AfterThrowing
- Around
```java
package com.neuedu.aop.adivce;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import java.lang.reflect.Executable;
import java.rmi.server.ExportException;
@Component
@Aspect //@Aspect定义此类为方面代码,即是一个通知。
public class MyAdvice {
/**
* 定义一个切点 execution(* com.neuedu.aop.service.*.insert(..))
* 第一个* 代表 类型
* insert 代表 这些类中所有 insert方法
*/
@Pointcut("execution(* com.neuedu.aop.service.*.insert(..))")
public void insertMethod(){}
@Pointcut("execution(* com.neuedu.aop.service.*.update(..))")
public void updateMethod(){}
@Pointcut("execution(* com.neuedu.aop.service.*.selectById(..))")
public void selectByIdMethod(){}
@Pointcut("execution(* com.neuedu.aop.service.*.save(..))")
public void saveMethod(){}
/**
* 前置通知
* @param joinpoint
*/
@Before("insertMethod()")
public void beforeMethod(JoinPoint joinpoint){
System.out.println("【前置通知日志】" + joinpoint.toString());
}
// @After("updateMethod()")
@After(value="updateMethod()")
public void afterMethod(JoinPoint joinpoint){
System.out.println("【后置通知日志】" + joinpoint.toString());
}
// @AfterReturning(value="selectByIdMethod()",returning="result")
// public void afterReturingMethod(JoinPoint joinpoint ,Object result){
// System.out.println("【AfterReturing 通知】" + joinpoint.toString());
// System.out.println("result = " + result);
// }
@AfterThrowing(value="selectByIdMethod()",throwing="ex")
public void afterReturingMethod(JoinPoint joinpoint , Exception ex){
System.out.println("【AfterThrowing 通知】" + joinpoint.toString());
System.out.println("ex = " + ex);
}
@Around(value="saveMethod()")
public Object afterReturingMethod(ProceedingJoinPoint joinpoint ){
Object obj = null;
try{
System.out.println("开启事务");
Object args[] = joinpoint.getArgs(); // 10,20 0 ,0
obj = joinpoint.proceed(args);
System.out.println("提交事务");
}catch (Throwable e) {
System.out.println("回滚");
throw new RuntimeException(e);
} finally {
}
return obj;
}
}
```
## 分别测试5中通知
```java
package com.neuedu.aop.service;
import com.neuedu.aop.AopApp;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import static org.junit.Assert.*;
/**
* @author 金山
* 项目:spring-learn
* site: https://blog.fulfill.com.cn
* 描述
* @data 2025/3/1114:11
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AopApp.class)
public class DeptServiceTest {
@Autowired
DeptService deptService;
@Test
public void beforeAdvice() {
deptService.insert();
}
@Test
public void afterAdvice() {
//不报错,后置通知 正常执行了
// deptService.update(10,20);
//产生了错误 后置通知,也正常执行
deptService.update(0,0);
}
@Test
public void afterReturing() {
//不报错,afterReturing通知 正常执行了
// deptService.selectById(10,20);
//产生了错误 afterReturing通知, 不会执行
deptService.selectById(0,0);
}
@Test
public void afterThrowing() {
//不报错,afterReturing通知 正常执行了
// deptService.selectById(10,20);
//产生了错误 afterReturing通知, 不会执行
deptService.selectById(0,0);
}
@Test
public void around() {
//不报错,around通知 正常执行了
// deptService.save(10,20);
//产生了错误 around通知, 不会执行
deptService.save(0,0);
}
}
```
# 现动态代理有两种形式:
1. jdk动态代理:根据目标类接口获取代理类实现规则,生成代理对象。这个代理对象,也是目标类接口的一个实现类。
2. cglib动态代理:根据目标类本身获取代理类实现规则,生成代理对象。这个代理对象,也是目标类的一个子类。 (如果目标类为final,则不能使用CGLib实现动态代理)
SpringAOP可以自动在jdk动态代理和CGLib动态代理之间进行切换,规则如下:
1. 如果目标对象实现了接口,采用jdk动态代理实现aop。
2. 如果目标对象没有实现接口,采用CGLib动态代理实现aop。
3. 如果目标对象实现了接口,但仍然想要使用CGLIB实现aop,可以手动进行配置。
创建项目
spring-12-aop-proxy
# Spring整合 MyBatis
1. 需要将 SqlSessionFactory对象 注册到 Spring IOC容器中 SqlSessionFactory重量级对象 全局唯一
```java
@Bean
public SqlSessionFactory getSqlSessionFactory(){
String resoueces = "mybatis-config.xml";
InputStream resourceAsStream = Resources.getResourceAsStream(resoueces);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
return sqlSessionFactory
}
```
2. 使用Spring容器管理 所有 Mapper代理对象
mybati-spring.jar
3. 最终的依赖
- junit5
- spring-test
- spring-context(aop、bean、core、Expression)
- mysql-connection-java 数据库驱动
- MyBatis
- 数据源(C3P0、Druid、HikariCP 、DBCP )
- Druid 阿里
## 编码实现
### spring-14-mybatis

### 添加依赖
```xml
4.0.0
com.neuedu.spring.mybatis
spring-14-mybatis
1.0-SNAPSHOT
17
17
5.11.4
5.3.39
8.0.33
3.5.19
3.0.4
1.2.24
org.junit.jupiter
junit-jupiter
${junit.version}
test
org.springframework
spring-test
${spring.version}
org.springframework
spring-context
${spring.version}
《!
org.springframework
spring-jdbc
${spring.version}
mysql
mysql-connector-java
${mysql.version}
org.mybatis
mybatis
${mybatis.version}
org.mybatis
mybatis-spring
${mybatis.spring.version}
com.alibaba
druid
${druid.version}
```
### 使用mybaits
#### 准备厍
his.sql
```sql
/*
SQLyog Ultimate v12.08 (64 bit)
MySQL - 8.0.30 : Database - his
*********************************************************************
*/
/*!40101 SET NAMES utf8 */;
/*!40101 SET SQL_MODE=''*/;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
CREATE DATABASE /*!32312 IF NOT EXISTS*/`his` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_bin */ /*!80016 DEFAULT ENCRYPTION='N' */;
USE `his`;
/*Table structure for table `check_apply` */
DROP TABLE IF EXISTS `check_apply`;
CREATE TABLE `check_apply` (
`item_id` int NOT NULL AUTO_INCREMENT COMMENT '检查项目主键',
`regist_id` int DEFAULT NULL COMMENT '病例号',
`check_id` int DEFAULT NULL COMMENT '检查ID',
`name` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '检查项目名称',
`price` decimal(6,2) DEFAULT NULL COMMENT '价格',
`status` varchar(5) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '状态',
`result` text CHARACTER SET utf8mb4 COLLATE utf8mb4_bin COMMENT '检查结果',
PRIMARY KEY (`item_id`),
KEY `FK_Reference_10` (`regist_id`),
KEY `FK_Reference_11` (`check_id`),
CONSTRAINT `FK_Reference_10` FOREIGN KEY (`regist_id`) REFERENCES `register` (`regist_id`) ON DELETE RESTRICT ON UPDATE RESTRICT,
CONSTRAINT `FK_Reference_11` FOREIGN KEY (`check_id`) REFERENCES `checkitem` (`check_id`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='开立检查申请';
/*Data for the table `check_apply` */
insert into `check_apply`(`item_id`,`regist_id`,`check_id`,`name`,`price`,`status`,`result`) values (3,6,4,'心电图','80.00','1',NULL),(4,6,1,'腹部CT','200.00','1',NULL),(5,19,1,'腹部CT','200.00','1',NULL),(6,19,2,'胸部x光片','50.00','1',NULL),(7,19,3,'颈部超声波扫描','10.00','1',NULL),(8,18,1,'腹部CT','200.00','2',NULL),(9,18,2,'胸部x光片','50.00','2',NULL),(11,37,1,'腹部CT','200.00','3','董卓检查结果.....'),(12,37,2,'胸部x光片','50.00','1',NULL),(13,69,1,'腹部CT','200.00','3','ok 回去多吃饭,'),(14,69,2,'胸部x光片','50.00','3','肺结节'),(15,69,3,'颈部超声波扫描','10.00','1',NULL),(16,69,4,'心电图','80.00','3','窦性心律');
/*Table structure for table `checkitem` */
DROP TABLE IF EXISTS `checkitem`;
CREATE TABLE `checkitem` (
`check_id` int NOT NULL AUTO_INCREMENT COMMENT '检查ID',
`name` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '名称',
`price` decimal(6,2) DEFAULT NULL COMMENT '价格',
`del` varchar(5) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT '1' COMMENT '是否有效',
`createtime` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`check_id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='检查';
/*Data for the table `checkitem` */
insert into `checkitem`(`check_id`,`name`,`price`,`del`,`createtime`) values (1,'腹部CT','200.00','1','2024-11-21 12:24:38'),(2,'胸部x光片','50.00','1','2024-11-21 12:24:39'),(3,'颈部超声波扫描','10.00','1','2024-11-21 12:25:31'),(4,'心电图','80.00','1','2024-12-02 13:47:20');
/*Table structure for table `constant_type` */
DROP TABLE IF EXISTS `constant_type`;
CREATE TABLE `constant_type` (
`type_id` int NOT NULL AUTO_INCREMENT COMMENT '主键',
`type` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '类别',
`caption` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '说明',
`del` varchar(5) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT '1' COMMENT '是否有效',
`createtime` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`type_id`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='常数类别';
/*Data for the table `constant_type` */
insert into `constant_type`(`type_id`,`type`,`caption`,`del`,`createtime`) values (1,'Gender','性别','1','2024-11-21 12:20:04'),(2,'RegisterStatus','患者状态','1','2024-11-21 16:57:54'),(5,'Docter','医生状态','1','2024-11-25 09:14:43'),(6,'YesOrNO','是否','1','2024-11-29 08:44:09'),(7,'CheckApplyStatus','检查项目申请状态','1','2024-12-02 16:30:03'),(8,'InspectApplyStatus','检验项目申请状态','1','2024-12-03 09:25:35');
/*Table structure for table `constants_item` */
DROP TABLE IF EXISTS `constants_item`;
CREATE TABLE `constants_item` (
`item_id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
`code` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '代码',
`caption` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '名称',
`type` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '类型',
`type_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '类型名称',
`del` varchar(5) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT '1' COMMENT '是否有效',
`createtime` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`item_id`)
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='常数项目';
/*Data for the table `constants_item` */
insert into `constants_item`(`item_id`,`code`,`caption`,`type`,`type_name`,`del`,`createtime`) values (1,'1','男','Gender','性别','1','2024-11-21 12:20:29'),(2,'2','女','Gender','性别','1','2024-11-21 12:20:31'),(4,'1','已挂号','RegisterStatus','患者状态','1','2024-11-22 11:15:48'),(7,'Y','是','YesOrNO','是否','1','2024-11-29 08:46:20'),(8,'N','否','YesOrNO','是否','1','2024-11-29 08:46:33'),(9,'1','待缴费','CheckApplyStatus','检查项目申请状态','1','2024-12-02 16:30:20'),(10,'2','已缴费','CheckApplyStatus','检查项目申请状态','1','2024-12-02 16:30:29'),(11,'3','已检查','CheckApplyStatus','检查项目申请状态','1','2024-12-02 16:31:01'),(12,'4','已退费','CheckApplyStatus','检查项目申请状态','1','2024-12-02 16:31:12'),(13,'1','待缴费','InspectApplyStatus','检验项目申请状态','1','2024-12-03 09:25:48'),(14,'2','已缴费','InspectApplyStatus','检验项目申请状态','1','2024-12-03 09:25:59'),(15,'3','已检查','InspectApplyStatus','检验项目申请状态','1','2024-12-03 09:26:03'),(16,'4','已退费','InspectApplyStatus','检验项目申请状态','1','2024-12-03 09:26:05');
/*Table structure for table `dept` */
DROP TABLE IF EXISTS `dept`;
CREATE TABLE `dept` (
`dept_id` bigint NOT NULL AUTO_INCREMENT COMMENT '部门ID',
`dept_name` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '部门名称',
`loc` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '办公地址',
`leader` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '科室主任',
`del` varchar(5) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT '1' COMMENT '是否有效',
`createtime` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`dept_id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='部门';
/*Data for the table `dept` */
insert into `dept`(`dept_id`,`dept_name`,`loc`,`leader`,`del`,`createtime`) values (1,'心内科','207','孙思邈','1','2024-11-21 13:56:49'),(5,'皮肤科','202','李时珍','1','2024-11-22 08:39:22');
/*Table structure for table `inspect_apply` */
DROP TABLE IF EXISTS `inspect_apply`;
CREATE TABLE `inspect_apply` (
`item_id` int NOT NULL AUTO_INCREMENT COMMENT '建议项目主键',
`inspect_id` int DEFAULT NULL COMMENT '检验ID',
`name` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '检验项目名称',
`regist_id` int DEFAULT NULL COMMENT '病例号',
`price` decimal(6,2) DEFAULT NULL COMMENT '价格',
`status` varchar(5) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '状态',
`result` text CHARACTER SET utf8mb4 COLLATE utf8mb4_bin COMMENT '检查结果',
PRIMARY KEY (`item_id`),
KEY `FK_Reference_13` (`inspect_id`),
KEY `FK_Reference_14` (`regist_id`),
CONSTRAINT `FK_Reference_13` FOREIGN KEY (`inspect_id`) REFERENCES `inspectitem` (`inspect_id`) ON DELETE RESTRICT ON UPDATE RESTRICT,
CONSTRAINT `FK_Reference_14` FOREIGN KEY (`regist_id`) REFERENCES `register` (`regist_id`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='开立检验请';
/*Data for the table `inspect_apply` */
insert into `inspect_apply`(`item_id`,`inspect_id`,`name`,`regist_id`,`price`,`status`,`result`) values (7,1,'血常规',18,'10.00','2',NULL),(8,4,'大生化',18,'40.00','2',NULL),(9,2,'肝肾功能',37,'20.00','1',NULL),(10,1,'血常规',37,'10.00','2',NULL),(11,3,'鸟产规',37,'30.00','2',NULL),(13,2,'肝肾功能',69,'20.00','2',NULL),(14,3,'鸟产规',69,'30.00','2',NULL),(15,4,'大生化',69,'40.00','1',NULL),(16,5,'肝肾功能',69,'500.00','1',NULL);
/*Table structure for table `inspectitem` */
DROP TABLE IF EXISTS `inspectitem`;
CREATE TABLE `inspectitem` (
`inspect_id` int NOT NULL AUTO_INCREMENT COMMENT '检验ID',
`name` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '名称',
`price` decimal(6,2) DEFAULT NULL COMMENT '价格',
`del` varchar(5) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT '1' COMMENT '是否有效',
`createtime` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`inspect_id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='检验';
/*Data for the table `inspectitem` */
insert into `inspectitem`(`inspect_id`,`name`,`price`,`del`,`createtime`) values (1,'血常规','10.00','1','2024-11-21 12:26:07'),(2,'肝肾功能','20.00','1','2024-11-21 12:26:28'),(3,'鸟产规','30.00','1','2024-11-21 12:26:35'),(4,'大生化','40.00','1','2024-11-21 12:26:41'),(5,'肝肾功能','500.00','1','2024-12-03 09:13:11');
/*Table structure for table `item_upload` */
DROP TABLE IF EXISTS `item_upload`;
CREATE TABLE `item_upload` (
`item_id` bigint NOT NULL COMMENT '项目Id',
`upload_id` bigint NOT NULL COMMENT '上传文件Id',
`type` int NOT NULL COMMENT '1 检查项目上传 2 检验上传的文件',
PRIMARY KEY (`item_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='上传文件和检验、检查项目的对应关系';
/*Data for the table `item_upload` */
/*Table structure for table `regist_level` */
DROP TABLE IF EXISTS `regist_level`;
CREATE TABLE `regist_level` (
`level_id` bigint NOT NULL AUTO_INCREMENT COMMENT '级别ID',
`caption` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '级别名称',
`fee` decimal(6,2) DEFAULT NULL COMMENT '费用',
`del` varchar(5) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT '1' COMMENT '是否删除0 删除1,正常的',
`createtime` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '数据创建时间',
PRIMARY KEY (`level_id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='挂号级别';
/*Data for the table `regist_level` */
insert into `regist_level`(`level_id`,`caption`,`fee`,`del`,`createtime`) values (1,'住院医','10.00','1','2024-11-22 11:59:02'),(2,'主治','20.00','1','2024-11-22 11:59:26'),(3,'主任','50.00','1','2024-11-22 11:59:34'),(4,'老专家','100.00','1','2024-11-22 11:59:40'),(5,'名老专家','2000.00','1','2024-11-22 12:19:06');
/*Table structure for table `register` */
DROP TABLE IF EXISTS `register`;
CREATE TABLE `register` (
`regist_id` int NOT NULL AUTO_INCREMENT COMMENT '病例号',
`name` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '名称',
`gender` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '性别',
`age` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '年龄',
`birthday` date DEFAULT NULL COMMENT '出生日期',
`visit_time` date DEFAULT NULL COMMENT '看诊时间',
`dept_id` bigint DEFAULT NULL COMMENT '部门ID',
`regist_level` bigint DEFAULT NULL COMMENT '级别ID',
`readme` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '主诉',
`present` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '现病史',
`present_treat` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '现病史治疗情况',
`history` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '既往史',
`allergy` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '过敏史',
`disease` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '确诊疾病',
`suit` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '处置方案',
`drug` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '药品清单',
`userid` bigint DEFAULT NULL COMMENT '用户ID',
`book` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT 'Y N ',
`fee` decimal(6,2) DEFAULT NULL COMMENT '挂号费用',
`status` varchar(5) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '1 代接诊,2 一看诊,3 已退',
`del` varchar(5) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT '1' COMMENT '是否有效',
`createtime` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`regist_id`),
KEY `FK_Reference_7` (`dept_id`),
KEY `FK_Reference_8` (`regist_level`),
KEY `FK_Reference_9` (`userid`),
CONSTRAINT `FK_Reference_7` FOREIGN KEY (`dept_id`) REFERENCES `dept` (`dept_id`) ON DELETE RESTRICT ON UPDATE RESTRICT,
CONSTRAINT `FK_Reference_8` FOREIGN KEY (`regist_level`) REFERENCES `regist_level` (`level_id`) ON DELETE RESTRICT ON UPDATE RESTRICT,
CONSTRAINT `FK_Reference_9` FOREIGN KEY (`userid`) REFERENCES `ums_user` (`userid`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE=InnoDB AUTO_INCREMENT=70 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='患者表';
/*Data for the table `register` */
insert into `register`(`regist_id`,`name`,`gender`,`age`,`birthday`,`visit_time`,`dept_id`,`regist_level`,`readme`,`present`,`present_treat`,`history`,`allergy`,`disease`,`suit`,`drug`,`userid`,`book`,`fee`,`status`,`del`,`createtime`) values (1,'张飞','2','58',NULL,'2024-12-02',1,1,'我啥毛病都没有',NULL,NULL,NULL,NULL,NULL,NULL,NULL,3,NULL,'0.00','1','1','2024-11-28 13:43:59'),(2,'刘备','2','58',NULL,'2024-12-02',1,1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,3,NULL,NULL,'2','1','2024-11-28 13:48:22'),(3,'关羽','2','58',NULL,'2024-12-02',1,1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,3,NULL,NULL,'1','1','2024-11-28 13:48:35'),(4,'赵云','1','50',NULL,'2024-12-02',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'2','1','2024-11-28 14:01:48'),(5,'诸葛','1','50','2019-01-01','2024-12-02',1,1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,3,'1',NULL,'2','1','2024-11-28 14:08:41'),(6,'司马懿','1','12',NULL,'2024-12-02',1,1,'1','12','13','14','15',NULL,NULL,NULL,7,'1','0.00','3','1','2024-11-28 14:36:11'),(7,'孙权','1','32',NULL,'2024-12-02',1,1,'aa','bb','cc','dd','ee',NULL,NULL,NULL,7,'1','0.00','2','1','2024-11-28 14:53:27'),(8,'测试1','1','12',NULL,'2024-12-02',1,1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,3,'1','0.00','2','1','2024-11-28 15:01:41'),(9,'1','1','222',NULL,'2024-12-02',1,1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,7,'2','0.00','1','1','2024-11-28 15:02:09'),(10,'1','1','22','2024-11-28','2024-12-02',1,1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,3,'1','0.00','2','1','2024-11-28 15:03:24'),(11,'12112',NULL,NULL,NULL,'2024-12-02',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'0.00','1','1','2024-11-29 09:23:12'),(12,NULL,NULL,NULL,NULL,'2024-12-02',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'0.00','1','1','2024-11-29 09:28:50'),(13,'曹操1203','2','58',NULL,'2024-12-03',1,1,'我啥毛病都没有',NULL,NULL,NULL,NULL,NULL,NULL,NULL,3,NULL,'0.00','1','1','2024-11-28 13:43:59'),(14,'周瑜1203','2','58',NULL,'2024-12-03',1,1,'我啥毛病都没有',NULL,NULL,NULL,NULL,NULL,NULL,NULL,3,NULL,'0.00','1','1','2024-11-28 13:43:59'),(15,'赵云1203','2','58',NULL,'2024-12-03',1,1,'我啥毛病都没有',NULL,NULL,NULL,NULL,NULL,NULL,NULL,3,NULL,'0.00','1','1','2024-11-28 13:43:59'),(16,'孙权1203','2','58',NULL,'2024-12-03',1,1,'我啥毛病都没有',NULL,NULL,NULL,NULL,NULL,NULL,NULL,3,NULL,'0.00','1','1','2024-11-28 13:43:59'),(17,'吕布1203','2','58',NULL,'2024-12-03',1,1,'我啥毛病都没有',NULL,NULL,NULL,NULL,NULL,NULL,NULL,3,NULL,'0.00','1','1','2024-11-28 13:43:59'),(18,'马超1203','2','58',NULL,'2024-12-03',1,1,'121212','121','12','12','1122121212',NULL,NULL,NULL,7,NULL,'0.00','3','1','2024-11-28 13:43:59'),(19,'刘禅1203','2','58',NULL,'2024-12-03',1,1,'sadfsa','sadfasfsa','asdfsaf','asdfsa','fdasfaffsf',NULL,NULL,NULL,7,NULL,'0.00','3','1','2024-11-28 13:43:59'),(20,'姜维1203','2','58',NULL,'2024-12-03',1,1,'我啥毛病都没有',NULL,NULL,NULL,NULL,NULL,NULL,NULL,7,NULL,'0.00','1','1','2024-11-28 13:43:59'),(21,'典韦1203','2','58',NULL,'2024-12-03',1,1,'我啥毛病都没有',NULL,NULL,NULL,NULL,NULL,NULL,NULL,7,NULL,'0.00','1','1','2024-11-28 13:43:59'),(22,'庞统1203','2','58',NULL,'2024-12-03',1,1,'我啥毛病都没有',NULL,NULL,NULL,NULL,NULL,NULL,NULL,7,NULL,'0.00','1','1','2024-11-28 13:43:59'),(23,'董卓1203','2','58',NULL,'2024-12-03',1,1,'我啥毛病都没有',NULL,NULL,NULL,NULL,NULL,NULL,NULL,7,NULL,'0.00','1','1','2024-11-28 13:43:59'),(24,'荀彧1203','2','58',NULL,'2024-12-03',1,1,'我啥毛病都没有',NULL,NULL,NULL,NULL,NULL,NULL,NULL,7,NULL,'0.00','1','1','2024-11-28 13:43:59'),(25,'黄忠1203','2','58',NULL,'2024-12-03',1,1,'我啥毛病都没有',NULL,NULL,NULL,NULL,NULL,NULL,NULL,7,NULL,'0.00','1','1','2024-11-28 13:43:59'),(26,'鲁肃1203','2','58',NULL,'2024-12-03',1,1,'我啥毛病都没有',NULL,NULL,NULL,NULL,NULL,NULL,NULL,7,NULL,'0.00','1','1','2024-11-28 13:43:59'),(27,'曹操1205','2','58',NULL,'2024-12-05',1,1,'我啥毛病都没有',NULL,NULL,NULL,NULL,NULL,NULL,NULL,3,NULL,'0.00','1','1','2024-11-28 13:43:59'),(28,'周瑜1205','2','58',NULL,'2024-12-05',1,1,'我啥毛病都没有',NULL,NULL,NULL,NULL,NULL,NULL,NULL,3,NULL,'0.00','1','1','2024-11-28 13:43:59'),(29,'赵云1205','2','58',NULL,'2024-12-05',1,1,'我啥毛病都没有',NULL,NULL,NULL,NULL,NULL,NULL,NULL,3,NULL,'0.00','1','1','2024-11-28 13:43:59'),(30,'孙权1205','2','58',NULL,'2024-12-05',1,1,'我啥毛病都没有',NULL,NULL,NULL,NULL,NULL,NULL,NULL,3,NULL,'0.00','1','1','2024-11-28 13:43:59'),(31,'吕布1205','2','58',NULL,'2024-12-05',1,1,'我啥毛病都没有',NULL,NULL,NULL,NULL,NULL,NULL,NULL,3,NULL,'0.00','1','1','2024-11-28 13:43:59'),(32,'马超1205','2','58',NULL,'2024-12-05',1,1,'我啥毛病都没有',NULL,NULL,NULL,NULL,NULL,NULL,NULL,7,NULL,'0.00','1','1','2024-11-28 13:43:59'),(33,'刘禅1205','2','58',NULL,'2024-12-05',1,1,'我啥毛病都没有',NULL,NULL,NULL,NULL,NULL,NULL,NULL,7,NULL,'0.00','1','1','2024-11-28 13:43:59'),(34,'姜维1205','2','58',NULL,'2024-12-05',1,1,'我啥毛病都没有',NULL,NULL,NULL,NULL,NULL,NULL,NULL,7,NULL,'0.00','1','1','2024-11-28 13:43:59'),(35,'典韦1205','2','58',NULL,'2024-12-05',1,1,'我啥毛病都没有',NULL,NULL,NULL,NULL,NULL,NULL,NULL,7,NULL,'0.00','1','1','2024-11-28 13:43:59'),(36,'庞统1205','2','58',NULL,'2024-12-05',1,1,'我啥毛病都没有',NULL,NULL,NULL,NULL,NULL,NULL,NULL,7,NULL,'0.00','1','1','2024-11-28 13:43:59'),(37,'董卓1205','2','58',NULL,'2024-12-05',1,1,'1','1','2','3','4',NULL,NULL,NULL,7,NULL,'0.00','3','1','2024-11-28 13:43:59'),(38,'荀彧1205','2','58',NULL,'2024-12-05',1,1,'我啥毛病都没有',NULL,NULL,NULL,NULL,NULL,NULL,NULL,7,NULL,'0.00','1','1','2024-11-28 13:43:59'),(39,'黄忠1205','2','58',NULL,'2024-12-05',1,1,'我啥毛病都没有',NULL,NULL,NULL,NULL,NULL,NULL,NULL,7,NULL,'0.00','1','1','2024-11-28 13:43:59'),(40,'鲁肃1205','2','58',NULL,'2024-12-05',1,1,'我啥毛病都没有',NULL,NULL,NULL,NULL,NULL,NULL,NULL,7,NULL,'0.00','1','1','2024-11-28 13:43:59'),(41,'曹操1206','2','58',NULL,'2024-12-06',1,1,'我啥毛病都没有',NULL,NULL,NULL,NULL,NULL,NULL,NULL,3,NULL,'0.00','1','1','2024-11-28 13:43:59'),(42,'周瑜1206','2','58',NULL,'2024-12-06',1,1,'我啥毛病都没有',NULL,NULL,NULL,NULL,NULL,NULL,NULL,3,NULL,'0.00','1','1','2024-11-28 13:43:59'),(43,'赵云1206','2','58',NULL,'2024-12-06',1,1,'我啥毛病都没有',NULL,NULL,NULL,NULL,NULL,NULL,NULL,3,NULL,'0.00','1','1','2024-11-28 13:43:59'),(44,'孙权1206','2','58',NULL,'2024-12-06',1,1,'我啥毛病都没有',NULL,NULL,NULL,NULL,NULL,NULL,NULL,3,NULL,'0.00','1','1','2024-11-28 13:43:59'),(45,'吕布1206','2','58',NULL,'2024-12-06',1,1,'我啥毛病都没有',NULL,NULL,NULL,NULL,NULL,NULL,NULL,3,NULL,'0.00','1','1','2024-11-28 13:43:59'),(46,'马超1206','2','58',NULL,'2024-12-06',1,1,'我啥毛病都没有',NULL,NULL,NULL,NULL,NULL,NULL,NULL,7,NULL,'0.00','1','1','2024-11-28 13:43:59'),(47,'刘禅1206','2','58',NULL,'2024-12-06',1,1,'我啥毛病都没有',NULL,NULL,NULL,NULL,NULL,NULL,NULL,7,NULL,'0.00','1','1','2024-11-28 13:43:59'),(48,'姜维1206','2','58',NULL,'2024-12-06',1,1,'我啥毛病都没有',NULL,NULL,NULL,NULL,NULL,NULL,NULL,7,NULL,'0.00','1','1','2024-11-28 13:43:59'),(49,'典韦1206','2','58',NULL,'2024-12-06',1,1,'我啥毛病都没有',NULL,NULL,NULL,NULL,NULL,NULL,NULL,7,NULL,'0.00','1','1','2024-11-28 13:43:59'),(50,'庞统1206','2','58',NULL,'2024-12-06',1,1,'我啥毛病都没有',NULL,NULL,NULL,NULL,NULL,NULL,NULL,7,NULL,'0.00','1','1','2024-11-28 13:43:59'),(51,'董卓1206','2','58',NULL,'2024-12-06',1,1,'我啥毛病都没有',NULL,NULL,NULL,NULL,NULL,NULL,NULL,7,NULL,'0.00','1','1','2024-11-28 13:43:59'),(52,'荀彧1206','2','58',NULL,'2024-12-06',1,1,'我啥毛病都没有',NULL,NULL,NULL,NULL,NULL,NULL,NULL,7,NULL,'0.00','1','1','2024-11-28 13:43:59'),(53,'黄忠1206','2','58',NULL,'2024-12-06',1,1,'我啥毛病都没有',NULL,NULL,NULL,NULL,NULL,NULL,NULL,7,NULL,'0.00','1','1','2024-11-28 13:43:59'),(54,'鲁肃1206','2','58',NULL,'2024-12-06',1,1,'我啥毛病都没有',NULL,NULL,NULL,NULL,NULL,NULL,NULL,7,NULL,'0.00','1','1','2024-11-28 13:43:59'),(55,'曹操1207','2','58',NULL,'2024-12-07',1,1,'我啥毛病都没有',NULL,NULL,NULL,NULL,NULL,NULL,NULL,3,NULL,'0.00','1','1','2024-11-28 13:43:59'),(56,'周瑜1207','2','58',NULL,'2024-12-07',1,1,'我啥毛病都没有',NULL,NULL,NULL,NULL,NULL,NULL,NULL,3,NULL,'0.00','1','1','2024-11-28 13:43:59'),(57,'赵云1207','2','58',NULL,'2024-12-07',1,1,'我啥毛病都没有',NULL,NULL,NULL,NULL,NULL,NULL,NULL,3,NULL,'0.00','1','1','2024-11-28 13:43:59'),(58,'孙权1207','2','58',NULL,'2024-12-07',1,1,'我啥毛病都没有',NULL,NULL,NULL,NULL,NULL,NULL,NULL,3,NULL,'0.00','1','1','2024-11-28 13:43:59'),(59,'吕布1207','2','58',NULL,'2024-12-07',1,1,'我啥毛病都没有',NULL,NULL,NULL,NULL,NULL,NULL,NULL,3,NULL,'0.00','1','1','2024-11-28 13:43:59'),(60,'马超1207','2','58',NULL,'2024-12-07',1,1,'我啥毛病都没有',NULL,NULL,NULL,NULL,NULL,NULL,NULL,7,NULL,'0.00','1','1','2024-11-28 13:43:59'),(61,'刘禅1207','2','58',NULL,'2024-12-07',1,1,'我啥毛病都没有',NULL,NULL,NULL,NULL,NULL,NULL,NULL,7,NULL,'0.00','1','1','2024-11-28 13:43:59'),(62,'姜维1207','2','58',NULL,'2024-12-07',1,1,'我啥毛病都没有',NULL,NULL,NULL,NULL,NULL,NULL,NULL,7,NULL,'0.00','1','1','2024-11-28 13:43:59'),(63,'典韦1207','2','58',NULL,'2024-12-07',1,1,'我啥毛病都没有',NULL,NULL,NULL,NULL,NULL,NULL,NULL,7,NULL,'0.00','1','1','2024-11-28 13:43:59'),(64,'庞统1207','2','58',NULL,'2024-12-07',1,1,'我啥毛病都没有',NULL,NULL,NULL,NULL,NULL,NULL,NULL,7,NULL,'0.00','1','1','2024-11-28 13:43:59'),(65,'董卓1207','2','58',NULL,'2024-12-07',1,1,'我啥毛病都没有',NULL,NULL,NULL,NULL,NULL,NULL,NULL,7,NULL,'0.00','1','1','2024-11-28 13:43:59'),(66,'荀彧1207','2','58',NULL,'2024-12-07',1,1,'我啥毛病都没有',NULL,NULL,NULL,NULL,NULL,NULL,NULL,7,NULL,'0.00','1','1','2024-11-28 13:43:59'),(67,'黄忠1207','2','58',NULL,'2024-12-07',1,1,'我啥毛病都没有',NULL,NULL,NULL,NULL,NULL,NULL,NULL,7,NULL,'0.00','1','1','2024-11-28 13:43:59'),(68,'鲁肃1207','2','58',NULL,'2024-12-07',1,1,'我啥毛病都没有',NULL,NULL,NULL,NULL,NULL,NULL,NULL,7,NULL,'0.00','1','1','2024-11-28 13:43:59'),(69,'孙权1206','1','50','2024-12-05','2024-12-06',1,1,'121','1244','1233','1222','1212121212','肠胃感冒','多喝热水','五',3,'Y','11.00','4','1','2024-12-06 11:32:58');
/*Table structure for table `role_menu` */
DROP TABLE IF EXISTS `role_menu`;
CREATE TABLE `role_menu` (
`menu_id` bigint DEFAULT NULL COMMENT '菜单ID',
`role_id` bigint DEFAULT NULL COMMENT '角色ID',
KEY `FK_Reference_1` (`menu_id`),
KEY `FK_Reference_2` (`role_id`),
CONSTRAINT `FK_Reference_1` FOREIGN KEY (`menu_id`) REFERENCES `ums_menu` (`menu_id`) ON DELETE RESTRICT ON UPDATE RESTRICT,
CONSTRAINT `FK_Reference_2` FOREIGN KEY (`role_id`) REFERENCES `ums_role` (`role_id`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='角色配置菜单';
/*Data for the table `role_menu` */
insert into `role_menu`(`menu_id`,`role_id`) values (10,2),(11,2),(12,2),(13,2),(14,2),(15,3),(16,3),(17,5),(18,5),(19,5),(30,5),(1,1),(3,1),(8,1),(9,1),(2,1),(4,1),(6,1),(7,1),(25,1),(28,1),(29,1),(10,1),(11,1),(12,1),(13,1),(14,1),(15,1),(16,1),(17,1),(18,1),(19,1),(30,1);
/*Table structure for table `ums_menu` */
DROP TABLE IF EXISTS `ums_menu`;
CREATE TABLE `ums_menu` (
`menu_id` bigint NOT NULL AUTO_INCREMENT COMMENT '菜单ID',
`menu_name` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '菜单名称',
`url` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '前端菜单路径',
`path` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '前端vue-router路径',
`level` int DEFAULT NULL COMMENT '菜单的级别',
`parent_id` bigint DEFAULT '0' COMMENT '上级ID',
`show` int NOT NULL DEFAULT '0' COMMENT '是否显示,0 显示,1 不显示',
`del` varchar(5) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT '1' COMMENT '是否有效',
`createtime` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`menu_id`)
) ENGINE=InnoDB AUTO_INCREMENT=31 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='菜单表(权限)';
/*Data for the table `ums_menu` */
insert into `ums_menu`(`menu_id`,`menu_name`,`url`,`path`,`level`,`parent_id`,`show`,`del`,`createtime`) values (1,'系统管理','xtgl',NULL,1,0,0,'1','2024-11-25 15:13:36'),(2,'基础信息管理','jcxxgl',NULL,NULL,0,0,'1','2024-11-25 15:16:56'),(3,'用户管理','/home/user','ums/user/index.vue',2,1,0,'1','2024-11-25 15:20:17'),(4,'部门管理','/home/dept','base/dept/index.vue',4,2,0,'1','2024-11-25 15:26:11'),(6,'挂号级别','/home/regist_level','base/regist_level/index.vue',2,2,0,'1','2024-11-25 16:08:16'),(7,'常数项类型管理','/home/constants_type','base/constants_type/index.vue',2,2,0,'1','2024-11-25 16:09:45'),(8,'角色管理','/home/role','ums/role/index.vue',2,1,0,'1','2024-11-25 16:10:11'),(9,'菜单管理','/home/menu','ums/menu/index.vue',1,1,0,'1','2024-11-25 16:10:23'),(10,'挂号收费员','ghsfy',NULL,1,0,0,'1','2024-11-28 08:46:54'),(11,'挂号','/home/guahao','guahao/guahao/index.vue',2,10,0,'1','2024-11-28 08:47:14'),(12,'收费','/home/fee','guahao/fee/index.vue',2,10,0,'1','2024-11-28 08:47:28'),(13,'退号','/home/refund_regist','guahao/refund-regist/index.vue',2,10,0,'1','2024-11-28 08:47:49'),(14,'退费','/home/refund','guahao/refund/index.vue',2,10,0,'1','2024-11-28 08:48:01'),(15,'门诊医生','mzys',NULL,1,0,0,'1','2024-11-28 08:48:21'),(16,'门诊病历','/home/doctor','doctor/index.vue',2,15,0,'1','2024-11-28 08:48:33'),(17,'医技医生','yjys','12121212121112',1,0,0,'1','2024-11-28 08:48:59'),(18,'检查处理','/home/checkapply','skill/checkapply/index.vue',2,17,0,'1','2024-11-28 08:49:12'),(19,'检验处理','/home/inspectapply','skill/inspectapply/index.vue',2,17,0,'1','2024-11-28 08:49:30'),(25,'常数项目','/home/constants_item','base/constants_item/index.vue',2,2,1,'1','2024-11-29 08:35:55'),(28,'检查项目管理','/home/checkitem','base/checkitem/index.vue',2,2,0,'1','2024-12-02 13:38:00'),(29,'检验项目管理','/home/inspect','base/inspectitem/index.vue',2,2,0,'1','2024-12-02 13:38:56'),(30,'检查项目列表','/home/checkapplylist','skill/checkapply/check_apply_list.vue',2,17,1,'1','2024-12-05 09:01:02');
/*Table structure for table `ums_role` */
DROP TABLE IF EXISTS `ums_role`;
CREATE TABLE `ums_role` (
`role_id` bigint NOT NULL AUTO_INCREMENT COMMENT '角色ID',
`role_name` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT '角色名称',
`del` varchar(5) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT '1' COMMENT '是否有效',
`createtime` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`role_id`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='角色';
/*Data for the table `ums_role` */
insert into `ums_role`(`role_id`,`role_name`,`del`,`createtime`) values (1,'系统管理员','1','2024-11-25 14:43:37'),(2,'挂号收费员','1','2024-11-25 14:45:05'),(3,'门诊医生','1','2024-11-25 14:45:17'),(5,'医技医生','1','2024-11-25 14:46:23'),(10,'121122','1','2024-11-26 12:25:52');
/*Table structure for table `ums_user` */
DROP TABLE IF EXISTS `ums_user`;
CREATE TABLE `ums_user` (
`userid` bigint NOT NULL AUTO_INCREMENT COMMENT '用户ID',
`username` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '用户名',
`password` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '密码',
`nickname` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '昵称',
`expire` date DEFAULT NULL COMMENT '过期时间',
`lastlogin` datetime DEFAULT NULL COMMENT '最后一次登录时间',
`dept_id` bigint DEFAULT NULL COMMENT '部门ID',
`dept_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '部门名称',
`regist_level` bigint DEFAULT NULL COMMENT '级别ID',
`del` varchar(5) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT '1' COMMENT '是否有效',
`createtime` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`userid`),
KEY `FK_Reference_5` (`dept_id`),
KEY `FK_Reference_6` (`regist_level`),
CONSTRAINT `FK_Reference_5` FOREIGN KEY (`dept_id`) REFERENCES `dept` (`dept_id`) ON DELETE RESTRICT ON UPDATE RESTRICT,
CONSTRAINT `FK_Reference_6` FOREIGN KEY (`regist_level`) REFERENCES `regist_level` (`level_id`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='医生、护士、医技等用户';
/*Data for the table `ums_user` */
insert into `ums_user`(`userid`,`username`,`password`,`nickname`,`expire`,`lastlogin`,`dept_id`,`dept_name`,`regist_level`,`del`,`createtime`) values (1,'admin','123456','系统管理员',NULL,'2024-12-06 15:06:20',1,'心内科',1,NULL,'2024-11-21 14:21:01'),(3,'ssm','123456','孙思邈','2025-04-26','2024-12-06 13:56:59',1,'心内科',1,NULL,'2024-11-22 13:51:33'),(7,'ht','123456','华佗',NULL,'2024-12-03 12:24:56',1,'心内科',1,NULL,'2024-11-25 13:43:59'),(8,'guahao','123456','挂号员','2024-11-29','2024-12-06 11:34:18',5,NULL,1,'1','2024-11-28 08:53:37'),(9,'yiji','123456','霍华德',NULL,'2024-12-06 11:53:09',5,NULL,1,'1','2024-11-28 08:54:20'),(10,NULL,NULL,NULL,NULL,NULL,NULL,NULL,1,'1','2024-11-28 09:26:02');
/*Table structure for table `upload` */
DROP TABLE IF EXISTS `upload`;
CREATE TABLE `upload` (
`upload_id` int NOT NULL AUTO_INCREMENT COMMENT '主键',
`path` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '上传文件的路径',
`origin_name` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '原始文件名',
`ext` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '上传文件的扩展名',
`up_time` datetime DEFAULT NULL COMMENT '上传时间',
`up_user` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '上传的人员',
`up_type` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT 'check inspect',
PRIMARY KEY (`upload_id`)
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='检查或者检查结果';
/*Data for the table `upload` */
insert into `upload`(`upload_id`,`path`,`origin_name`,`ext`,`up_time`,`up_user`,`up_type`) values (1,'3bf84b63fa134b6cb9193692f9469d1d.png','abc','png','2024-12-05 08:53:46','admin','check'),(2,'3bf7d62817af48c1a2c80c503700ee15.png','微信图片_20241017140004.png','.png','2024-12-06 09:07:23','admin',NULL),(3,'86b7f7b1daac48cd84f03e21a895ccbd.png','QQ20241205-140636.png','.png','2024-12-06 09:26:51','admin',NULL),(4,'b14987dace144af890231f51af4cc06d.png','QQ20241205-140636.png','.png','2024-12-06 09:35:57','admin',NULL),(5,'e24f84a934fb4c88bffb63e890c57f45.png','微信图片_20241017140004.png','.png','2024-12-06 09:39:58','admin',NULL),(6,'7c22606b2be2495b9667d3d00c37647a.png','微信图片_20241017140004.png','.png','2024-12-06 09:40:21','admin',NULL),(7,'02614ddfd5454b2593c8b64f3aee2b32.png','QQ20241205-140636.png','.png','2024-12-06 09:40:30','admin',NULL),(8,'3fb36886eda142fb8219f9ef932b6fc1.png','QQ20241205-140636.png','.png','2024-12-06 11:10:27','admin',NULL),(9,'52a90e074d6e4ee8994b5b0dd91941b5.png','微信图片_20241017140004.png','.png','2024-12-06 11:10:32','admin',NULL),(10,'e7a9a25928b5449aa2160cf07d74d48e.png','QQ20241205-140636.png','.png','2024-12-06 11:35:49','yiji',NULL),(11,'8622916fca6e4b73b188e781fa611102.png','微信图片_20241017140004.png','.png','2024-12-06 11:35:52','yiji',NULL),(12,'af95a9d232754335a12545b4b55791fe.png','QQ20241205-140636.png','.png','2024-12-06 11:53:28','yiji',NULL),(13,'6af958a0cfea41afad6b4b513db30570.png','微信图片_20241017140004.png','.png','2024-12-06 11:53:31','yiji',NULL),(14,'51cdd3a8841b4a39bf921e0cd337faa5.png','QQ20241205-140636.png','.png','2024-12-06 11:53:47','yiji',NULL),(15,'56d0d566d07543a7b7a1418cdabedcf9.png','微信图片_20241017140004.png','.png','2024-12-06 11:53:51','yiji',NULL);
/*Table structure for table `user_role` */
DROP TABLE IF EXISTS `user_role`;
CREATE TABLE `user_role` (
`userid` bigint DEFAULT NULL COMMENT '用户ID',
`role_id` bigint DEFAULT NULL COMMENT '角色ID',
KEY `FK_Reference_3` (`userid`),
KEY `FK_Reference_4` (`role_id`),
CONSTRAINT `FK_Reference_3` FOREIGN KEY (`userid`) REFERENCES `ums_user` (`userid`) ON DELETE RESTRICT ON UPDATE RESTRICT,
CONSTRAINT `FK_Reference_4` FOREIGN KEY (`role_id`) REFERENCES `ums_role` (`role_id`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='用户角色';
/*Data for the table `user_role` */
insert into `user_role`(`userid`,`role_id`) values (1,1),(3,3),(7,3),(8,2),(9,5);
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
```
#### 核心的配置文件
> mybatis-config.xml
>
> jdbc、mapper扫描、别名、打印日志
#### 编写 Mapper.java Mapper.xml
使用MybaitsX插件生成


com.neuedu.spring.mybatis

com/neuedu/spring/mybatis/mapper
com.neuedu.spring.mybatis.mapper

基于junit5的测试
```java
package com.neuedu.spring.mybatis.mapper;
import com.neuedu.spring.mybatis.po.Dept;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.io.InputStream;
/**
* @author 金山
* 项目:spring-learn
* site: https://blog.fulfill.com.cn
* 描述
* @data 2025/3/1214:37
*/
class DeptMapperTest {
@Test
void selectByPrimaryKey() throws IOException {
//SqlSessionFactory
String resoueces = "mybatis-config.xml";
InputStream resourceAsStream = Resources.getResourceAsStream(resoueces);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
// SQLSession
SqlSession session = sqlSessionFactory.openSession();
// 获取Mapper 代理对象
DeptMapper deptMapper = session.getMapper(DeptMapper.class);
long id = 1;
Dept dept = deptMapper.selectByPrimaryKey(id);
System.out.println("dept = " + dept);
}
}
```
### 整合Spring
#### spring核心配置文件 spirng-mybatis.xml
1. 配置SqlSessionFactory到IOC容器中
1. 使用mybaits开发的库,专门用户跟spring整合
1. 在IOC容器中注册 Mapper
使用单元测试
> 获取IOC容器中 Mapper
#### 使用mybatis-spring.jar
```xml
org.mybatis
mybatis-spring
2.0.0
```
> 在ioc容器中注册 SqlSessionFactory
在Spring-mybatis.xml 配置文件中声明两个bean (Datasource、SqlSessionFactory)
```xml
```
从容器中获取SqlSessionFactory并创建SqlSession以及Mapper,并调用mapper的方法
```java
//使用 IOC容器中的 SqlSessionFactory
@Test
void selectByPrimaryKeySqlSessionFactory() throws IOException {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-mybatis.xml");
SqlSessionFactory sqlSessionFactory = context.getBean(SqlSessionFactory.class);
// SQLSession
SqlSession session = sqlSessionFactory.openSession();
// 获取Mapper 代理对象
DeptMapper deptMapper = session.getMapper(DeptMapper.class);
long id = 1;
Dept dept = deptMapper.selectByPrimaryKey(id);
System.out.println("dept = " + dept);
}
```
### 基于spring处理mybatis配置文件
将mybaits-config.xml的配置项 交给spring配置

最终的spirng配置文件
```xml
```
测试
```java
package com.neuedu.spring.mybatis.mapper;
import com.neuedu.spring.mybatis.po.Dept;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
/**
* @author 金山
* 项目:spring-learn
* site: https://blog.fulfill.com.cn
* 描述
* @data 2025/3/139:31
*/
@SpringJUnitConfig(locations = "classpath:spring-mybatis.xml")
public class DeptMapperSpringTest {
@Autowired
private DeptMapper deptMapper;
@Test
public void test(){
long id = 1;
Dept dept = deptMapper.selectByPrimaryKey(id);
System.out.println(dept);
}
}
```
# 整合Spring+MyBatis
## 添加依赖 pom.xml
```xml
4.0.0
com.neuedu.spring.mybatis
spring-14-mybatis
1.0-SNAPSHOT
8
8
5.11.4
5.3.39
8.0.33
3.5.19
2.0.0
1.2.24
org.junit.jupiter
junit-jupiter
${junit.version}
test
org.springframework
spring-test
${spring.version}
org.springframework
spring-context
${spring.version}
org.springframework
spring-jdbc
${spring.version}
mysql
mysql-connector-java
${mysql.version}
org.mybatis
mybatis
${mybatis.version}
org.mybatis
mybatis-spring
${mybatis.spring.version}
com.alibaba
druid
${druid.version}
```
## 配置spring的配置文件
- 数据源
- SqlSessionFactory
- Mapper的包扫描
```xml
```
## 生成 Mapper.java Mapper.xml Po

## 测试使用
从容器中获取 Mapper
```java
package com.neuedu.spring.mybatis.mapper;
import com.neuedu.spring.mybatis.po.Dept;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
/**
* @author 金山
* 项目:spring-learn
* site: https://blog.fulfill.com.cn
* 描述
* @data 2025/3/139:31
*/
@SpringJUnitConfig(locations = "classpath:spring-mybatis.xml")
public class DeptMapperSpringTest {
@Autowired
private DeptMapper deptMapper;
@Test
public void test(){
long id = 1;
Dept dept = deptMapper.selectByPrimaryKey(id);
System.out.println(dept);
}
}
```
# 使用配置类整合Spring+mybaits
## 添加依赖 pom.xml
```xml
4.0.0
com.neuedu.spring.mybatis
spring-14-mybatis
1.0-SNAPSHOT
8
8
5.11.4
5.3.39
8.0.33
3.5.19
2.0.0
1.2.24
org.junit.jupiter
junit-jupiter
${junit.version}
test
org.springframework
spring-test
${spring.version}
org.springframework
spring-context
${spring.version}
org.springframework
spring-jdbc
${spring.version}
mysql
mysql-connector-java
${mysql.version}
org.mybatis
mybatis
${mybatis.version}
org.mybatis
mybatis-spring
${mybatis.spring.version}
com.alibaba
druid
${druid.version}
```
## 生成 Mapper.java Mapper.xml Po
从15项目中copy过来的.......

## 配置类
使用配置类替换 配置文件(spirng-mybatis.xml)
```java
package com.neuedu.spring;
import com.alibaba.druid.pool.DruidDataSource;
import org.apache.ibatis.logging.stdout.StdOutImpl;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import javax.sql.DataSource;
/**
* @author 金山
* 项目:spring-learn
* site: https://blog.fulfill.com.cn
* 描述
* @data 2025/3/1310:30
*/
@Configuration
@ComponentScan("com.neuedu.spring")
public class SpringMyBatisConfiguration {
/**
* 数据源
* @return
*/
@Bean
public DataSource dataSource(){
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUsername("root");
dataSource.setPassword("root");
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/his?useSSL=false");
return dataSource;
}
/**
* SqlSessionFactory
* @param dataSource
* @return
* @throws Exception
*/
@Bean
public SqlSessionFactory sqlSessionFactory( DataSource dataSource ) throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
//设置 mybaits的 settingxxxxxx
org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
configuration.setLogImpl(StdOutImpl.class);
sqlSessionFactoryBean.setConfiguration(configuration);
return sqlSessionFactoryBean.getObject();
}
/**
* 扫描 MyBatis中 Mapper的 包,并注册在 IOC容器中
* @param sqlSessionFactory
* @return
*/
@Bean
public MapperScannerConfigurer mapperSanccer(SqlSessionFactory sqlSessionFactory){
MapperScannerConfigurer scannerConfigurer = new MapperScannerConfigurer();
//创建一堆 Mapper的扫描
scannerConfigurer.setBasePackage("com.neuedu.spring.mybatis.mapper");
scannerConfigurer.setSqlSessionFactory(sqlSessionFactory);
return scannerConfigurer;
}
}
```
## 测试使用
从容器中获取 Mapper
```java
package com.neuedu.spring.mybatis.mapper;
import com.neuedu.spring.SpringMyBatisConfiguration;
import com.neuedu.spring.mybatis.po.Dept;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
/**
* @author 金山
* 项目:spring-learn
* site: https://blog.fulfill.com.cn
* 描述
* @data 2025/3/139:31
*/
@SpringJUnitConfig(classes = SpringMyBatisConfiguration.class)
public class DeptMapperSpringTest {
@Autowired
private DeptMapper deptMapper;
@Test
public void test(){
long id = 1;
Dept dept = deptMapper.selectByPrimaryKey(id);
System.out.println(dept);
}
}
```
测试结果
```log
"D:\Program Files\Java\jdk-17\bin\java.exe" -ea -Didea.test.cyclic.buffer.size=1048576 "-javaagent:D:\Program Files\JetBrains\IntelliJ IDEA 2022.1.2\lib\idea_rt.jar=51644:D:\Program Files\JetBrains\IntelliJ IDEA 2022.1.2\bin" -Dfile.encoding=UTF-8 -classpath "C:\Users\Administrator\.m2\repository\org\junit\platform\junit-platform-launcher\1.11.4\junit-platform-launcher-1.11.4.jar;C:\Users\Administrator\.m2\repository\org\junit\platform\junit-platform-engine\1.11.4\junit-platform-engine-1.11.4.jar;C:\Users\Administrator\.m2\repository\org\opentest4j\opentest4j\1.3.0\opentest4j-1.3.0.jar;C:\Users\Administrator\.m2\repository\org\junit\platform\junit-platform-commons\1.11.4\junit-platform-commons-1.11.4.jar;C:\Users\Administrator\.m2\repository\org\apiguardian\apiguardian-api\1.1.2\apiguardian-api-1.1.2.jar;D:\Program Files\JetBrains\IntelliJ IDEA 2022.1.2\lib\idea_rt.jar;D:\Program Files\JetBrains\IntelliJ IDEA 2022.1.2\plugins\junit\lib\junit5-rt.jar;D:\Program Files\JetBrains\IntelliJ IDEA 2022.1.2\plugins\junit\lib\junit-rt.jar;D:\workspace\spring-learn\spring-16-mybatis-javaconfig\target\test-classes;D:\workspace\spring-learn\spring-16-mybatis-javaconfig\target\classes;D:\app\apache-maven-3.9.9\jarrepository\org\junit\jupiter\junit-jupiter\5.11.4\junit-jupiter-5.11.4.jar;D:\app\apache-maven-3.9.9\jarrepository\org\junit\jupiter\junit-jupiter-api\5.11.4\junit-jupiter-api-5.11.4.jar;D:\app\apache-maven-3.9.9\jarrepository\org\opentest4j\opentest4j\1.3.0\opentest4j-1.3.0.jar;D:\app\apache-maven-3.9.9\jarrepository\org\junit\platform\junit-platform-commons\1.11.4\junit-platform-commons-1.11.4.jar;D:\app\apache-maven-3.9.9\jarrepository\org\apiguardian\apiguardian-api\1.1.2\apiguardian-api-1.1.2.jar;D:\app\apache-maven-3.9.9\jarrepository\org\junit\jupiter\junit-jupiter-params\5.11.4\junit-jupiter-params-5.11.4.jar;D:\app\apache-maven-3.9.9\jarrepository\org\junit\jupiter\junit-jupiter-engine\5.11.4\junit-jupiter-engine-5.11.4.jar;D:\app\apache-maven-3.9.9\jarrepository\org\junit\platform\junit-platform-engine\1.11.4\junit-platform-engine-1.11.4.jar;D:\app\apache-maven-3.9.9\jarrepository\org\springframework\spring-test\5.3.39\spring-test-5.3.39.jar;D:\app\apache-maven-3.9.9\jarrepository\org\springframework\spring-core\5.3.39\spring-core-5.3.39.jar;D:\app\apache-maven-3.9.9\jarrepository\org\springframework\spring-jcl\5.3.39\spring-jcl-5.3.39.jar;D:\app\apache-maven-3.9.9\jarrepository\org\springframework\spring-context\5.3.39\spring-context-5.3.39.jar;D:\app\apache-maven-3.9.9\jarrepository\org\springframework\spring-aop\5.3.39\spring-aop-5.3.39.jar;D:\app\apache-maven-3.9.9\jarrepository\org\springframework\spring-beans\5.3.39\spring-beans-5.3.39.jar;D:\app\apache-maven-3.9.9\jarrepository\org\springframework\spring-expression\5.3.39\spring-expression-5.3.39.jar;D:\app\apache-maven-3.9.9\jarrepository\org\springframework\spring-jdbc\5.3.39\spring-jdbc-5.3.39.jar;D:\app\apache-maven-3.9.9\jarrepository\org\springframework\spring-tx\5.3.39\spring-tx-5.3.39.jar;D:\app\apache-maven-3.9.9\jarrepository\com\mysql\mysql-connector-j\8.0.33\mysql-connector-j-8.0.33.jar;D:\app\apache-maven-3.9.9\jarrepository\com\google\protobuf\protobuf-java\3.21.9\protobuf-java-3.21.9.jar;D:\app\apache-maven-3.9.9\jarrepository\org\mybatis\mybatis\3.5.19\mybatis-3.5.19.jar;D:\app\apache-maven-3.9.9\jarrepository\org\mybatis\mybatis-spring\2.0.0\mybatis-spring-2.0.0.jar;D:\app\apache-maven-3.9.9\jarrepository\com\alibaba\druid\1.2.24\druid-1.2.24.jar" com.intellij.rt.junit.JUnitStarter -ideVersion5 -junit5 com.neuedu.spring.mybatis.mapper.DeptMapperSpringTest,test
3月 13, 2025 10:40:33 上午 org.springframework.test.context.support.AbstractTestContextBootstrapper getDefaultTestExecutionListenerClassNames
信息: Loaded default TestExecutionListener class names from location [META-INF/spring.factories]: [org.springframework.test.context.web.ServletTestExecutionListener, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener, org.springframework.test.context.event.ApplicationEventsTestExecutionListener, org.springframework.test.context.support.DependencyInjectionTestExecutionListener, org.springframework.test.context.support.DirtiesContextTestExecutionListener, org.springframework.test.context.transaction.TransactionalTestExecutionListener, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener, org.springframework.test.context.event.EventPublishingTestExecutionListener]
3月 13, 2025 10:40:33 上午 org.springframework.test.context.support.AbstractTestContextBootstrapper getTestExecutionListeners
信息: Using TestExecutionListeners: [org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener@510f3d34, org.springframework.test.context.event.ApplicationEventsTestExecutionListener@7817fd62, org.springframework.test.context.support.DependencyInjectionTestExecutionListener@8297b3a, org.springframework.test.context.support.DirtiesContextTestExecutionListener@2362f559, org.springframework.test.context.transaction.TransactionalTestExecutionListener@b2c9a9c, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener@4c178a76, org.springframework.test.context.event.EventPublishingTestExecutionListener@fa4c865]
Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter.
Creating MapperFactoryBean with name 'checkApplyMapper' and 'com.neuedu.spring.mybatis.mapper.CheckApplyMapper' mapperInterface
Creating MapperFactoryBean with name 'checkitemMapper' and 'com.neuedu.spring.mybatis.mapper.CheckitemMapper' mapperInterface
Creating MapperFactoryBean with name 'constantTypeMapper' and 'com.neuedu.spring.mybatis.mapper.ConstantTypeMapper' mapperInterface
Creating MapperFactoryBean with name 'constantsItemMapper' and 'com.neuedu.spring.mybatis.mapper.ConstantsItemMapper' mapperInterface
Creating MapperFactoryBean with name 'deptMapper' and 'com.neuedu.spring.mybatis.mapper.DeptMapper' mapperInterface
Creating MapperFactoryBean with name 'inspectApplyMapper' and 'com.neuedu.spring.mybatis.mapper.InspectApplyMapper' mapperInterface
Creating MapperFactoryBean with name 'inspectitemMapper' and 'com.neuedu.spring.mybatis.mapper.InspectitemMapper' mapperInterface
Creating MapperFactoryBean with name 'itemUploadMapper' and 'com.neuedu.spring.mybatis.mapper.ItemUploadMapper' mapperInterface
Creating MapperFactoryBean with name 'registLevelMapper' and 'com.neuedu.spring.mybatis.mapper.RegistLevelMapper' mapperInterface
Creating MapperFactoryBean with name 'registerMapper' and 'com.neuedu.spring.mybatis.mapper.RegisterMapper' mapperInterface
Creating MapperFactoryBean with name 'roleMenuMapper' and 'com.neuedu.spring.mybatis.mapper.RoleMenuMapper' mapperInterface
Creating MapperFactoryBean with name 'umsMenuMapper' and 'com.neuedu.spring.mybatis.mapper.UmsMenuMapper' mapperInterface
Creating MapperFactoryBean with name 'umsRoleMapper' and 'com.neuedu.spring.mybatis.mapper.UmsRoleMapper' mapperInterface
Creating MapperFactoryBean with name 'umsUserMapper' and 'com.neuedu.spring.mybatis.mapper.UmsUserMapper' mapperInterface
Creating MapperFactoryBean with name 'uploadMapper' and 'com.neuedu.spring.mybatis.mapper.UploadMapper' mapperInterface
Creating MapperFactoryBean with name 'userRoleMapper' and 'com.neuedu.spring.mybatis.mapper.UserRoleMapper' mapperInterface
3月 13, 2025 10:40:33 上午 org.springframework.context.annotation.ConfigurationClassPostProcessor enhanceConfigurationClasses
信息: Cannot enhance @Configuration bean definition 'springMyBatisConfiguration' since its singleton instance has been created too early. The typical cause is a non-static @Bean method with a BeanDefinitionRegistryPostProcessor return type: Consider declaring such methods as 'static'.
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@10027fc9] was not registered for synchronization because synchronization is not active
3月 13, 2025 10:40:34 上午 com.alibaba.druid.support.logging.JakartaCommonsLoggingImpl info
信息: {dataSource-1} inited
JDBC Connection [com.alibaba.druid.pool.DruidStatementConnection@456abb66] will not be managed by Spring
==> Preparing: select dept_id,dept_name,loc, leader,del,createtime from dept where dept_id = ?
==> Parameters: 1(Long)
<== Columns: dept_id, dept_name, loc, leader, del, createtime
<== Row: 1, 心内科-dao, 201, selective, 1, 2024-11-21 13:56:49
<== Total: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@10027fc9]
Dept [Hash = 1431409351, deptId=1, deptName=心内科-dao, loc=201, leader=selective, del=1, createtime=Thu Nov 21 13:56:49 CST 2024, serialVersionUID=1]
Process finished with exit code 0
```
# MyBatis中Mapper.xml的路径
默认情况 Mapper.java 和 Mapper.xml 应该在相同的类路径下

可以通过设置SqlSessionFactory的 mapperLocations 属性 设置 xml文件的位置
通过如下配置

Mapper.xml 可以 跟Mapper.java 不同路径

如果使用Java注解@bean的方式 声明 SqlSessionFactory对象 可以使用如下方式设置
1. **sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/*.xml"));**
```java
@Bean
public SqlSessionFactory sqlSessionFactory( DataSource dataSource ) throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
//设置 mybaits的 settingxxxxxx
org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
configuration.setLogImpl(StdOutImpl.class);
sqlSessionFactoryBean.setConfiguration(configuration);
//设置 Mapper。xml的位置
sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/*.xml"));
return sqlSessionFactoryBean.getObject();
}
```
# 事务管理
spring-tx 提供了事务相关的操作
> 事务的特性
>
> - 原子性
> - 一致性
> - 持久性
> - 隔离性
Spring为了支持事务管理,专门封装了事务管理对象。我们只要在Spring容器中配置这个对象,即可使用。
在Spring容器中添加事务管理的配置:
```xml
```
在Service组件中,使用@Transactional注解,就可以给业务方法添加事务管理。
```java
@Transactional
public int transferAccounts(Emp emp1,Emp emp2) {
//需要事务管理的业务
}
```
注意:
1. 需要事务管理的service,在方法上加上@Transactional 注解即可。
2. 必须为public方法才行,不要捕捉异常,要让异常自动抛出,否则不能进行事务回滚。
# 使用事务管理器
需求
> 将ID 为 1 部门 loc 201 改成 301
> 将ID 为 2 部门 loc 201 改成 401
```java
package com.neuedu.spring.mybatis.service;
/**
* @author 金山
* 项目:spring-learn
* site: https://blog.fulfill.com.cn
* 描述
* @data 2025/3/1313:43
*/
public interface IDeptService {
public void changeDeptLoc(int numa,int numb);
}
```
```java
package com.neuedu.spring.mybatis.service.impl;
import com.neuedu.spring.mybatis.mapper.DeptMapper;
import com.neuedu.spring.mybatis.po.Dept;
import com.neuedu.spring.mybatis.service.IDeptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* @author 金山
* 项目:spring-learn
* site: https://blog.fulfill.com.cn
* 描述
* @data 2025/3/1313:44
*/
@Service
public class DeptServiceImpl implements IDeptService {
@Autowired
DeptMapper deptMapper;
/**
* 将ID 为 1 部门 loc 201 改成 301
* 将ID 为 2 部门 loc 201 改成 401
*/
@Override
public void changeDeptLoc(int numa,int numb) {
//ID1
Dept dept1 = deptMapper.selectByPrimaryKey(1L);
//将ID 为 1 部门 loc 201 改成 301
dept1.setLoc("301");
int updateId1Count = deptMapper.updateByPrimaryKey(dept1);
System.out.println("中间有一些操作");
int result = numa / numb;
//ID5
Dept dept5 = deptMapper.selectByPrimaryKey(5L);
//将ID 为 2 部门 loc 201 改成 401
dept5.setLoc("401");
int updateId5Count = deptMapper.updateByPrimaryKey(dept5);
}
}
```
基于xml文件的配置
> 基于 spring-15-mybatis-xml-clean 项目 开发
- 编写Service
- changeDeptLoc()
- 编写切面在某一些service的方法上开启事务
```java
package com.neuedu.spring.mybatis.service.impl;
import com.neuedu.spring.mybatis.mapper.DeptMapper;
import com.neuedu.spring.mybatis.po.Dept;
import com.neuedu.spring.mybatis.service.IDeptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
* @author 金山
* 项目:spring-learn
* site: https://blog.fulfill.com.cn
* 描述
* @data 2025/3/1313:44
*/
@Service
public class DeptServiceImpl implements IDeptService {
@Autowired
DeptMapper deptMapper;
/**
* 将ID 为 1 部门 loc 201 改成 301
* 将ID 为 2 部门 loc 201 改成 401
*/
@Transactional
@Override
public void changeDeptLoc(int numa,int numb) {
//ID1
Dept dept1 = deptMapper.selectByPrimaryKey(1L);
//将ID 为 1 部门 loc 201 改成 301
dept1.setLoc("301");
int updateId1Count = deptMapper.updateByPrimaryKey(dept1);
System.out.println("中间有一些操作");
int result = numa / numb;
//ID5
Dept dept5 = deptMapper.selectByPrimaryKey(5L);
//将ID 为 2 部门 loc 201 改成 401
dept5.setLoc("401");
int updateId5Count = deptMapper.updateByPrimaryKey(dept5);
}
}
```
- 在 spring的配置文件中配置 事务管理Bean, 设置 注解驱动
```xml
```
测试
```java
package com.neuedu.spring.mybatis.service.impl;
import com.neuedu.spring.mybatis.service.IDeptService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import static org.junit.jupiter.api.Assertions.*;
/**
* @author 金山
* 项目:spring-learn
* site: https://blog.fulfill.com.cn
* 描述
* @data 2025/3/1313:47
*/
@SpringJUnitConfig(locations = "classpath:spring-mybatis.xml")
class DeptServiceImplTest {
@Autowired
IDeptService deptService;
@Test
void changeDeptLoc() {
//调用serivce 方法测试
deptService.changeDeptLoc(10,20);
//中间可能产生错误的 有错误,事务不会提交, 没有事务 第一个会改成301 ,第二个不会改
// deptService.changeDeptLoc(0,0);
}
}
```
1、脏读:脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。
2 不可重复读:是指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。
说法一:事务 A 根据条件查询得到了 N 条数据,但此时事务 B 删除或者增加了 M 条符合事务 A 查询条件的数据,这样当事务 A 再次进行查询的时候真实的数据集已经发生了变化,但是A却查询不出来这种变化,因此产生了幻读。
这一种说法强调幻读在于某一个范围内的数据行变多或者是变少了,侧重说明的是数据集不一样导致了产生了幻读。
说法二:幻读并不是说两次读取获取的结果集不同,幻读侧重的方面是某一次的 select 操作得到的结果所表征的数据状态无法支撑后续的业务操作。更为具体一些:A事务select 某记录是否存在,结果为不存在,准备插入此记录,但执行 insert 时发现此记录已存在,无法插入,此时就发生了幻读。产生这样的原因是因为有另一个事务往表中插入了数据。
说法二这种情况也属于幻读,说法二归根到底还是数据集发生了改变,查询得到的数据集与真实的数据集不匹配。
对于说法二:当进行INSERT的时候,也需要隐式的读取,比如插入数据时需要读取有没有主键冲突,然后再决定是否能执行插入。如果这时发现已经有这个记录了,就没法插入。所以,SELECT 显示不存在,但是INSERT的时候发现已存在,说明符合条件的数据行发生了变化,也就是幻读的情况,而不可重复读指的是同一条记录的内容被修改了。
> 在 MySQL 和 Oracle 中,默认的隔离级别是不同的:
>
> MySQL: 默认的隔离级别是可重复读(Repeatable Read)。这意味着当你启动一个事务时,MySQL 会使用可重复读来执行事务,这有助于避免不可重复读问题。
>
> Oracle: 默认的隔离级别是读已提交(Read Committed)。Oracle数据库在不同的时间点使用不同的默认隔离级别,但通常情况下,对于大多数会话,它默认使用读已提交的隔离级别。
>
>