!!!!!!吐血总结SSM(Spring SpringMVC Mybatis),万字血书!!!!!!

SSM

一、Spring

1、简介

Spring是一个分层的JavaSE/EE full-stack(一站式) 轻量级开源框架。

2、特点

1.方便解耦,简化开发

2.AOP编程的支持

3.声明式事务的支持

4.方便程序的测试

5.方便集成各种优秀框架

6.降低Java EE API的使用难度

3、组织架构

在这里插入图片描述

ORM- object relation mapping

OXM-Object xml mapping

JMS - Java消息服务(Java Message Service ,JMS)

WebSocket protocol 是HTML5一种新的协议。它实现了浏览器与服务器全双工通信(full-duplex)。一

开始的握手需要借助HTTP请求完成。Socket是传输控制层协议,WebSocket是应用层协议。

Portlet是一种Web组件-就像servlets-是专为将合成页面里的内容聚集在一起而设计的。通常请求一

个portal页面会引发多个portlets被调用。每个portlet都会生成标记段,并与别的portlets生成的标记段

组合在一起嵌入到portal页面的标记内

spring全家桶:spring,Spring Data、Spring MVC、Spring Boot、Spring Cloud(微服务)

4、核心模块

-spring-core:依赖注入IOC与DI的最基本实现

- spring-beans:Bean工厂与bean的装配

- spring-context:spring的context上下文即IoC容器

- spring-context-support

- spring-expression:spring表达式语言

5、IOC

IOC是 Inverse of Control 的简写,意思是控制反转。是降低对象之间的耦合关系的设计思想。

DI是Dependency Injection的缩写,意思是依赖注入,说的是创建对象实例时,同时为这个对象注入它所依赖的属性

实现过程:

1.导入依赖包:

<!-- Spring的核心工具包--> 
    <dependency>
    <groupId>org.springframework</groupId> 
    <artifactId>spring-core</artifactId> 
    <version>5.0.8.RELEASE</version>
    </dependency> 
    <!--在基础IOC功能上提供扩展服务,还提供许多企业级服务的支持,有邮件服务、 任务调度、远程访问、缓存以及多种视图层框架的支持--> 
    <dependency> 
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId> 
    <version>5.0.8.RELEASE</version>
    </dependency>
    <!-- Spring IOC的基础实现,包含访问配置文件、创建和管理bean等 --> 
    <dependency>
    <groupId>org.springframework</groupId> 
    <artifactId>spring-beans</artifactId> 
    <version>5.0.8.RELEASE</version>
    </dependency> 
    <!-- Spring context的扩展支持,用于MVC方面 --> 
    <dependency> 
    <groupId>org.springframework</groupId>
    <artifactId>spring-context-support</artifactId>
    <version>5.0.8.RELEASE</version> 
    </dependency> 
    <!-- Spring表达式语言 --> 
    <dependency> 
    <groupId>org.springframework</groupId> 
    <artifactId>spring-expression</artifactId> 
    <version>5.0.8.RELEASE</version>
    </dependency>

2.在resource下面创建配置文件:application.xml

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> 
</beans>

3.在配置文件中创建对象

<bean id="对象名" class="类的完整路径"> 
    <property name="属性名" ref="对象的id值"></property>
</bean>

4.加载配置文件,获取对象

ApplicationContext app=new ClassPathXmlApplicationContext("spring.xml"); 
Users users=(Users)app.getBean("u1");
bean标签的属性:

在这里插入图片描述

对象的创建方式:

(1)无参构造

(2)有参构造

public Person(String name , Car car){ 
    this.name = name; 
    this.car = car; 
    System.out.println("Person的有参构造方法:"+name+car); 
} 
<bean name="person" class="com.java.spring.bean.Person"> 
    <constructor-arg name="name" value="rose"/> <constructor-arg name="car"ref="car"/> </bean>

(3)静态方法创建对象

public class PersonFactory { 
    public static Person createPerson(){
        System.out.println("静态工厂创建Person"); 
        return new Person(); 
    } 
}

<!--factorymethod指的是类中的方法名-->
<bean name="pf" class="com.java.PersonFactory" factory-method="createPerson" />

(4)非静态工厂方法

public class Users{
    public Person createPerson1(){
        System.out.println("非静态工厂创建Person"); 
        return new Person(); 
    }
}
<!--factorymethod指的是类中的方法名-->
<bean id="u2" class="com.java.bean.Users"></bean>
<bean id="u3" factorymethod="createPerson1" factory-bean="u2"></bean>
SpringBean的生命周期

在这里插入图片描述

1)根据配置情况调用 Bean 构造方法或工厂方法实例化 Bean。 
2)利用依赖注入完成 Bean 中所有属性值的配置注入。
3)如果 Bean 实现了 BeanNameAware 接口,则 Spring 调用 Bean 的 setBeanName() 方法传入当前
Bean 的 id 值。
4)如果 Bean 实现了 BeanFactoryAware 接口,则 Spring 调用 setBeanFactory() 方法传入当前工厂
实例的引用。
5)如果 Bean 实现了 ApplicationContextAware 接口,则 Spring 调用 setApplicationContext() 方法传入当前 ApplicationContext 实例的引用。
6)如果 BeanPostProcessor 和 Bean 关联,则 Spring 将调用该接口的预初始化方postProcessBeforeInitialzation() 对 Bean 进行加工操作,此处非常重要,Spring 的 AOP 就是利用它
实现的。
7)如果 Bean 实现了 InitializingBean 接口,则 Spring 将调用 afterPropertiesSet() 方法。初始化bean的时候执行,可以针对某个具体的bean进行配置。afterPropertiesSet 必须实现 InitializingBean
接口。实现 InitializingBean接口必须实现afterPropertiesSet方法。
8)如果在配置文件中通过 init-method 属性指定了初始化方法,则调用该初始化方法。
9)如果 BeanPostProcessor 和 Bean 关联,则 Spring 将调用该接口的初始化方法postProcessAfterInitialization()。此时,Bean 已经可以被应用系统使用了。
10)如果在 中指定了该 Bean 的作用范围为 scope="singleton",则将该 Bean 放入 Spring IoC 的缓
存池中,将触发 Spring 对该 Bean 的生命周期管理;如果在 中指定了该 Bean 的作用范围为
scope="prototype",则将该 Bean 交给调用者,调用者管理该 Bean 的生命周期,Spring 不再管理该 
Bean。
11)如果 Bean 实现了 DisposableBean 接口,则 Spring 会调用 destory() 方法将 Spring 中的 Bean销毁;如果在配置文件中通过 destory-method 属性指定了 Bean 的销毁方法,则 Spring 将调用该方
法对 Bean 进行销毁。

6、DI

分类:一种是调取属性的set方法赋值,第二种使用构造方法

<?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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">

   <!--DI赋值-->
   <bean id="stu1" class="com.java.bean.Student">
       <!--基本属性赋值-->
       <property name="stuname" value="张三"></property>
   </bean>
    <!--引用属性赋值-->
    <bean id="stu" class="com.java.bean.Student">
        <property name="stuname" ref="stu1"></property>
    </bean>
    <!--通过name属性,按照参数名赋值-->
    <bean id="stu2" class="com.java.bean.Student">
        <constructor-arg name="sex" value="" ></constructor-arg>
        <constructor-arg name="age" value="19" ></constructor-arg>
        <!--spel spring表达式赋值-->
        <constructor-arg name="stuname" value="#{stu1.stuname}"></constructor-arg>
    </bean>
    <!--P命名空间注入值-->
 <bean id="stu3" class="com.xzk.bean.Student" p:stuname="aa" p:age="18" p:sex="" ></bean>
</beans>

注意:P命名空间注入值:

基本类型值:

p:属性名=“值”- 引用类型值:

P:属性名-ref=“bean名称”

实现步骤:配置文件中 添加命名空间p

xmlns:p="http://www.springframework.org/schema/p"
复杂类型的赋值:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="t1" class="com.java.bean.Teacher">
        <!--数组类型赋值-->
        <property name="obj">
            <list>
                <value>张三</value>
                <value>12313</value>
                <value>qsghs</value>
<!--               <ref bean="u2"></ref>-->
            </list>
        </property>
        <!--List类型赋值-->
        <property name="list">
            <list>
                <value>张三1</value>
                <value>123</value>
                <value>qss</value>
