环境:
依赖:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.12</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId> <!--spring操作数据库还需要spring-jdbc-->
<version>5.3.12</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.7</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.16</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.6</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
文档:
core的文档:
https://docs.spring.io/spring-framework/docs/current/reference/html/core.html
Spring框架
SSH:Struts2 + Spring + Hibernate
SSM: SpringMVC + Spring + Mybatis
Spring依赖配置:
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.12.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.12.RELEASE</version>
</dependency>
总结:Spring是一个轻量级的控制反转(IOC)和面向切片编程(AOP)的框架!
Spring Boot
一个快速开发脚手架
基于SpringBoot可以快速开发单个微服务
约定大于配置
Spring Cloud
学习SpringBoot的前提,需要完全掌握Spring及SpringMVC。
唯一弊端:发展太久,违背了原来的理念,配置十分繁琐,称为配置地狱。
原本的实现
UserDao接口
UserDaoImpl
UserService业务接口
UserServiceImpl实现
在我们之前的业务中,用户的需求可能会影响我们原来的代码,我们需要根据用户的需求去修改原代码。如果程序量代码十分大,修改一次的代价成本十分昂贵
使用一个Set接口实现,优点在:
private UserDao userDao;
// 利用set方法动态实现值的注入
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
之前,程序时主动创建对象,控制权在程序员手上;使用set注入后,程序不再具有主动性,而是变成动态被动地接收对象。
没有IoC的程序,对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,IoC后将对象的创建转移给第三方,“获得依赖对象的方式反转了”。
IoC是Spring容器的核心内容。Spring容器在初始化时先读取配置文件,根据配置文件或元数据创建与组织对象存入容器中,程序使用时再从IoC容器中取出需要的对象。
采用XML方式配置Bean的时候,Bean的定义信息和实现是分离的;而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到零配置的目的
控制反转是一种通过描述(xml或注解)并通过第三方去生产获取特定对象的方式。在Spring中实现控制反转的是IoC容器,其实现方法是依赖注入。
The following example shows the basic structure of XML-based configuration metadata:
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<!--解释:
类型 变量名 = new 类型();
Hello hello = new Hello();
id = 变量名
class = new 的类型
property 设置对象的属性 -->
<bean id="..." class="...">
<!-- collaborators and configuration for this bean go here -->
<property name="name" value="Spring" />
</bean>
<!-- more bean definitions go here -->
</beans>
ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");
控制反转:
控制:谁来控制对象的创建?传统应该程序的对象是由程序本身控制创建的,使用Spring后是,对象是Spring来创建的。
反转:程序本身不创建对象,而是变成被动地接收对象。
依赖注入:就是利用set方法来进行注入,所有property中要设置的值必须要有**对应(名字对应)**的set方法。
对象由Spring创建、管理和装配。\
<bean id="mysqlImpl" class="com.kuang.dao.UserDaoMysqlImpl"/>
<bean id="oracleImpl" class="com.kuang.dao.UserDaoOracleImpl"/>
<bean id="userServiceImpl" class="com.kuang.service.UserServiceImpl">
<!--ref:引用Spring容器中创建好的对象
value:具体的值,比如基本数据类型-->
<property name="userDao" ref="mysqlImpl"/>
</bean>
// 获取ApplicationContext:拿到Spring容器
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
UserService userService = (UserService) context.getBean("userServiceImpl");
userService.getUser();
<bean id="user" class="com.kuang.pojo.User">
<property name="name" value="秦疆"/>
</bean>
有参构造器
<bean id="user" class="com.kuang.pojo.User">
<constructor-arg index="0" value="秦疆"/>
</bean>
<bean id="user" class="com.kuang.pojo.User">
<constructor-arg type="java.lang.String" value="qinjiang"/>
</bean>
<bean id="user" class="com.kuang.pojo.User">
<constructor-arg name="name" value="qinjiang"/>
</bean>
1、别名
<alias name="user" alias="userdfas"/>
2、Bean的配置
id 唯一标识符,相当于对象名
class:bean对象所对应的类型
name:别名,name比alias高级。可以取多个别名。
<bean id="user" class="com.kuang.pojo.User" name="userA, userB userC">
<constructor-arg name="name" value="qinjiang"/>
</bean>
3、import,假设项目由多个成员开发,bean需要注册在不同的类中,可以利用import合并为一个总的。applicationContext.xml
<import resource="bean2.xml"/>
如果存在重名,下面的会覆盖上面的。
依赖注入:set注入
依赖:bean对象的创建依赖于容器
注入:bean对象中的所有属性,由容器来注入
普通值的注入:
<bean id="student" class="com.kuang.pojo.Student">
<!--普通值注入-->
<property name="name" value="秦疆" />
</bean>
完善测试信息
<bean id="adresss" class="com.kuang.pojo.Address">
<property name="address" value="北京"/>
</bean>
<bean id="student" class="com.kuang.pojo.Student">
<!--普通值注入-->
<property name="name" value="秦疆" />
<property name="address" ref="adresss"/>
<!--String[]注入-->
<property name="books">
<array>
<value>三国演义</value>
<value>红楼梦</value>
<value>水浒传</value>
<value>西游记</value>
</array>
</property>
<!--list注入-->
<property name="hobbys">
<list>
<value>敲代码</value>
<value>看电影</value>
<value>听音乐</value>
</list>
</property>
<!--map注入-->
<property name="cards">
<map>
<entry key="身份证" value="111111222222223333"/>
<entry key="学生卡" value="1111222233"/>
</map>
</property>
<!--set注入-->
<property name="games">
<set>
<value>COC</value>
<value>BOB</value>
</set>
</property>
<!--null注入-->
<property name="wife">
<null/>
</property>
<!-- <java.util.Properties> 配置类型注入-->
<property name="info">
<props>
<prop key="adminstrator">guanliyuan</prop>
<prop key="user">yonghu</prop>
</props>
</property>
</bean>
集合
bean | ref | idref | list | set | map | props | value | null
p命名空间和c命名空间
<?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:c="http://www.springframework.org/schema/c"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- p命名空间,必须有无参构造器,可以直接直接注入属性的值,p:代表property-->
<bean name="user" class="com.kuang.pojo.User" p:name="秦疆" p:age="18"/>
<!-- c命名空间,必须使用有参构造器,通过构造器注入,c:代表construct-args-->
<bean name="user2" class="com.kuang.pojo.User" c:name="高大翔" c:age="200"/>
</beans>
注意:
p命名和c命名不能直接使用,必须导入xml约束
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
Scope | Description |
---|---|
singleton | (Default) Scopes a single bean definition to a single object instance for each Spring IoC container. |
prototype | Scopes a single bean definition to any number of object instances. |
request | Scopes a single bean definition to the lifecycle of a single HTTP request. That is, each HTTP request has its own instance of a bean created off the back of a single bean definition. Only valid in the context of a web-aware Spring ApplicationContext . |
session | Scopes a single bean definition to the lifecycle of an HTTP Session . Only valid in the context of a web-aware Spring ApplicationContext . |
application | Scopes a single bean definition to the lifecycle of a ServletContext . Only valid in the context of a web-aware Spring ApplicationContext . |
websocket | Scopes a single bean definition to the lifecycle of a WebSocket . Only valid in the context of a web-aware Spring ApplicationContext . |
singleton单例
<bean id="accountService" class="com.something.DefaultAccountService"/>
<!-- the following is equivalent, though redundant (singleton scope is the default) -->
<bean id="accountService" class="com.something.DefaultAccountService" scope="singleton"/>
2、原型模式prototype
每次从容器中get,都会产生一个新对象
在Spring中有三种装配的方式:
搭建环境:
一个人有两个宠物,一只猫、一只狗
原先的装配方式
<bean id="cat" class="com.kuang.pojo.Cat"/>
<bean id="dog" class="com.kuang.pojo.Dog"/>
<bean id="people" class="com.kuang.pojo.People">
<property name="name" value="狂神"/>
<property name="cat" ref="cat"/>
<property name="dog" ref="dog"/>
</bean>
自动装配
<bean id="cat" class="com.kuang.pojo.Cat"/>
<bean id="dog" class="com.kuang.pojo.Dog"/>
<bean id="people" class="com.kuang.pojo.People" autowire="byName">
<property name="name" value="狂神"/>
</bean>
jdk 1.5、Spring2.5 开始i支持注解
要使用注解,须知:
context
<context:annotation-config/>
小结:
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
</beans>
@Autowired
科普
// @Nullable 加了这个注解,可以为null
// @Autowired(required=false) 说明这个对象可以为null
// @Qualifier 配合@Autoweired使用,指定id名
@Autowired
@Qualifier(value = "dog222")
private Dog dog;
先通过bytype,不匹配再用byname
如果@Autowired不能唯一自动装配上属性,则需要通过@Qualifier(value="xxx")来指定名称。
@Resource实现自动装配
@Resource(name="bean id")
小结:
@Autowired和@Resource的区别
在Spring4之后,要使用注解开发,必须导入aop的包
使用注解需要导入context约束,增加注解的支持。
DAO层: DAO层叫数据访问层,全称为data access object,属于一种比较底层,比较基础的操作,具体到对于某个表的增删改查,也就是说某个DAO一定是和数据库的某一张表一一对应的,其中封装了增删改查基本操作,建议DAO只做原子操作,增删改查。
Service层: Service层叫服务层,被称为服务,粗略的理解就是对一个或多个DAO进行的再次封装,封装成一个服务,所以这里也就不会是一个原子操作了,需要事物控制。
Controler层: Controler负责请求转发,接受页面过来的参数,传给Service处理,接到返回值,再传给页面。
总结: DAO面向数据,Service面向业务。后端开发时先数据库设计出所有表,然后对每一张表设计出DAO层,然后根据具体的业务逻辑进一步封装DAO层成一个Service层,对外提供成一个服务。
@Component 组件,放在类上,说明这个类被Spring管理了
// 等价于 <bean id="user" class="com.kuang.pojo.User"/>
@Component
public class User {
public String name = "qinjiang";
}
@Component // 等价于<bean id="user" class="com.kuang.pojo.User"/>
public class User {
@Value("狂神") // 相当于<property name="name" value="狂神"/>
public String name;
}
复杂的注入还是需要用配置文件
@Value("狂神2")
public void setName(String name) {
this.name = name;
}
@component 有几个衍生注解,在web开发中,会按照mvc三层进行分层
这四个注解功能都是一样的,都是代表将某个类注册到Spring中,装配Bean
(后面单讲)
@Scope(value="singleton")
@Scope(value="prototype")
xml 与注解
最佳实践:
使用过程中,需要注意一个问题,需要开启注解的支持:
<context:annotation-config/>
<!--指定要扫描的包,这个包下的注解就会生效-->
<context:component-scan base-package="com.kuang.pojo"/>
可以使用java 的配置完全替代xml的配置
// 这个注解就是说明这个类被Spring接管了,注册到容器中,本身就是一个@Component
// @Configuration 代表这是一个配置类,和beans.xml一样
@Configuration
@ComponentScan("com.kuang.pojo")
public class KuangConfig {
@Bean
public User getUser() {
/* 相当于写了一个bean标签
* 方法名:就是Bean id Bean名
* 返回值:bean中的class
**/
return new User();
}
}
/** 等价于xml
<bean id="myService" class="com.acme.services.MyServiceImpl"/>
**/
JavaConfig是Spring的一个子项目,在Spring4之后变成Spring 的核心功能。
测试:
@Test
public void test01() {
// 如果完全使用配置类方式去做,就只能通过AnnotationConfig上下文来获取容器,通过配置类的class对象来加载
ApplicationContext context = new AnnotationConfigApplicationContext(KuangConfig.class);
User user = context.getBean("getUser", User.class);
System.out.println(user.getName());
}
Bean可能存在多个
@Configuration
@ComponentScan("com.kuang.pojo")
@Import(KuangConfig.class)
public class KuangConfig2 {
}
纯Java的配置,在SpringBoot中随处可见!
为什么学习AOP之前要学代理模式?因为代理模式是SpringAOP的底层 【SpringAOP和SpringMVC面试必问】
代理模式的分类:
代理和被代理的都得有共同要做的事情
角色分析:
代码步骤:
1、抽象接口
/*租房*/
public interface Rent {
public void rent();
}
2、真实角色
/*房东*/
public class Host implements Rent{
@Override
public void rent() {
System.out.println("房东要往外出租房子");
}
}
3、代理角色
public class Proxy implements Rent{
private Host host;
public Proxy() {
}
public Proxy(Host host) {
this.host = host;
}
@Override
public void rent() {
seeHouse();
host.rent();
hetong();
fare();
}
/*看房(附属操作)*/
public void seeHouse() {
System.out.println("中介带你看房");
}
/*收中介费(附属操作)*/
public void fare() {
System.out.println("收中介费");
}
/*签合同呢(附属操作)*/
public void hetong() {
System.out.println("签合同呢");
}
}
4、客户端访问代理角色
public class Client {
public static void main(String[] args) {
Host host = new Host();
// 代理:中介帮房东租房子,但是呢,代理一般会有一些附属操作。
Proxy proxy = new Proxy(host);
// 不用面对房东,直接找中介租房即可!
proxy.rent();
}
}
代理模式的好处:
缺点:
扩展:《面向对象七大原则》之:单一职能原则
为什么不在原来的代码上添加扩展的功能:
1、改动源代码是公司的大忌。
代码对应08-demo02
聊聊AOP
动态代理:改变静态代理的缺点
需要了解两个类 Proxy、InvocationHandler调用处理程序
InvocationHandler
代码步骤:
1、创建抽象接口、真实角色、代理类
动态代理其实挺简单。就两个类。生成代理类Proxy.newProxyInvocation(参数1.参数2,参数3) 参数1:表明你要用那个类加载器去加载生成的代理类。(这个是JVM类加载的知识,这个类加载器只要是应用类的类加载器就行了,我管你哪一个,不过一般用当前类的类加载器)。 参数2:说明你要生成的代理类的接口。被代理类的对象 参数3:实现了InvocationHandle的类,这个类只有一个方法需要你要实现它。
invoke(Object proxy, Method method, Object【】 args) { 这个方法第一个参数,是生成的代理类,目前没发现用处,不管它。 第二个参数,是执行的方法(利用反射的原理,可以去看反射,也很简单。) 第三个参数,是执行某方法需要的参数。 第二个第三个参数解释执行的方法意思是:代理类不是要代理某个对象么,然后增强里面的方法么,指得就是这个方法,代理类会为几乎所有方法都增强,除非你在这里做判断。 返回值,是执行这个方法所返回的值。 然后你要去执行方法,就是用第二参数的invoke(obj,args);第一个参数是你要增强的对象。第二个是参数。object是你返回的类型 Object object= method.invoke(obj,args); }
InvocationHandler
/* 实现demo02的动态代理*/
/* 通过一个通用类,来实现,成为一个万能工具 */
public class ProxyInvocationHandler implements InvocationHandler {
// 被代理的接口
private Object target;
public void setTarget(Object target) {
this.target = target;
}
// 生成代理类
public Object getProxy() {
return Proxy.newProxyInstance(
this.getClass().getClassLoader(),
target.getClass().getInterfaces(),
this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
log(method.getName());
Object result = method.invoke(target, args);
return result;
}
// 日志方法 (实现代理的附属方法)
public void log(String msg) {
System.out.println("使用了" + msg + "方法");
}
}
客户调用
public class Client {
public static void main(String[] args) {
// 真实角色
UserService userService = new UserServiceImpl();
// 获取代理角色,现在还不存在
ProxyInvocationHandler pih = new ProxyInvocationHandler();
pih.setTarget(userService); // 设置要代理的对象
// 动态生成代理类
UserService proxy = (UserService) pih.getProxy();
proxy.add();
}
}
动态代理的好处:
SpringAOP中,通过Advice定义横切逻辑,Spring中支持5中类型的Advice
即AOP在不改变原有代码的情况下,去增加新的功能。
【重点】使用AOP植入,需要导入一个依赖包
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.7</version>
</dependency>
切面:
public class BeforeLog implements MethodBeforeAdvice {
/**
* Callback before a given method is invoked.
* @param method the method being invoked 要执行的方法
* @param args the arguments to the method objects:参数
* @param target the target of the method invocation. May be {@code null}. o
* @throws Throwable if this object wishes to abort the call.
* Any exception thrown will be returned to the caller if it's
* allowed by the method signature. Otherwise the exception
* will be wrapped as a runtime exception.
*/
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println(target.getClass().getName() + "的" + method.getName() + "方法被执行");
}
}
bean配置:
<bean id="userService" class="com.kuang.service.UserServiceImpl"/>
<bean id="beforeLog" class="com.kuang.log.BeforeLog"/>
<bean id="afterLog" class="com.kuang.log.AfterLog"/>
<!--方式一:使用原生Spring API接口-->
<!-- 配置aop-->
<aop:config>
<!-- 首先需要一个切入点, expression表达式是固定的.要执行的位置execution([返回类型,*表示所有类型] 类名.方法名(参数))-->
<aop:pointcut id="pointcut" expression="execution(* com.kuang.service.UserServiceImpl.*(..))"/>
<!-- 执行环绕-->
<aop:advisor advice-ref="beforeLog" pointcut-ref="pointcut"/>
</aop:config>
定义切面,代码:
public class DiyPointCut {
public void before() {
System.out.println("=======方法执行前==========");
}
public void after() {
System.out.println("=======方法执行后==========");
}
}
bean配置:
<bean id="userService" class="com.kuang.service.UserServiceImpl"/>
<bean id="beforeLog" class="com.kuang.log.BeforeLog"/>
<bean id="afterLog" class="com.kuang.log.AfterLog"/>
<!-- 方式二:自定义类-->
<bean id="diy" class="com.kuang.diy.DiyPointCut"/>
<aop:config>
<!-- 切面:就是自定义的类-->
<aop:aspect ref="diy">
<!--切入点-->
<aop:pointcut id="pointcut" expression="execution(* com.kuang.service.UserServiceImpl.*(..))"/>
<aop:before method="before" pointcut-ref="pointcut"/>
<aop:after method="after" pointcut-ref="pointcut"/>
</aop:aspect>
</aop:config>
proxy-target-class="false" 默认就是jdk
切面代码
// 使用注解实现
@Aspect
public class AnnotationPointCut {
@Before("execution(* com.kuang.service.UserServiceImpl.*(..))")
public void before() {
System.out.println("=======方法执行前==========");
}
@After("execution(* com.kuang.service.UserServiceImpl.*(..))")
public void after() {
System.out.println("=======方法执行后==========");
}
// 在环绕增强中,我们可以给定一个参数,代表我们要获取处理切入的点
@Around("execution(* com.kuang.service.UserServiceImpl.*(..))")
public void around(ProceedingJoinPoint jp) throws Throwable {
System.out.println("=======方法执行前(环绕)==========");
System.out.println(jp.getSignature());
// 执行方法
Object proceed = jp.proceed();
System.out.println("=======方法执行后(环绕)==========");
}
}
bean 配置:
<!-- 方式三:-->
<bean id="annotationPointCut" class="com.kuang.diy.AnnotationPointCut"/>
<!-- 开启注解支持 jdk(默认) cglib -->
<aop:aspectj-autoproxy proxy-target-class="false"/>
切面代码输出:
=======方法执行前(环绕)==========
void com.kuang.service.UserService.add()
=======方法执行前==========
增加了一个用户
=======方法执行后==========
=======方法执行后(环绕)==========
步骤:
MyBatis-Spring | MyBatis | Spring Framework | Spring Batch | Java |
---|---|---|---|---|
2.0 | 3.5+ | 5.0+ | 4.0+ | Java 8+ |
1.3 | 3.4+ | 3.2.2+ | 2.1+ | Java 6+ |
package com.kuang.pojo;
import lombok.Data;
@Data
public class User {
private int id;
private String name;
private String pwd;
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<typeAliases>
<package name="com.kuang.pojo"/>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="org.mariadb.jdbc.Driver"/>
<property name="url" value="jdbc:mariadb://localhost:3306/mybatis"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<!--注册接口-->
<mappers>
<mapper class="com.kuang.mapper.UserMapper"/>
</mappers>
</configuration>
package com.kuang.mapper;
import com.kuang.pojo.User;
import java.util.List;
public interface UserMapper {
public List<User> selectUser();
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.kuang.mapper.UserMapper">
<select id="selectUser" resultType="user">
select * from mybatis.user;
</select>
</mapper>
public class MyTest {
@Test
public void test() throws IOException {
String resource = "mybatis-config.xml";
InputStream in = Resources.getResourceAsStream(resource);
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(in);
SqlSession sqlSession = sessionFactory.openSession(true);
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> userList = mapper.selectUser();
for (User user : userList) {
System.out.println(user);
}
}
}
注:maven静态资源过滤问题,设置pom.xml
<build>
<resources>
<!-- maven静态资源过滤问题 -->
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
mybatis-config.xml里的mappers 要删了,这个和 spring-dao的
<property name="mapperLocations" value="classpath:com/lzh/mapper/*.xml"/>
只能二选一!!!!!!不然会报错的,都是mapper的作用!
1、编写数据源配置
2、sqlSessionFactory
3、sqlSessionTemplete
4、给接口加实现类
spring整合mybatis,多了一个实现类,去自动创建
public class UserMapperImpl implements UserMapper{
/*我们的所有操作,原来都是用SqlSession,现在使用SqlSessionTemplete*/
private SqlSessionTemplate sqlSession;
public void setSqlSession(SqlSessionTemplate sqlSession) {
this.sqlSession = sqlSession;
}
@Override
public List<User> selectUser() {
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
return mapper.selectUser();
}
}
5、将自己写的实现类,注入到spring中,测试使用
【TODO:不太会,得补充一下mybatis】
1、回故事务
事务的ACID原则
原子性(Atomicity):所有的步骤要么全部完成,要么一个也不会完成
一致性(Consistency)即数据库事务不能破坏关系数据的完整性及业务逻辑上的一致性
隔离性(Isolation)
持久性(Durability)
2、spring中的事务
声明式事务:AOP应用,横切进去的,不影响业务
编程式事务:改变原有的代码。
为什么需要声明式事务:
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。