<!--                <ref bean="u2"></ref>-->
            </list>
        </property>
        <!--Set类型-->
        <property name="set">
            <set>
                <value>张三2</value>
                <value>122</value>
                <value>qsa</value>
<!--                <ref bean="u2"></ref>-->
            </set>
        </property>
        <!--Map类型赋值-->
        <property name="map">
            <map>
                <entry key="username" value="李四"></entry>
                <entry key="age" value="8855"></entry>
<!--                <entry key="user" value-ref="u1"></entry>-->
            </map>
        </property>
        <!--属性类型赋值-->
        <property name="properties">
            <props>
                <prop key="username">王五</prop>
                <prop key="password">145632</prop>
            </props>
        </property>
    </bean>

</beans>

获取值:

public static void main(String[] args) {
        //1.加载配置文件
        ApplicationContext app=new ClassPathXmlApplicationContext("application.xml");
        Teacher t=(Teacher) app.getBean("t1");
        //2.得到对象中的信息
        System.out.println("--------------数组------------");
        Object[] objects = t.getObj();
        for (Object object : objects) {
            System.out.println(object);
        }
        System.out.println("--------------List------------");
        List list = t.getList();
        for (Object o : list) {
            System.out.println(o);
        }
        System.out.println("--------------Set---------------");
        Set set = t.getSet();
        for (Object o : set) {
            System.out.println(o);
        }
        System.out.println("-----------------Map--------------");
        Map map = t.getMap();
        Set keySet = map.keySet();
        Iterator iterator = keySet.iterator();
        while(iterator.hasNext()){
            String key=(String)  iterator.next();
            System.out.println(key+","+map.get(key));
        }
        System.out.println("----------Properties-----------");
        Properties properties = t.getProperties();
        System.out.println(properties.getProperty("username"));
        System.out.println(properties.getProperty("password"));
    }

7、自动注入

autowire:

no 不自动装配(默认值)

byName 属性名=id名 ,调取set方法赋值

byType 属性的类型和id对象的类型相同,当找到多个同类型的对象时报错,调取set方法赋值

constructor 构造方法的参数类型和id对象的类型相同,当没有找到时,报错。调取构造方法赋值

示例:

<bean id="service" class="service.impl.UserServiceImpl" autowire="constructor"> </bean>

配置全局自动装配:

<beans default-autowire="constructor/byName/byType/no">

8、注解实现IOC

1、添加依赖:

pom.xml中:
spring-framework-5.0.8.RELEASE\docs\spring-framework-
reference\html\xsdconfiguration.html
application.xml中:
    xmlns:context="http://www.springframework.org/schema/context" 				
	http://www.springframework.org/schema/context 	
	http://www.springframework.org/schema/context/spring-context.xsd

2、配置注解扫描:指定扫描包下所有类中的注解,扫描包时,会扫描包所有的子孙包:

<!--扫描包设置--> 
<context:component-scan base-package="com.java"></context:component- scan>

3、注解:

  • 注解在类名上:
@Component("对象名") 
@Service("person") // service层 
@Controller("person") // controller层 
@Repository("person") // dao层 
@Scope(scopeName="singleton") //单例对象
@Scope(scopeName="prototype") //多例对象
  • 注解在属性上:
@Value("属性值") 
private String name;
@Autowired //如果一个接口类型,同时有两个实现类,则报错,此时可以借助@Qualifier("bean name") 
@Qualifier("bean name") 
private Car car;
//说明:@Resource 是java的注释,但是Spring框架支持,@Resource指定注入哪个名称的对象 //@Resource(name="对象名") == @Autowired + @Qualifier("name") 
@Resource(name="baoma") 
private Car car;
  • 注解在方法上
@PostConstruct //等价于init-method属性 
public void init(){ 
    System.out.println("初始化方法"); 
}
@PreDestroy //等价于destroy-method属性
public void destroy(){
    System.out.println("销毁方法"); 
}

9、AOP

AOP(Aspect Oriented Programming)即面向切面编程。即在不改变原程序的基础上为代码段增加新

的功能。应用在权限认证、日志、事务。

JDK代理模式:

针对实现了接口的类产生代理。InvocationHandler接口。

  • 创建接口和对应实现类
public interface UserService { 
    public void login(); 
}
//实现类
public class UserServiceImpl implements UserService {
    public void login(){
        System.out.println("UsersDaoImpl");
    } 
}
  • 创建动态代理类,实现InvocationHandler接口
public class agency implements InvocationHandler { 
    private UserService target; //目标对象 
    public agency(UserService target){
        this.target = target; 
    }
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 
    //本方法中的其他输出输入增强 
    //proxy 代理方法被调用的代理实例 
    System.out.println("方法触发了");
    //执行被代理类 原方法 
    Object invoke = method.invoke(target, args); 
    System.out.println("执行完毕了"); 
    return invoke; 
} 
}
  • 测试
//测试JDK动态代理技术 
UserService us = new UserServiceImpl(); 
agency ag = new agency(us); 
//这里不能转换成一个实际的类,必须是接口类型 
UserService uservice = (UserService)Proxy.newProxyInstance(us.getClass().getClassLoader(),us.getClass().getInterfaces(),ag); 
uservice.login();
CGlib代理模式:

针对没有实现接口的类产生代理,应用的是底层的字节码增强的技术 生成当前类的子类对象,MethodInterceptor接口

  • 导入依赖包
<dependency> 
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId> 
    <version>3.2.5</version>
</dependency
  • 创建实体类
public class Users{ public void login(){} }
  • 创建CGlib代理对象
class CgProxy implements MethodInterceptor { 
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("输出语句1");
        //参数:Object为由CGLib动态生成的代理类实例,Method为上文中实体类所调用的被代理的方法 //引用,Object[]为参数值列表,MethodProxy为生成的代理类对方法的代理引用。 
        Object obj= methodProxy.invokeSuper(o,objects);
        System.out.println("输出语句2"); 
        return obj; 
    } 
}
  • 测试
public static void main(String[] args) {
    //1.创建真实对象 
    Users users = new Users();
    //2.创建代理对象
    Enhancer enhancer = new Enhancer();
    enhancer.setSuperclass(users.getClass()); 
    enhancer.setCallback(new CglibProxy());
    Users o = (Users) enhancer.create();//代理对象 
    o.login();
}
区别:

1、jdk动态代理生成的代理类和委托类实现了相同的接口;

2、cglib动态代理中生成的字节码更加复杂,生成的代理类是委托类的子类,且不能处理被fifinal关键字

修饰的方法;

3、jdk采用反射机制调用委托类的方法,cglib采用类似索引的方式直接调用委托类方法;

Spring中使用AOP

1.导入依赖包

 <dependencies>
        <dependency>
            <groupId>aopalliance</groupId>
            <artifactId>aopalliance</artifactId>
            <version>1.0</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.13</version>
        </dependency>
        <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
        <version>5.0.8.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>5.0.8.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>5.0.8.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.0.8.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>5.0.8.RELEASE</version>
        </dependency>
        <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context-support</artifactId>
            <version>5.0.8.RELEASE</version>
        </dependency>
    </dependencies>

2.创建接口和实现类:

//User dao层接口和实现类
public interface UserDao {
    public  void test1();
}
public class UserDaoImpl  implements UserDao {
    public void test1() {
        System.out.println("userTest1------");
    }
}
//User  service层接口和实现类
public interface UserService {
    public  void test1();
}
public class UserServiceImpl  implements UserService {
    private UserDao dao;

    public void setDao(UserDao dao) {
        this.dao = dao;
    }

    public void test1() {
        System.out.println("userserviceTest1-----");
        dao.test1();
    }
}
//创建Aop的增强类
public class MyAop {
    //前置增强,读取目标方法之前执行
    public void before(){
        System.out.println("日志开始-----");
    }
    //后置增强,读取目标方法之后执行
    public  void after(){
        System.out.println("日志结束-----");
    }
}


3.添加application.xml配置文件并且配置对应参数

<?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:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-4.2.xsd">

    <bean id="udao" class="com.java.dao.impl.UserDaoImpl"></bean>
    <bean id="uservice" class="com.java.service.impl.UserServiceImpl">
        <property name="dao" ref="udao"></property>
    </bean>

    <!--创建增强类的对象-->
    <bean id="myaop" class="com.java.util.MyAop"></bean>
    <!--建立增强类和目标方法之间的关系-->
    <aop:config>
        <aop:pointcut id="mypc" expression="execution(public void  com.java.service.UserService.test1())"></aop:pointcut>
        <aop:aspect ref="myaop">
            <!--前置增强-->
            <aop:before method="before" pointcut-ref="mypc"></aop:before>
            <!--后置增强-->
            <aop:after-returning method="after" pointcut-ref="mypc"></aop:after-returning>
        </aop:aspect>
    </aop:config>
</beans>

4.测试

public class Test1 {
    public static void main(String[] args) {
        //创建对象
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("application.xml");
        UserService userService = (UserService)applicationContext.getBean("uservice");
        userService.test1();
    }
}

在这里插入图片描述

增强类的类型:

//前置通知:目标方法运行之前调用 aop:before

//后置通知(如果出现异常不会调用):在目标方法运行之后调用 aop:after-returning

//环绕通知:在目标方法之前和之后都调用 aop:around

//最终通知(无论是否出现 异常都会调用):在目标方法运行之后调用 aop:after

//异常增强:程序出现异常时执行(要求:程序代码中不要处理异常) aop:after-throwing

表达式定义:

例如:expression=“execution(public void com.java.service.UserService.test1())”

1、public * addUser(com.pb.entity.User):“*”表示匹配所有类型的返回值

2、public void (com.pb.entity.User):“”表示匹配所有方法名。

3、public void addUser (…):“…”表示匹配所有参数个数和类型

4、* com.pb.service..(…):匹配com.pb.service 包下所有类的所有方法

5、* com.pb.service…*(…):匹配com.pb.service 包及子包下所有类的所有方法

获取切点信息:

使用JoinPoint。

 public void before(JoinPoint joinPoint){
       System.out.println("日志开始-----");
       System.out.println(new Date()+"切点对象信息:"+joinPoint.getTarget().getClass().getSimpleName());
       System.out.println("方法信息:"+joinPoint.getSignature());
       System.out.println("参数信息:"+joinPoint.getArgs());
    }
特殊的前置增强Advisor前置增强
  • 创建实现类:MethodBeforeAdvice
public class BeforeAop  implements MethodBeforeAdvice {
    @Override
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println("特殊的前置增强");
        System.out.println("目标方法:"+method.getName());
    }
}

  • 修改配置文件
<?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:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-4.2.xsd">

    <bean id="udao" class="com.java.dao.impl.UserDaoImpl"></bean>
    <bean id="uservice" class="com.java.service.impl.UserServiceImpl">
        <property name="dao" ref="udao"></property>
    </bean>

    <!--创建增强类的对象-->
    <bean id="myaop" class="com.java.util.MyAop"></bean>
    <bean id="before" class="com.java.util.BeforeAop"></bean>
    <!--建立增强类和目标方法之间的关系-->
    <aop:config>
        <aop:pointcut id="mypc" expression="execution(* com.java.service.*.*(..))"></aop:pointcut>
        <aop:advisor advice-ref="before" pointcut-ref="mypc"></aop:advisor>
    </aop:config>
</beans>

注解方式中注解的顺序问题:

  • 1.没有异常情况下
  • 环绕开始。。。。
  • 前置增强开始执行
  • insert-----------
  • 环绕结束。。。。
  • 最终增强
  • 后置增强开始执行
  • 相对顺序固定,注解换位置时不影响结果顺序
  • 2.有异常
  • 前置增强开始执行
  • insert-----------
  • 最终增强
  • 异常增强
  • 注意:不要使用环绕增强,使用的话,异常增强不执行

在这里插入图片描述

注意:

aop的应用场景:事务底层实现,日志,权限控制,mybatis中sql绑定,性能检测

10、Spring连接JDBC

  • 导入依赖包

Mysql 5版本:

<dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.0.8.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.46</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>5.0.8.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.0.8.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>com.mchange</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.5.2</version>
        </dependency>
    </dependencies>

测试:

public static void main(String[] args) throws PropertyVetoException {
        //创建数据库连接池对象
        ComboPooledDataSource dataSource=new ComboPooledDataSource();
        dataSource.setDriverClass("com.mysql.jdbc.Driver");
        dataSource.setJdbcUrl("jdbc:mysql//localhost:3306/user?userUnicode=true&characterEncoding=utf-8");
        dataSource.setUser("root");
        dataSource.setPassword("123456");
        //创建工具类
        JdbcTemplate jdbcTemplate = new JdbcTemplate();

        //调用方法,增删改查用update  查询用query方法
        int update = jdbcTemplate.update("insert into student values(1,'stu11','haha')");
        System.out.println(update);
    }

11、事务管理

通过sql将逻辑相关的一组操作绑定在一起,以便服务器 保持数据的完整性(准确性)。

事务通常是以begin transaction开始,以commit或rollback结束。

事务执行的流程:开启事务->执行insert,update,delete->commit/rollback

原因:

(1)为了提高性能

(2)为了保持业务流程的完整性

(3)使用分布式事务

特性:

1 - 原子性(atomicity)

事务是数据库的逻辑工作单位,而且是必须是原子工作单位,对于其数据修改,要么全部执行,要么全部不执行。

2、一致性(consistency)

事务在完成时,必须是所有的数据都保持一致状态。在相关数据库中,所有规则都必须应用于事务的修改,以保持所有数据的完整性。

3、隔离性(isolation)

一个事务的执行不能被其他事务所影响。企业级的数据库每一秒钟都可能应付成千上万的并发访问,因而带来了并发控制的问题。

4、持久性(durability)

一个事务一旦提交,事务的操作便永久性的保存在DB中。即使此时再执行回滚操作也不能撤消所做的更改。

注意:

spring事务是基于代理来实现的,所以:

(1)private、fifinal、static 方法无法被代理,所以添加事务无效。

(2)当绕过代理对象, 直接调用添加事务管理的方法时, 事务管理将无法生效。比如直接new出的对象。

(3)在同一个类下,有2个方法,A、B,A没有事务,B有事务,但是A调用B时,方法B被标记的事务无效。 究其原因,因为此类的调用对象为代理对象,代理方法A调用真正的被代理方法A后,在被代理方法A中才会去调用方法B,此时this对象为被代理的对象,所以是不会通知到代理对象,也就变成了第二种情况,绕过了代理对象。所以无效。

隔离级别:
  1. Serializable(串行化):可避免脏读、不可重复读,幻读情况的发生。

  2. Repeatable read(可重复读):可避免脏读、不可重复读情况的发生。

  3. Read committed(读已提交):可避免脏读情况发生。

  4. Read uncommitted(读未提交):最低级别,以上情况均无法保证。

Spring实现事务管理:

添加依赖:

<dependency>
    <groupId>org.aspectj</groupId> 
    <artifactId>aspectjweaver</artifactId>
    <version>1.8.13</version> 
</dependency>

事务属性介绍:

package org.springframework.transaction; 
public interface TransactionDefinition {
    int PROPAGATION_REQUIRED = 0; //支持当前事务,如果不存在,就新建一个 
    int PROPAGATION_SUPPORTS = 1; //支持当前事务,如果不存在,就不使用事务 
    int PROPAGATION_MANDATORY = 2; //支持当前事务,如果不存在,就抛出异常
    int PROPAGATION_REQUIRES_NEW = 3;//如果有事务存在,挂起当前事务,创建一个新的事物 
    int PROPAGATION_NOT_SUPPORTED = 4;//以非事务方式运行,如果有事务存在,挂起当前事务 
    int PROPAGATION_NEVER = 5;//以非事务方式运行,如果有事务存在,就抛出异常
    int PROPAGATION_NESTED = 6;//如果有事务存在,则嵌套事务执行 
    int ISOLATION_DEFAULT = -1;//默认级别,MYSQL: 默认为REPEATABLE_READ级别 SQLSERVER: 默认为READ_COMMITTED
    int ISOLATION_READ_UNCOMMITTED = 1;//读取未提交数据(会出现脏读, 不可重复读) 基本不使用
    int ISOLATION_READ_COMMITTED = 2;//读取已提交数据(会出现不可重复读和幻读) 
    int ISOLATION_REPEATABLE_READ = 4;//可重复读(会出现幻读) 
    int ISOLATION_SERIALIZABLE = 8;//串行化 
    int TIMEOUT_DEFAULT = -1;//默认是-1,不超时,单位是秒
    //事务的传播行为
    int getPropagationBehavior(); 
    //事务的隔离级别 
    int getIsolationLevel(); 
    //事务超时时间 
    int getTimeout(); 
    //是否只读
    boolean isReadOnly(); 
    String getName(); }

添加配置:

<!-- 平台事务管理器 --> 
<bean id="transactionManager class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 
    <property name="dataSource" ref="dataSource"/>
</bean> 
 <!-- 通知 --> 
<tx:advice id="txAdvice" transaction-manager="transactionManager"> 
<tx:attributes> 
<!-- 传播行为:propagation 不是必须的,默认值是REQUIRED -->
<!-- REQUIRED:如果有事务,则在事务中执行;如果没有事务,则开启一个新的事务 --> 
<tx:method name="save*" propagation="REQUIRED" />
 <!-- SUPPORTS:如果有事务,则在事务中执行;如果没有事务,则不会开启事务 --> 
<tx:method name="find*" propagation="SUPPORTS" read-only="true" />
</tx:attributes> 
 </tx:advice> <aop:config> <aop:pointcut id="txPointCut" expression="execution(* com.service.*.* (..))" /><aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/> </aop:config>

二、Spring MVC

1、Web请求过程

在这里插入图片描述

2、核心组件

DispatcherServlet:作为前端控制器,整个流程控制的中心,控制其它组件执行,统一调度,降低组件之间的耦合 性,提高每个组件的扩展性。

HandlerMapping:通过扩展处理器映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式 等。

HandlAdapter:通过扩展处理器适配器,支持更多类型的处理器,调用处理器传递参数等工作!

ViewResolver:通过扩展视图解析器,支持更多类型的视图解析,例如:jsp、freemarker、pdf、excel等

3、Spring Mvc执行过程

在这里插入图片描述

4、框架搭建

1、创建项目:webapp。

2、在main目录下面新建java和resources目录,并且编译

java目录:
在这里插入图片描述

resources目录:

在这里插入图片描述

3、添加依赖包

 <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.1.0</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
    <version>5.0.8.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.0.8.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context-support</artifactId>
      <version>5.0.8.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>5.0.8.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>jstl</artifactId>
      <version>1.2</version>
    </dependency>

4、修改web.xml文件

  <servlet>
    <servlet-name>aa</servlet-name>
    <servlet-class>
      org.springframework.web.servlet.DispatcherServlet
    </servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:springmvc.xml</param-value>
    </init-param>
  </servlet>
  <servlet-mapping>
    <servlet-name>aa</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>

注意:/和/*的区别

< url-pattern > / </ url-pattern > 不会匹配到*.jsp,即:*.jsp不会进入spring的 DispatcherServlet类 。

< url-pattern > /* </ url-pattern > 会匹配*.jsp,会出现返回jsp视图时再次进入spring的DispatcherServlet 类, 导致找不到对应的controller所以报404错。

可以配置/ ,此工程 所有请求全部由springmvc解析,此种方式可以实现 RESTful方式,需要特殊处理对静态文件 的解析不能由springmvc解析

可以配置*.do*或.action,所有请求的url扩展名为.do或.action由springmvc解析,此种方法常用

不可以/,如果配置/,返回jsp也由springmvc解析,这是不对的。

5、修改spring配置文件

<?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:context="http://www.springframework.org/schema/context"
        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" >

    <!--1、扫描注解包-->
    <context:component-scan base-package="com.java"></context:component-scan>
    <!--2、创建视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--用来指定结果页面的前缀和后缀-->
        <property name="prefix" value="/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>
</beans>

6、创建控制器类

1.@Controller

2.@RequestMapping(“请求地址”)

* 加在类上: 给模块添加根路径

* 加载方法: 方法具体的路径

设置@RequestMapping method属性

@RequestMapping(method=RequestMethod.GET,value=“请求名”)

@Controller
public class MyController {

    @RequestMapping("/test")
    public  String test1(){
        System.out.println("test1被执行了-----");
        //return 的是结果页面的名称
        // -->因为在springmvc.xml配置文件中制定了前缀和后缀,所以最后呈现的是/success.jsp
        return  "success";
    }
}

执行过程:首先访问index.jsp --> 访问web.xml -->跳转DispatcherServlet和springmvc.xml -->访问Mycontroller -->访问success.jsp

5、获取前端的数据

(1)HttpServletRequest

(2)页面传值时的key=处理请求的方法的参数名

<html>
<body>
<h2>Hello World!</h2>
<a href="/test?username=yyy&age=10">test</a>
</body>
</html>
//其中username和age必须和前端的命名是一样的
@RequestMapping("/test")
    public  String test1(String username,int age){
        System.out.println("test1被执行了-----");
        System.out.println("username:"+username);
        System.out.println("age:"+age);
        //return 的是结果页面的名称
        // -->因为在springmvc.xml配置文件中制定了前缀和后缀,所以最后呈现的是/success.jsp
        return  "success";
    }

(3)使用控件名和对象的属性名一致的方式进行接收

创建一个实体类,其属性就是前端需要传输的值,通过调用实体类来进行传值。

//实体类
public class User {
    private  String username;
    private  int age;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

//传值
 @RequestMapping("/test")
    public  String test1(User user){
        System.out.println("test1被执行了-----User");
        System.out.println("username:"+user.getUsername());
        System.out.println("age:"+user.getAge());
        //return 的是结果页面的名称
        // -->因为在springmvc.xml配置文件中制定了前缀和后缀,所以最后呈现的是/success.jsp
        return  "success";
    }

如果key值和参数名不同:使用@RequestParam(value = “”)进行指定对应关系

public String login(@RequestParam(value = "name") String username, String password){} //设置默认值 
public String list(@RequestParam(defaultValue = "1") Integer currentPage)

如果key值和参数名的类型不同会导致无法执行:

在这里插入图片描述

**日期问题处理:**springmvc框架默认支持转换得日期格式:yyyy/MM/dd

(1)使用string接受日期,接受后,再转换: SimpleDataFormate

(2)使用工具类处理日期

<dependency> 
    <groupId>joda-time</groupId>
    <artifactId>joda-time</artifactId>
    <version>2.9.9</version>
</dependency>

配置文件:<mvc:annotation-driven/>

public String test1(@DateTimeFormat(pattern = "yyyy-MM-dd")Date birthday){}

6、返参

修改web.xml以支持jsp的EL表达式

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">

(1)HttpServletRequest

(2)ModelMap map ,默认作用域request

(3)ModelAndView 对象需要new,同时作为返回值类型

(4)Model类保存数据

在这里插入图片描述
在这里插入图片描述

7、处理session数据

1)使用HttpSession :request.getSession();2)使用@sessionAttributes("key值")//写的是ModelMap中定义的key值
注:该注解和ModelMap结合使用,当使用ModelMap存值时,会在session中同时存储一份数据
@SessionAttributes()的小括号中如果是一个值,不要加{}
示例:
@SessionAttributes("key") 
@SessionAttributes({"key1","key2"}) 
清除注解session:SessionStatus类
status.setComplete();

在这里插入图片描述

8、弹窗响应

后端操作:

在这里插入图片描述

乱码处理:

在这里插入图片描述

转发和重定向:

默认是转发:

@RequestMapping("/forwardView") 
public String forwardView(){ 
    return "forward:/WEB_INF/pages/success.jsp"; 
}

重定向:

//重定向时会忽视视图解析器的配置
return "redirect:a.jsp" 或者:redirect:findall

9、异常处理

在web.xml中单独加一个异常处理页面,然后跳转

    //异常处理
    @ExceptionHandler(Exception.class)
    public  String  error(){
        System.out.println("Error-----");
        return  "error";
    }

设置全局异常处理

//新建一个异常处理类,在类名前面加上@ControllerAdvice注解
@ControllerAdvice
public class ExceptionUtil {
    //全局异常处理
    @ExceptionHandler(Exception.class)
    public  String  error(){
        System.out.println("Error-----");
        return  "error";
    }
}

10、cookie和请求头数据获取

cookie:使用@CookieValue

请求头:使用@RequestHeader

  public ModelAndView test2(@CookieValue("JSESSIONID") String sessionid,@RequestHeader("Accept-Language")String language){
      System.out.println("sessionid:"+sessionid);
      System.out.println("language:"+language);
  }

11、RestFul请求模式

REST:即Representational State Transfer ,(资源)表现层状态转化,是目前最流行的一种互联网软件架构。 具体说,就是HTTP协议里面,四个表示操作方式的动词: GET POST PUT DELETE

分别代表着四种基本操作:

- GET用来获取资源

- POST用来创建新资源

- PUT用来更新资源

- DELETE用来删除资源

实现:

1、 web.xml添加HiddenHttpMethodFilter配置

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://java.sun.com/xml/ns/javaee"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
         http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
        version="2.5">

  <display-name>Archetype Created Web Application</display-name>

  <servlet>
    <servlet-name>aa</servlet-name>
    <servlet-class>
      org.springframework.web.servlet.DispatcherServlet
    </servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:springmvc.xml</param-value>
    </init-param>
  </servlet>
  <servlet-mapping>
    <servlet-name>aa</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>

  <filter>
    <filter-name>hid</filter-name>
    <filter-class>
      org.springframework.web.filter.HiddenHttpMethodFilter
    </filter-class>
  </filter>
  <filter-mapping>
    <filter-name>hid</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>

2、新建JSP文件

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Restful</title>
</head>
<body>
    <form action="/testrest" method="post">
        <input type="submit" value="post">
    </form>
    <form action="/testrest" method="get">
        <input type="submit" value="get">
    </form>
    <form action="/testrest" method="post">
        <input type="hidden" name="_method" value="put">
        <input type="submit" value="put">
    </form>
    <form action="/testrest" method="post">
        <input type="hidden" name="_method" value="delete">
        <input type="submit" value="delete">
    </form>
</body>
</html>

注意:因为put和delete请求是不存在的,所以需要在其中加入:
	<input type="hidden" name="_method" value="delete">
其中form表单的method必须使用post并且input的name必须是_method.

3、测试

@Controller
public class RestController {
    @RequestMapping(value = "/testrest",method = RequestMethod.POST)
    public String post(){
        System.out.println("post请求");
        return  "postsuccess";
    }
    @RequestMapping(value = "/testrest",method = RequestMethod.GET)
    public String get(){
        System.out.println("get请求");
        return  "getsuccess";
    }
    @RequestMapping(value = "/testrest",method = RequestMethod.PUT)
    public String put(){
        System.out.println("put请求");
        return  "putsuccess";
    }
    @RequestMapping(value = "/testrest",method = RequestMethod.DELETE)
    public String del(){
        System.out.println("del请求");
        return  "delsuccess";
    }
}

传值:

使用@PathVariable注解,并且需要在@RequestMapping中设置需要获取的几个变量值,使用{}。

@Controller
public class RestController {
    @RequestMapping(value = "/testrest/{name}/{age}",method = RequestMethod.POST)
    public String post(@PathVariable("name")String name,@PathVariable("age")int age){
        System.out.println("name:"+name+",age:"+age);
        System.out.println("post请求");
        return  "postsuccess";
    }
    @RequestMapping(value = "/testrest/{name}/{age}",method = RequestMethod.GET)
    public String get(@PathVariable("name")String name,@PathVariable("age")int age){
        System.out.println("name:"+name+",age:"+age);
        System.out.println("get请求");
        return  "getsuccess";
    }
    @RequestMapping(value = "/testrest/{name}/{age}",method = RequestMethod.PUT)
    public String put(@PathVariable("name")String name,@PathVariable("age")int age){
        System.out.println("name:"+name+",age:"+age);
        System.out.println("put请求");
        return  "putsuccess";
    }
    @RequestMapping(value = "/testrest/{name}/{age}",method = RequestMethod.DELETE)
    public String del(@PathVariable("name")String name,@PathVariable("age")int age){
        System.out.println("name:"+name+",age:"+age);
        System.out.println("del请求");
        return  "delsuccess";
    }

}

12、静态资源访问

1、修改spring.xml

<?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:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" 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/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd ">

2、 添加处理标签

<mvc:annotation-driven /> <!--注解驱动--> 
<mvc:resources mapping="/img/**" location="/images/" ></mvc:resources>

方式二:

<mvc:default-servlet-handler></mvc:default-servlet-handler>

13、Json数据处理

1、添加jar包

<dependency> 
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.9.5</version> 
</dependency>

2、实现代码:@ResponseBody 注意:需要在配置文件添加 mvc:annotation-driven/

在这里插入图片描述

14、SpringMVC拦截器

1、创建拦截器类:实现HandlerInterceptor接口

preHandle() 拦截器开始

postHandle() 拦截器结束

afterCompletion 最后执行

2、配置拦截器

<!--拦截所有-->
<mvc:interceptors> 
    <bean id="my" class="util.MyInterceptor"/> 
</mvc:interceptors>
<!--拦截指定请求-->
<mvc:interceptors> 
    <mvc:interceptor > 
        <mvc:mapping path="/请求名" />
        <mvc:mapping path="/请求名" />
        <bean id="my" class="util.MyInterceptor"/>
    </mvc:interceptor> 
</mvc:iterceptors>

在这里插入图片描述

使用场景:

1、日志记录 :记录请求信息的日志

2、权限检查,如登录检查

3、性能检测:检测方法的执行时间

过滤器和拦截器的区别:
  • 过滤器:
  • 依赖于servlet容器。在实现上基于函数回调,可以对几乎所有请求进行过滤,但是缺点是一个过滤器实例只能在容 器初始化时调用一次。使用过滤器的目的是用来做一些过滤操作,获取我们想要获取的数据,比如:在过滤器中修 改字符编码;在过滤器中修改HttpServletRequest的一些参数,包括:过滤低俗文字、危险字符等
  • 拦截器:
  • 依赖于web框架,在SpringMVC中就是依赖于SpringMVC框架。在实现上基于Java的反射机制,属于面向切面编程 (AOP)的一种运用。由于拦截器是基于web框架的调用,因此可以使用Spring的依赖注入(DI)进行一些业务操 作,同时一个拦截器实例在一个controller生命周期之内可以多次调用。但是缺点是只能对controller请求进行拦 截,对其他的一些比如直接访问静态资源的请求则没办法进行拦截处理 。
  • 多个过滤器与拦截器的代码执行顺序
  • 1、过滤器的运行是依赖于servlet容器的,跟springmvc等框架并没有关系。并且,多个过滤器的执行顺序跟xml文 件中定义的先后关系有关
  • 2、对于多个拦截器它们之间的执行顺序跟在SpringMVC的配置文件中定义的先后顺序有关

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ApVu6ip1-1605966060603)(F:\开课吧-Java\笔记\图片\第十二章\18.png)]

15、文件上传下载

上传:MultipartResolver

1、添加jar包

<dependency> 
    <groupId>commons-fileupload</groupId> 
    <artifactId>commons-fileupload</artifactId> 
    <version>1.3.1</version> 
</dependency>
<dependency> 
    <groupId>commons-io</groupId> 
    <artifactId>commons-io</artifactId>
    <version>2.4</version>
</dependency>

2、配置MultipartResolver:

<mvc:annotation-driven/>
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" p:defaultEncoding="UTF-8" p:maxUploadSize="5242880" /

3、页面表单,提交方式必须是post

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
   <h1>上传</h1>
<form action="/upload" method="post" enctype="multipart/form-data">
      文件:<input type="file" name="myfile">
    <input type="submit" value="上传">

</form>
</body>
</html>

4、java代码

@Controller
public class UploadController {
    @RequestMapping("/upload")
    public String upload(MultipartFile myfile, HttpServletRequest request){
        //处理上传的文件内容
        //1.将上传的文件夹转换成服务器路径
        String realPath = request.getRealPath("/uploadimg");
        System.out.println("realpath="+realPath);
        //2.得到上传的文件名
        String filename = myfile.getOriginalFilename();
        //3.上传
        try {
            myfile.transferTo(new File(realPath+"/"+filename));
        } catch (IOException e) {
            e.printStackTrace();
        }
        request.setAttribute("filename",filename);
        return "uploadsuccess";
    }
}
下载:

1、添加jar包

<dependency> 
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.4</version>
</dependency>

2、处理类

@Controller
public class DownloadController {
    @RequestMapping("/download")
    public ResponseEntity<byte[]> down(String filename, HttpServletRequest request) throws UnsupportedEncodingException, IOException {
        //1.转换服务器地址
        String realPath = request.getRealPath("/uploadimg");
        //2.得到要下载的文件路径
       String filePath= realPath+"/"+filename;
       //3.设置响应的头信息
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        //给用户弹窗的方式进行下载
        //attachment 用来表示以附件的形式响应给客户端
        httpHeaders.setContentDispositionFormData("attachment", URLEncoder.encode(filename,"UTF-8"));
        //4.创建文件
        File file = new File(filePath);
        //5.将文件进行返回
        ResponseEntity<byte[]> responseEntity = new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file),httpHeaders, HttpStatus.CREATED);
        return responseEntity;
    }
}

三、Mybatis

1、简介

MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口 和 Java 的 POJOs(Plain Ordinary Java Object,普通的 Java对象)映射成数据库中的记录。

2、搭建Mybatis

mysql-connector-java-8.0.21.jar
1、添加依赖包和配置相应的xml文件
<!--pom.xml-->
<?xml version="1.0" encoding="UTF-8"?>
<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.java</groupId>
    <artifactId>MybatisDemo1</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencies>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.6</version>
        </dependency>
        <dependency>
        <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.21</version>
        </dependency>
    </dependencies>
</project>

<!--Mybatis.xml-->
<?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">
<!--连接数据库的环境,default=环境的id-->
<configuration>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <!--<property name="url" value="jdbc:mysql://localhost:3306/test"/>-->
                <property name="url" value="jdbc:mysql://localhost:3306/test?useUnicode=true&amp;characterEncoding=utf-8&amp;serverTimezone=GMT&amp;nullCatalogMeansCurrent = true"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
    <!-- 指定maper文件的路径(maven项目从resources源文件夹下找资源)-->
    <mappers>
       <!-- <mapper resource="包名/mapper文件名"/>-->
        <mapper resource="userMapper.xml"></mapper>
    </mappers>
</configuration>
2、创建实体类和接口
//实体类
package com.java.bean;

/**
 * @Author: YNB
 * @Description:
 * @Date Created in 2020-11-21 11:18
 * @Modified By:
 */
public class User {
    private  int userid;
    private  String username;
    private  String userphone;

    public int getUserid() {
        return userid;
    }

    public void setUserid(int userid) {
        this.userid = userid;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getUserphone() {
        return userphone;
    }

    public void setUserphone(String userphone) {
        this.userphone = userphone;
    }

    @Override
    public String toString() {
        return "User{" +
                "userid=" + userid +
                ", username='" + username + '\'' +
                ", userphone='" + userphone + '\'' +
                '}';
    }
}


//接口
public interface UserDao {
    //定义增删改查
    public List<User> getAll();
}

3、添加mapper文件
<?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="接口的完整路径"-->
<mapper namespace="com.java.dao.UserDao">
    <!--id=方法名-->
    <select id="getAll" resultType="com.java.bean.User">
        SELECT  * FROM USER1;
    </select>
</mapper>
4、处理数据
public class Test1 {
    public static void main(String[] args) {
        try {
            //1 加载配置文件
            Reader reader = Resources.getResourceAsReader("mybatis.xml");
            //2 得到sqlSessionFactoryBuilder
            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
            SqlSessionFactory build = builder.build(reader);
            //3 得到sqlSession
            SqlSession sqlSession = build.openSession();
            //4 操作sql
            List<User> users = sqlSession.selectList("com.java.dao.UserDao.getAll");
            //5 遍历
            for (User user:users){
                System.out.println(user);
            }
            //6 关闭资源
            sqlSession.close();
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

3、配置多数据源

1、<!--在mybatis.xml文件中配置多个数据源,通过不同的id指定-->
<environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <!--<property name="url" value="jdbc:mysql://localhost:3306/test"/>-->
                <property name="url" value="jdbc:mysql://localhost:3306/test?useUnicode=true&amp;characterEncoding=utf-8&amp;serverTimezone=GMT&amp;nullCatalogMeansCurrent = true"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
        <environment id="development1">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <!--<property name="url" value="jdbc:mysql://localhost:3306/test"/>-->
                <property name="url" value="jdbc:mysql://localhost:3306/test?useUnicode=true&amp;characterEncoding=utf-8&amp;serverTimezone=GMT&amp;nullCatalogMeansCurrent = true"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
2、在调用时加上对应的id
public class Test1 {
    public static void main(String[] args) {
        try {
            //1 加载配置文件
            Reader reader = Resources.getResourceAsReader("mybatis.xml");
            //2 得到sqlSessionFactoryBuilder
            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
            SqlSessionFactory build = builder.build(reader,"development1");
            //3 得到sqlSession
            SqlSession sqlSession = build.openSession();
            //4 操作sql
            List<User> users = sqlSession.selectList("com.java.dao.UserDao.getAll");
            //5 遍历
            for (User user:users){
                System.out.println(user);
            }
            //6 关闭资源
            sqlSession.close();
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

4、增删改查-----CRUD

//接口
public interface UserDao {
    //根据id查询用户信息
    public  List<User> findByUserid(int userid);
    //新增  需要新增的数据存储于单个对象
    public  int insertUser(User user);
    //新增  需要新增的数据是单独的,必须存放于一个map集合中,然后在配置文件中读取它的key值
    public  int insertUser1(Map map);
    //取最大值、最小值、平均值
    public Map  find();
}
//实现:
  public static void main(String[] args) {
        try {
            //1 加载配置文件
            Reader reader = Resources.getResourceAsReader("mybatis.xml");
            //2 得到sqlSessionFactoryBuilder
            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
            SqlSessionFactory build = builder.build(reader,"development");
            //3 得到sqlSession
            SqlSession sqlSession = build.openSession();
            //4 操作sql
            
            //查询
            User user = sqlSession.selectOne("com.java.dao.UserDao.findByUserid", 5);
            //整个对象插入
            User user = new User(1, "五哈", "876644455");
            int insert = sqlSession.insert("com.java.dao.UserDao.insertUser", user);
            sqlSession.commit();
            System.out.println(insert);
            //多值分开插入
             Map map = new HashMap();
            map.put("uname","王五");
            map.put("uphone","123456282");
            int insert = sqlSession.insert("com.java.dao.UserDao.insertUser1", map);
            sqlSession.commit();
            System.out.println(insert);
            //查询  最大值、最小值
            Map map= sqlSession.selectOne("com.java.dao.UserDao.find");
            Set<Map.Entry> set = map.entrySet();
            //5 遍历
            for (Map.Entry o:set) {
                System.out.println(set);
            }
            
            
            //5 遍历
            System.out.println("user:"+user);
            /*for (User user:users){
                System.out.println(user);
            }*/
            //6 关闭资源
            sqlSession.close();
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

配置:

<?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="接口的完整路径"-->
<mapper namespace="com.java.dao.UserDao">
    <!--id=方法名-->
    <select id="getAll" resultType="com.java.bean.User">
        SELECT  * FROM USER1;
    </select>

    <select id="findByUserid" parameterType="int" resultType="com.java.bean.User" >
        SELECT  * FROM USER1 WHERE USERID = #{USERID};
    </select>

    <!--增删改返回的是收影响的行数,不需要配置resultType-->
    <insert id="insertUser" parameterType="com.java.bean.User">
        insert  into user1 values(#{userid},#{username},#{userphone})
    </insert>

    <insert id="insertUser1" parameterType="com.java.bean.User">
        insert  into user1(username,userphone) values(#{uname},#{uphone})
    </insert>

    <select id="find" resultType="map">
    select  max(userid) 最大值,avg(userid) 平均值,min(userid) 最小值 from  user1
    /*select  max(userid) ,avg(userid) ,min(userid) from  user1*/
    </select>
</mapper>

5、getMapper方法

在这里插入图片描述

6、ThreadLocal处理sqlSession

ThreadLocal并非是一个线程的本地实现版本,它并不是一个Thread,而是threadlocalvariable(线程局部变量)。也许把它命名为ThreadLocalVar更加合适。线程局部变量(ThreadLocal)其实的功用非常简单,就是为每一个使用该变量的线程都提供一个变量值的副本,是Java中一种较为特殊的线程绑定机 制,是每一个线程都可以独立地改变自己的副本,而不会和其它线程的副本冲突。

public class TestThread {
    private ThreadLocal<String> threadLocal=new ThreadLocal<String>();
    private List<String> list=new ArrayList<String>();
    class A extends  Thread{
        @Override
        public void run() {
           //存值
            System.out.println("A线程开始存值");
            threadLocal.set("thread内容");
            list.add("list内容");
            System.out.println("A---threadLocal="+threadLocal.get());
        }
    }
    class B extends  Thread{
        @Override
        public void run() {
            //  取值
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("B线程取数据");
            System.out.println("b---threadLocal="+threadLocal.get());
            System.out.println("list="+list.get(0));
        }
    }
    public static void main(String[] args) {
        TestThread testThread = new TestThread();
        TestThread.A a=testThread.new A();
        TestThread.B b=testThread.new B();
        a.start();
        b.start();
    }
}

优化:

public class SqlSessionUtil {
    private static ThreadLocal<SqlSession>threadLocal=new ThreadLocal<SqlSession>();
    private static SqlSessionFactory sqlSessionFactory;

    static {
        try {
            Reader resourceAsReader = Resources.getResourceAsReader("mybatis.xml");
            sqlSessionFactory= new SqlSessionFactoryBuilder().build(resourceAsReader,"a2");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public static SqlSession getSession(){
        SqlSession session = threadLocal.get();
        if(session==null){
            session = sqlSessionFactory.openSession();
            threadLocal.set(session);
        }
        return session;
    }
    public static void closeSession(){
        SqlSession session = threadLocal.get();
        if(session!=null){
            session.close();
            threadLocal.remove();
        }
    }
}

起别名:

<configuration>
    <!--给类起别名-->
    <typeAliases>
        <!--给类起别名-->
        <!--<typeAlias type="com.java.bean.User" alias="user"></typeAlias>-->
        <!--给包起别名-->
        <package name="com.java.bean"/>
    </typeAliases>

7、log4j显示sql语句

1、导入依赖

<dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.5</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.12</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>

2、添加log4j.properties属性文件

log4j.rootLogger=DEBUG, Console 
log4j.appender.Console=org.apache.log4j.ConsoleAppender  
log4j.appender.Console.layout=org.apache.log4j.PatternLayout  
log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n  

log4j.logger.java.sql.ResultSet=INFO  
log4j.logger.org.apache=INFO  
log4j.logger.java.sql.Connection=DEBUG  
log4j.logger.java.sql.Statement=DEBUG  
log4j.logger.java.sql.PreparedStatement=DEBUG   

8、mybatis复杂查询

1、In查询:
<!--配置文件-->
<?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="接口的完整路径"-->
<mapper namespace="com.java.dao.UserDao2">
    <!--id=方法名-->
    <!--List类型-->
   <select id="finda" resultType="user">
       select * from user1 where userid in
       <foreach collection="list" item="uid" open="(" close=")" separator=",">
           #{uid}
       </foreach>
   </select>
    <!--数组类型-->
    <select id="findb" resultType="user">
        select * from user1 where userid in
        <foreach collection="array" item="uid" open="(" close=")" separator=",">
            #{uid}
        </foreach>
    </select>
    <!--Map类型-->
    <select id="findc" resultType="user">
        select * from user1 where userid in
        <foreach collection="id" item="uid" open="(" close=")" separator=",">
            #{uid}
        </foreach>
    </select>
</mapper>

//实现类
public class Test6 {
    public static void main(String[] args) {
        SqlSession session = SqlSessionUtil.getSession();
        UserDao2 mapper = session.getMapper(UserDao2.class);
      /* List
      List list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        List<User> user = mapper.finda(list);*/
        /* 数组
        int [] id = new int[]{1,2,3};
        List<User> user = mapper.findb(id);*/
        // map集合
        List list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        Map map = new HashMap();
        map.put("id",list);
        List<User> user = mapper.findc(map);
        for (User u: user) {
            System.out.println(u);
        }
        SqlSessionUtil.closeSession();
    }
}

2、模糊查询和分页查询

模糊查询:

//接口类
public interface UserDao2 {
    //模糊查询  根据姓名和编号进行查询
    public List<User> findd(Map map);
    public  List<User> finde (User user);
}
 <!--模糊查询  map集合-->
    <select id="findd" resultType="user">
        select * from user1 where  1=1
        <if test="uid != null and uid != ''">
            and userid=${uid}
        </if>
        <if test="uname != null and uname != ''" >
            and username like  '%${uname}%'
        </if>
    </select>
<!--模糊查询  User对象-->
    <select id="finde" resultType="user">
        select * from user1 where  1=1
        <if test="userid != null and userid != ''">
            and userid=${userid}
        </if>
        <if test="username != null and username != ''" >
            and username like  '%${username}%'
        </if>
    </select>

//实现类
public class Test7 {
    public static void main(String[] args) {
        SqlSession session = SqlSessionUtil.getSession();
        UserDao2 mapper = session.getMapper(UserDao2.class);
        /*Map map =  new HashMap();
        map.put("uid","1");
        map.put("uname","五");
        List<User> user = mapper.findd(map);*/
        User user1 = new User();
        user1.setUsername("五");
        List<User> user = mapper.finde(user1);
        for(User u: user){
            System.out.println(u);
        }
        SqlSessionUtil.closeSession();
    }
}
3、分页查询:

1、逻辑分页:

List<User> users = sqlSession.selectList("com.java.dao.UserDao.getAll",null,new RowBounds(0,3));

2、物理分页:

导包:

 <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>5.1.6</version>
        </dependency>

修改配置文件

  <!--分页插件-->
    <plugins>
        <plugin interceptor="com.github.pagehelper.PageInterceptor">
        </plugin>
    </plugins>

实现类:

public static void main(String[] args) {
        try {
            //1.加载配置文件
            Reader reader = Resources.getResourceAsReader("mybatis.xml");
            //2.得到sqlSessionFactoryBuilder
            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
            SqlSessionFactory build = builder.build(reader,"a2");
            //3.得到SqlSession
            SqlSession session = build.openSession();
            //4.操作sql
            //4.1 指定分页的参数
            PageHelper.startPage(5,3);
            //4.2 调取dao层方法
            List<Student> list = session.selectList("com.yhp.dao.StudentDao.getall");//方法参数是被调取的sql的完整路径=namespace+id
            //4.3 创建分页工具类对象
            PageInfo<Student> info = new PageInfo<Student>(list);
            //5.从分页数据中获得数据
            for (Student student : info.getList()) {
                System.out.println(student);
            }
            System.out.println("当前页条数:"+info.getSize());
            System.out.println("总条数:"+info.getTotal());
            System.out.println("总页数:"+info.getPages());
            System.out.println("上一页:"+info.getPrePage()); //如果没有上一页,则返回0
            System.out.println("下一页:"+info.getNextPage());
            System.out.println("当前页:"+info.getPageNum());
            System.out.println("显示条数:"+info.getPageSize());
            //6.关闭资源
            session.close();
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

区间查询 :between 开始值 and 结束值

9、resultMap

1、、处理属性值和列名不匹配 单表关系

通过给列起别名,让别名=属性名,也可以实现数据对应

resultType=“指定返回值的类型”//当列名和属性名一致时使用

resultMap=“key 值” //1.当列名和属性名不一致 2.做多表查询时

mybatis 能实现的是单标的自动操作

    <resultMap id="rs1" type="com.yhp.bean.Student">
        <result property="age" column="stuage"></result>
    </resultMap>

    <!--id="方法名"-->
     <select id="getall" resultMap="rs1">
         select * from student
     </select>
2、处理多表关系

一对多

<resultMap type="" id="自定义名称"> 
    <id property="id" column="dept_id" /><!--主键列-->
    <result property="java 属性名" column="列名" />
    <collection property="属性名" ofType="java 类型">
        <id property="属性名" column="列名" /> 
        <result property="属性名" column="列名" /> 
    </collection> 
</resultMap>

多对一

<resultMap type="" id=""> 
    <id property="" column="" /> 
    <result property="" column="" /> 
    <association property="" javaType=""> 
        <id property="" column="" /> 
        <result property="" column="" />
    </association>
</resultMap>

一对一:

<!--配置文件-->
<?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="接口的完整路径"-->
<mapper namespace="com.yhp.dao.WifeDao">
    <resultMap id="rs6" type="com.yhp.bean.Husband">
        <id property="husId" column="husid"></id>
        <result property="husName" column="husname"></result>
        <association property="wife" javaType="com.yhp.bean.Wife">
            <id property="wifeId" column="wifeid"></id>
            <result property="wifeName" column="wifename"></result>
        </association>
    </resultMap>
    <resultMap id="rs7" type="com.yhp.bean.Wife">
        <id property="wifeId" column="wifeid"></id>
        <result property="wifeName" column="wifename"></result>
        <association property="husband" javaType="com.yhp.bean.Husband">
            <id property="husId" column="husid"></id>
            <result property="husName" column="husname"></result>
        </association>
    </resultMap>
    <select id="findByhusId" resultMap="rs6">
  select * from wife w,husband h
  where w.wifeid=h.wid and h.husid=#{husid}
    </select>

    <select id="findByWifeId" resultMap="rs7">
        select * from wife w,husband h
  where w.wifeid=h.wid and w.wifeid=#{wifeid}
    </select>
</mapper>

//接口
public interface WifeDao {
    //根据丈夫查询妻子
    public Husband findByhusId(int husid);
    //根据妻子查询丈夫
    public Wife findByWifeId(int wifeid);
}
//实现类
public class TestWife {
    public static void main(String[] args) {
        SqlSession session = SqlSessionUtil.getSession();
        WifeDao mapper = session.getMapper(WifeDao.class);
        Wife wife = mapper.findByWifeId(1);
        System.out.println(wife.getWifeName()+","+wife.getHusband().getHusName());
        Husband husband = mapper.findByhusId(1);
        System.out.println(husband.getHusName()+","+husband.getWife().getWifeName());
        SqlSessionUtil.closeSession();
    }
}

10、缓存

**一级缓存:**SqlSession 的缓存 ------>自动开启

**二级缓存:**做到从不同的缓存中共享数据 SqlSessionFactory 的缓存 —>需要手动开启

配置:

<mapper namespace="接口路径">
    <cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/> 
</mapper>

eviction: 二级缓存中,缓存的对象从缓存中移除的策略,回收策略为先进先出 
flushInterval: 刷新缓存的事件间隔,单位:毫秒
size: 缓存对象的个数
readOnly: 是否是只读的

11、Mybatis注解

<mapper class="com.dao.StudentDao"></mapper>
public interface StudentDao {
    //增删改查
    @Insert("insert into student(studentno,stuname,stuage) values(#{studentNo},#{stuName},#{age})")
    @Options(useGeneratedKeys = true,keyProperty = "studentId")//获得新增数据的id
    public int insertStu(Student student);

    @Update("update student set studentno=#{studentNo},stuname=#{stuName} where studentid=#{studentId}")
    public int updateStu(Student student);

    @Select("select * from student")
    @Results({
            @Result(column = "stuage",property = "age")
    })
    public List<Student> findall();

    @Select("select count(*) from student")
    public int totalCount();

    @Delete("delete from student where studentid=#{sid}")
    public int deleteStu(int sid);
    //计算id的最大值,最小值,平均值
    @Select("select max(studentid) max,min(studentid) min,avg(studentid) avg from student")
    public Map total2();

}

//测试
public class Demo1 {
    public static void main(String[] args) {
        SqlSession session = SqlSessionUtil.getSession();

        StudentDao studentDao = session.getMapper(StudentDao.class);
       /* Student student = new Student();
        student.setStudentNo("a1101");
        student.setStuName("abc");
        student.setAge(18);
        int i = studentDao.insertStu(student);
        session.commit();
        System.out.println("i="+i+",id="+student.getStudentId());*/

       /* Student student = new Student();
        student.setStudentId(119);
        student.setStudentNo("a1101");
        student.setStuName("张娜");
        student.setAge(20);
        int i = studentDao.updateStu(student);
        session.commit();
        System.out.println("i="+i);*/
/*
        List<Student> students = studentDao.findall();
        for (Student student : students) {
            System.out.println(student);
        }*/
     /*   int i = studentDao.deleteStu(119);
        session.commit();
        System.out.println("i="+i);*/

     /*   int i = studentDao.totalCount();
        System.out.println("total="+i);*/
        Map map = studentDao.total2();
        Set<Map.Entry> set = map.entrySet();
        for (Map.Entry entry : set) {
            System.out.println(entry);
        }
        SqlSessionUtil.closeSession();
    }
}
    

12、lombok插件

<dependency>
    <groupId>org.projectlombok</groupId> 
    <artifactId>lombok</artifactId> 
    <version>1.18.2</version>
    <scope>provided</scope> 
</dependency>

lombok的使用 :

@Data 注解在类上;提供类所有属性的 getting 和 setting 方法,此外还提供了equals、canEqual、hashCode、toString 方法
@Setter :注解在属性上;为属性提供 setting 方法 @Getter :注解在属性上;为属性提供 getting 方法 
@Log4j :注解在类上;为类提供一个 属性名为log 的 log4j 日志对象 
@NoArgsConstructor :注解在类上;为类提供一个无参的构造方法 
@AllArgsConstructor :注解在类上;为类提供一个全参的构造方法 
@Cleanup : 可以关闭流
@Builder : 被注解的类加个构造者模式 
@Synchronized : 加个同步锁
@SneakyThrows : 等同于try/catch 捕获异常
@NonNull : 如果给参数加个这个注解 参数为null会抛出空指针异常 
@Value : 注解和@Data类似,区别在于它会把所有成员变量默认定义为private final修饰,并且不会生成set方法。 
@ToString 重写toString()方法

13、Mybatis自动化

作用:反向生成实体类,接口,mapper.xml

<dependency> 
    <groupId>org.mybatis.generator</groupId>
    <artifactId>mybatis-generator-core</artifactId> 
    <version>1.3.5</version> 
</dependency>

加载插件:

<build>
    <plugins>
        <plugin>
            <groupId>org.mybatis.generator</groupId> 
            <artifactId>mybatis-generator-maven-plugin</artifactId>
            <version>1.3.5</version> 
            <configuration> 
   <!--配置文件的路径-->
                <configurationFile>src/main/resources/generatorConfig.xml</configurationFile> 
                <overwrite>true</overwrite>
            </configuration>
            <dependencies> 
                <dependency>
                    <groupId>org.mybatis.generator</groupId>
                    <artifactId>mybatis-generator-core</artifactId>
                    <version>1.3.5</version> 
                </dependency>
            </dependencies>
        </plugin> 
    </plugins> 
</build>
   

修改配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
        PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">

<!-- 配置生成器 -->
<generatorConfiguration>
    <!--数据库驱动jar -->
    <classPathEntry
            location="F:\kaikeba\maven\maven_repository\mysql\mysql-connector-java\5.1.40\mysql-connector-java-5.1.40.jar" />

    <context id="MyBatis" targetRuntime="MyBatis3">

        <!--去除注释 -->
        <commentGenerator>
            <property name="suppressAllComments" value="true" />
        </commentGenerator>

        <!--数据库连接 -->
        <jdbcConnection driverClass="com.mysql.jdbc.Driver"
                        connectionURL="jdbc:mysql://localhost:3306/mytest"
                        userId="root"
                        password="123456">
        </jdbcConnection>

        <!--生成实体类 指定包名 以及生成的地址 (可以自定义地址,但是路径不存在不会自动创建
        使用Maven生成在target目录下,会自动创建) -->
        <javaModelGenerator targetPackage="com.yhp.bean"
                            targetProject="D:\mybatis3\src\main\java">
            <property name="trimStrings" value="true" />
        </javaModelGenerator>


        <!--生成SQLmapper文件 -->
        <sqlMapGenerator targetPackage="mapper"
                         targetProject="D:\mybatis3\src\main\resources">
        </sqlMapGenerator>
        <!--生成Dao文件,生成接口 -->
        <javaClientGenerator type="XMLMAPPER"
                             targetPackage="com.yhp.dao"
                             targetProject="D:\mybatis3\src\main\java">
        </javaClientGenerator>

        <table tableName="student" enableCountByExample="false"
               enableUpdateByExample="false" enableDeleteByExample="false"
               enableSelectByExample="false" selectByExampleQueryId="false">
        </table>
        <table tableName="grade" enableCountByExample="false"
               enableUpdateByExample="false" enableDeleteByExample="false"
               enableSelectByExample="false" selectByExampleQueryId="false">
        </table>
        <table tableName="role" enableCountByExample="false"
               enableUpdateByExample="false" enableDeleteByExample="false"
               enableSelectByExample="false" selectByExampleQueryId="false">
        </table>   </context>
</generatorConfiguration>

运行:maven Project选项卡->plugins->找到mybatis-generator-core,双击运行就会自动生成

注意:运行一次即可,如果运行过程中,未完全成功。则将原来生成的代码删除后,再次运行。

切记!切记!切记

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值