spring基础

Spring

学习文档:spring中文官网spring官网

  • spring是一个开源的免费框架
  • spring是一个轻量级,非入侵式的框架
  • 支持事务处理,对框架整合支持
  • 重点控制反转(IOC)和面向切面编程(AOP)

spring就是一个控制反转和面向切面编程的框架(容器)

一、IOC

1.IOC的本质

控制反转loC(Inversion of Control),是一种设计思想,**DI(依赖注入)**是实现loC的一种方法。没有loC的程序中,我们使用面向对象编程,对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方。

采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的。
控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是loC容器,其实现方法是依赖注入(Dependency Injection,Dl)。

ioc

IOC的Hello程序

导入依赖包

<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.3.22</version>
    </dependency>
//创建一个Hello类
package com.suzezhi.pojo;

public class Hello {
    private String name;

    public Hello() {
    }

    public Hello(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Hello{" +
                "name='" + name + '\'' +
                '}';
    }
    
}

创建一个Spring的配置文件,一般以applicationContext.xml命名(命名随便)

//ApplicationContext.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
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- 更多bean 定义在这里 -->
    <!--    id唯一标识相当于Hello的实例对象,class指定对应的类-->
    <bean id="hello" class="com.suzezhi.pojo.Hello">
        <property name="name" value="小陈"></property>
    </bean>
</beans>

这里要点击右上角,让其加载为配置文件

在这里插入图片描述

测试

import com.suzezhi.pojo.Hello;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {
    @Test
    public void testIoc(){
        //原来面向对象的写法
//        Hello hello = new Hello("小陈");
//        System.out.println(hello);
        //ioc写法
        /*
        * 实例化ClassPathXmlApplicationContext来加载配置文件(可以加载多个配置文件)
        * 从而获取指定的bean
        * 通过bean来操作具体的实现
        * */
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        Hello hello = (Hello) applicationContext.getBean("hello");
        System.out.println(hello);
    }
}

  • Hello 对象是谁创建的?
    • hello 对象是由Spring创建的。
  • Hello对象的属性是怎么设置的?
    • hello 对象的属性是由Spring容器设置的。

这个过程就叫控制反转:
控制:谁来控制对象的创建,传统应用程序的对象是由程序本身控制创建的,使用Spring后,对象是由Spring来创建的.
反转:程序本身不创建对象,而变成被动的接收对象.
依赖注入:就是利用set方法来进行注入的.

IOC是一种编程思想,由主动的编程变成被动的接收.
可以通过newClassPathXmlApplicationContext去浏览一下底层源码.

OK,到了现在,我们彻底不用再程序中去改动了,要实现不同的操作,只需要在xml配置文件中进行修改,所谓的loC,一句话搞定:对象由Spring来创建,管理,装配!

2. Spring配置

1. bean

bean 定义(definition)本质上是创建一个或多个对象的“配方”。容器在被要求时查看命名的Bean的“配方”,并使用该Bean定义所封装的配置元数据来创建(或获取)一个实际的对象

bean常用属性
<bean id="hello" class="com.suzezhi.pojo.Hello" scope="singleton" name="hello2">
 <property name="name" value="小陈"></property>
</bean>
属性名描述
id相当于Hello的实例对象
class指定对应的类路径
scope作用域,默认都是singleton(单例模式)
name为id指定的对象设置别名,可以有多个(通过,或者空格分开),在这里hello与hello2都指向Hello类
property注入Hello的属性 name指定属性名,基础数据类型:value直接通过以上例子的简写形式赋值;对象类型:使用ref指向注入的bean
2. import
//ApplicationContext.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
        https://www.springframework.org/schema/beans/spring-beans.xsd">
<!--将其他配置导入-->
    <import resource="services.xml"/>
    <import resource="resources/messageSource.xml"/>
    <import resource="/resources/themeSource.xml"/>
    <!-- 更多bean 定义在这里 -->
    <!--    id唯一标识相当于Hello的实例对象,class指定对应的类-->
    <bean id="hello" class="com.suzezhi.pojo.Hello">
        <property name="name" value="小陈"></property>
    </bean>
</beans>

3. IOC依赖注入

在配置文件加载的时候,容器中管理的对象就被初始化了。

方式:构造器注入 和 setter注入

构造器注入方式

方式一:通过使用 type 属性显式地指定构造函数参数的类型,容器就可以使用简单类型的类型匹配

<bean id="hello" class="com.suzezhi.pojo.Hello">
    <constructor-arg type="java.lang.String" value="小陈"></constructor-arg>
</bean>

方式二:使用 index 属性来明确指定构造函数参数的索引

<bean id="hello" class="com.suzezhi.pojo.Hello">
    <constructor-arg index="0" value="小陈"></constructor-arg>
</bean>

方式三:使用构造函数的参数名称

<bean id="hello" class="com.suzezhi.pojo.Hello">
    <constructor-arg name="name" value="小陈"></constructor-arg>
</bean>
setter注入方式

要写属性的set方法,否则无法注入

//把Cat类当作Person类的复杂数据类型
package com.suzezhi.pojo;

public class Cat {
    private String name;

    public Cat() {
    }

    public Cat(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Cat{" +
                "name='" + name + '\'' +
                '}';
    }
}

package com.suzezhi.pojo;

import java.util.*;

public class Person {
    private String name;
    private Cat cat;
    private List<String> list;
    private String[] arrays;
    private Map<String,String> map;
    private Set<String> set;
    private Properties properties;

    public Person(String name, Cat cat, List<String> list, String[] arrays, Map<String, String> map, Set<String> set, Properties properties) {
        this.name = name;
        this.cat = cat;
        this.list = list;
        this.arrays = arrays;
        this.map = map;
        this.set = set;
        this.properties = properties;
    }

    public Person() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Cat getCat() {
        return cat;
    }

    public void setCat(Cat cat) {
        this.cat = cat;
    }

    public List<String> getList() {
        return list;
    }

    public void setList(List<String> list) {
        this.list = list;
    }

    public String[] getArrays() {
        return arrays;
    }

    public void setArrays(String[] arrays) {
        this.arrays = arrays;
    }

    public Map<String, String> getMap() {
        return map;
    }

    public void setMap(Map<String, String> map) {
        this.map = map;
    }

    public Set<String> getSet() {
        return set;
    }

    public void setSet(Set<String> set) {
        this.set = set;
    }

    public Properties getProperties() {
        return properties;
    }

    public void setProperties(Properties properties) {
        this.properties = properties;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", cat=" + cat +
                ", list=" + list +
                ", arrays=" + Arrays.toString(arrays) +
                ", map=" + map +
                ", set=" + set +
                ", properties=" + properties +
                '}';
    }
}

在配置文件注册

<?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">
<!--Cat类-->
    <bean id="cat" class="com.suzezhi.pojo.Cat"></bean>
<!--    person类-->
    <bean id="person" class="com.suzezhi.pojo.Person">
<!--        注入相关属性-->
        <property name="name" value="小红"></property>
<!--        注入bean,使用ref-->
        <property name="cat" ref="cat"></property>
<!--        注入list-->
        <property name="list">
            <list>
                <value>list1</value>
                <value>list2</value>
                <value>list3</value>
                <value>list4</value>
            </list>
        </property>
<!--        注入数组-->
        <property name="arrays">
            <array>
                <value>西游记</value>
                <value>水浒传</value>
                <value>红楼梦</value>
                <value>三国演义</value>
            </array>
        </property>
<!--        注入map-->
        <property name="map">
            <map>
                <entry key="name" value="中国"></entry>
                <entry key="name" value="朝鲜"></entry>
            </map>
        </property>
<!--        set-->
        <property name="set">
            <set>
                <value>set1</value>
                <value>set2</value>
                <value>set3</value>
            </set>
        </property>
<!--        propertoes-->
        <property name="properties">
            <props>
                <prop key="username">root</prop>
                <prop key="password">123456</prop>
            </props>
        </property>
    </bean>
</beans>
//测试
import com.suzezhi.pojo.Person;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {
    @Test
    public void test(){

        ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
        Person person = (Person) context.getBean("person");
        System.out.println(person);

    }
}

4.Bean的作用域

Scope说明
singleton(默认情况下)为每个Spring IoC容器将单个Bean定义的Scope扩大到单个对象实例。
prototype将单个Bean定义的Scope扩大到任何数量的对象实例。
request将单个Bean定义的Scope扩大到单个HTTP请求的生命周期。也就是说,每个HTTP请求都有自己的Bean实例,该实例是在单个Bean定义的基础上创建的。只在Web感知的Spring ApplicationContext 的上下文中有效。
session将单个Bean定义的Scope扩大到一个HTTP Session 的生命周期。只在Web感知的Spring ApplicationContext 的上下文中有效。
application将单个Bean定义的 Scope 扩大到 ServletContext 的生命周期中。只在Web感知的Spring ApplicationContext 的上下文中有效。
websocket将单个Bean定义的 Scope 扩大到 WebSocket 的生命周期。仅在具有Web感知的 Spring ApplicationContext 的上下文中有效。

5. 自动注入

使用autowire属性将其他bean注册进来

byName

<?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">
    <bean id="dog11" class="com.suzezhi.pojo.Dog"></bean>
    <bean id="cat" class="com.suzezhi.pojo.Cat"></bean>

<!--
这样不需要我们写<property name="cat" ref="cat"></property>这种引入其他bean的代码
byName:会自动查找和自己在对象上set后面的值对应的beanid,上面的cat能找到(setCat),dog11找不到(setDog)

-->
    <bean id="person" class="com.suzezhi.pojo.Person" autowire="byName">
        <property name="name" value=""></property>
    </bean>
</beans>

byType

<?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">
    <bean id="dog11" class="com.suzezhi.pojo.Dog"></bean>
    <bean id="cat" class="com.suzezhi.pojo.Cat"></bean>

<!--
这样不需要我们写<property name="cat" ref="cat"></property>这种引入其他bean的代码
byName:会自动在上下文查找,和自己在对象上set后面的值对应的beanid,上面的cat能找到(setCat),dog11找不到(setDog)
byType:会自动在上下文查找,和自己在对象上类型对应的beanid,上面都可以找到
-->
    <bean id="person" class="com.suzezhi.pojo.Person" autowire="byType">
        <property name="name" value=""></property>
    </bean>
</beans>

6. 基于注解的方式

  1. 导入:context约束
  2. 配置: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:component-scan base-package="com.suzezhi"></context:component-scan>
    <context:annotation-config/>

</beans>
package com.suzezhi.pojo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

//相当于xml文件的bean
@Component
public class Person {
    //为name赋值
    @Value("小陈")
    private String name;
    //相当于xml文件的<property name="cat" ref="cat"></property>
    @Autowired
    private Cat cat;
    @Autowired
    private Dog dog;

    public Person(String name, Cat cat, Dog dog) {
        this.name = name;
        this.cat = cat;
        this.dog = dog;
    }

    public Person() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Cat getCat() {
        return cat;
    }

    public void setCat(Cat cat) {
        this.cat = cat;
    }

    public Dog getDog() {
        return dog;
    }

    public void setDog(Dog dog) {
        this.dog = dog;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", cat=" + cat +
                ", dog=" + dog +
                '}';
    }
}

7. 使用Java配置类

使用java配置类实现全注解方式,不需要写xml配置文件

package com.suzezhi.config;

import com.suzezhi.pojo.Person;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

//设置为配置文件
@Configuration
//扫描包路径
@ComponentScan("com.suzezhi")
//就像 <import/> 元素在Spring XML文件中被用来帮助模块化配置一样,@Import 注解允许从另一个配置类中加载 @Bean 定义
//@Import(ConfigA.class),将configA.class配置文件导入到本配置文件中,外面直接使用本配置文件就可以拿到A的配置信息
public class JavaConfig {
//    相当于<bean id="person" class="com.suzezhi.pojo.Person"></bean>
//    默认情况下,配置类使用 @Bean 方法的名称作为结果Bean的名称。然而,这个功能可以通过 name 属性来重写@Bean("person1")。
    @Bean
    public Person person() {
        return new Person();
    }
}

import com.suzezhi.config.JavaConfig;
import com.suzezhi.pojo.Person;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {
    @Test
    public void test(){
//        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");
//        Person person = applicationContext.getBean("person", Person.class);
//        person.getCat().shout();
//        person.getDog().shout();

        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(JavaConfig.class);
        Person person = applicationContext.getBean("person", Person.class);
        person.getDog().shout();
    }
}

二、AOP

AOP是一种横向编程,不需要改变原来的业务逻辑

使用Spring AOP需要导入依赖包

<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.3.18</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.9.7</version>
    </dependency>

1. xml方式

写一个测试业务的类

package com.suzezhi.service;

public class UserServiceImpl {
    public void add(){
        System.out.println("添加方法");
    }
    public void del(){
        System.out.println("删除方法");
    }
    public void update(){
        System.out.println("更改方法");
    }
    public void select(){
        System.out.println("查询方法");
    }
}

创建一个切面类

package com.suzezhi.aspect;

import org.aspectj.lang.ProceedingJoinPoint;

/*这是一个切面*/
public class MyAspect {
    /*
    * 通知,就是方法
    * */
    //前置方法
    public void before(){
        System.out.println("前置方法》》》》》");
    }
    //后置方法
    public void after(){
        System.out.println("后置方法》》》》》");
    }
    // 环绕方法,要有连接点作为参数
    public void round(ProceedingJoinPoint joinPoint) throws Throwable {
        Object proceed = joinPoint.proceed();
        System.out.println("》》环绕方法《《");
    }
}

spring的配置文件

引入aop:aspectj-autoproxy/

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

<!--    引入aop-->
    <aop:aspectj-autoproxy/>
<!--  注册业务类,测试用-->
    <bean id="userServiceImpl" class="com.suzezhi.service.UserServiceImpl">
    </bean>
<!--    注册切面类-->
    <bean id="myAspect" class="com.suzezhi.aspect.MyAspect"></bean>

<!--    声明配置aop-->
    <aop:config>
<!--        指定注册的切面,id是标识,ref来自上面注册的切面-->
        <aop:aspect id="aspect" ref="myAspect">
<!--            指定切点,以及接入点(用于那个包) id是切入点的唯一标识,expression里面设置那些路径为连接点,就是要使用aop的-->
            <aop:pointcut id="point" expression="execution(* com.suzezhi.service.*.*(..))"/>
<!--            指定前置方法和后置方法,就是通知,method指定切面类定义的方法,pointcut-ref指定运用到那个切入点上-->
            <aop:before method="before" pointcut-ref="point"></aop:before>
            <aop:after method="after" pointcut-ref="point"></aop:after>
        </aop:aspect>
    </aop:config>



</beans>

测试类

import com.suzezhi.service.UserServiceImpl;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {
    @Test
    public void test(){
//        加载spring配置文件
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
//        获取注册的bean
        UserServiceImpl userServiceImpl = applicationContext.getBean("userServiceImpl", UserServiceImpl.class);
//        调用对应的方法
        userServiceImpl.add();
    }
}

测试结果

# 测试里面使用的add方法打印`添加方法`,切面里面定义了前置通知和后置通知,所以add()的内容会被包含在中间
前置方法》》》》》
添加方法
后置方法》》》》》

2. 基于注解方式

使用xml的例子,修改spring配置文件和切面文件

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

<!--    引入注解-->
<!--    <context:annotation-config/>-->
<!--    引入aop-->
    <aop:aspectj-autoproxy/>

    <bean id="userServiceImpl" class="com.suzezhi.service.UserServiceImpl">
    </bean>

<!--    注册切面类-->
    <bean id="myAspect" class="com.suzezhi.aspect.MyAspect"></bean>
</beans>

切面文件

package com.suzezhi.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class MyAspect {
    /*
     * 通知,就是方法
     * */
    //前置方法
    @Before("execution(* com.suzezhi.service.*.*(..))")
    public void before(){
        System.out.println("前置方法》》》》》");
    }
    //后置方法
    @After("execution(* com.suzezhi.service.*.*(..))")
    public void after(){
        System.out.println("后置方法》》》》》");
    }
    // 环绕方法
    @Around("execution(* com.suzezhi.service.*.*(..))")
    public Object round(ProceedingJoinPoint joinPoint) throws Throwable {
        Object proceed = joinPoint.proceed();
        System.out.println("》》环绕方法《《");
        return proceed;
    }
}

三、Spring整合Mybatis(mybatis-spring)

MyBatis-Spring 会帮助你将 MyBatis 代码无缝地整合到 Spring 中。它将允许 MyBatis 参与到 Spring 的事务管理之中,创建映射器 mapper 和 SqlSession 并注入到 bean 中,以及将 Mybatis 的异常转换为 Spring 的 DataAccessException。 最终,可以做到应用代码不依赖于 MyBatis,Spring 或 MyBatis-Spring。

mybatis-spring官网

MyBatis-SpringMyBatisSpring FrameworkSpring BatchJava
2.03.5+5.0+4.0+Java 8+
1.33.4+3.2.2+2.1+Java 6+

前置条件:

由于要使用spring,mybatis,mysql(数据库),数据库驱动等等需要使用到这几个依赖

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13.2</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.6</version>
</dependency>
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis-spring</artifactId>
    <version>2.0.4</version>
</dependency>
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.12</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.3.22</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.3.22</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.47</version>
</dependency>

接下来的步骤跟使用mybatis差不多,我们先做相同点

创建一个user表

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(30) COLLATE utf8_bin NOT NULL,
  `password` varchar(30) COLLATE utf8_bin NOT NULL,
  `email` varchar(25) COLLATE utf8_bin DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

-- 插入数据
insert into user(username,password,email) values('小小','123456','xiao@qq.com'),('大大','123456','da@qq.com')

创建user实体类

package com.suzezhi.pojo;

public class User {
    private int id;
    private String username;
    private String password;
    private String email;

    public User(int id, String username, String password, String email) {
        this.id = id;
        this.username = username;
        this.password = password;
        this.email = email;
    }

    public User() {
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

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

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", email='" + email + '\'' +
                '}';
    }
}

创建Mapper(或者Dao)接口

package com.suzezhi.mapper;

import com.suzezhi.pojo.User;

import java.util.List;

public interface UserMapper {
    //查询用户的方法
    List<User> getUserAll();
}

创建映射文件,我创建在resources目录下,包和文件命名与上面的UserMapper保持一致,也可以将映射文件放在mapper接口的同一目录下(需要配置pom.xml文件,使其过滤时包含上mapper目录上的xml文件)

<!-- resources/com/suzezhi/mapper/UserMapper.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--指定命名空间,就是定义的接口类-->
<mapper namespace="com.suzezhi.mapper.UserMapper">
<!--    resultType这里使用别名,在Mybatis核心配置文件设置-->
    <select id="getUserAll" resultType="User">
        select * from USER ;
    </select>
</mapper>

从设置mybatis核心配置文件开始就有所不同了,由于整合mybatis,所以mybatis-config.xml文件我们一般只放起别名和设置(或者全部整合到Spring配置文件中)

<!-- mybatis-config.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">
<configuration>
    <settings>
<!--        配置日志-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
    <typeAliases>
<!--        起别名-->
        <typeAlias type="com.suzezhi.pojo.User" alias="User"></typeAlias>
    </typeAliases>
</configuration>

到这里mybatis已配置完成,之前只需将xxxmapper.xml的注册到mybatis-config.xml文件中就可以了

现在由于使用spring整合,需要一个类来注册成组件,所以创建一个UserMapper的实现类(这是不同点)

//UserMapperImpl.java
package com.suzezhi.mapper.impl;

import com.suzezhi.mapper.UserMapper;
import com.suzezhi.pojo.User;
import org.mybatis.spring.SqlSessionTemplate;

import java.util.List;

public class UserMapperImpl implements UserMapper {
    private SqlSessionTemplate sqlSession;
    //设置set方法,用于依赖注入
    public void setSqlSession(SqlSessionTemplate sqlSession) {
        this.sqlSession = sqlSession;
    }

    public List<User> getUserAll() {
        //获取mapper
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> userAll = mapper.getUserAll();
        return userAll;
    }
}

spring的配置文件**,重要:获取sqlSessionFactory对象注册sqlSession对象 对应的SqlSessionTemplate**

<?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">

<!--    获取数据源(这里使用jdbc)-->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://localhost:3306/mybatis_test?useSSL=false&amp;useUnicode=true&amp;characterEncoding=UTF8"></property>
        <property name="username" value="root"></property>
        <property name="password" value="134679"></property>
    </bean>

<!--    获取sqlSessionFactory对象-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--        添加数据源-->
        <property name="dataSource" ref="dataSource"></property>
<!--        添加mybatis配置文件-->
        <property name="configLocation" value="mybatis-config.xml"></property>
<!--        添加mapper的映射文件-->
        <property name="mapperLocations" value="com/suzezhi/mapper/*.xml"></property>
    </bean>

<!--    注册sqlSession对象  对应的SqlSessionTemplate-->
    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<!--        SqlSessionTemplate没有setter,只有构造函数,需要一个sqlSessionFactory对象-->
        <constructor-arg index="0" ref="sqlSessionFactory"></constructor-arg>
    </bean>

<!--    给接口实现类注入sqlSession对象-->
    <bean id="userMapperImpl" class="com.suzezhi.mapper.impl.UserMapperImpl">
        <property name="sqlSession" ref="sqlSession"></property>
    </bean>
</beans>

测试类

public class MyTest {
@Test
public void test(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    UserMapper userMapperImpl = applicationContext.getBean("userMapperImpl", UserMapperImpl.class);
    List<User> userAll = userMapperImpl.getUserAll();
    for (User user : userAll) {
        System.out.println(user);
    }
}
总结差异点

mybatis:

  1. mybatis单独使用,数据源配置和xxxmapper.xml文件映射在mybatis-config.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">
    <configuration>
        <environments default="development">
            <environment id="development">
                <transactionManager type="JDBC"/>
                <dataSource type="POOLED">
                    <property name="driver" value="com.mysql.jdbc.Driver"/>
                    <property name="url" value="jdbc:mysql://localhost:3306/mybatis_test?useUnicode=true&amp;characterEncoding=UTF-8"/>
                    <property name="username" value="root"/>
                    <property name="password" value="134679"/>
                </dataSource>
            </environment>
        </environments>
        <mappers>
            <mapper resource="mapper/userMapper.xml"></mapper>
        </mappers>
    </configuration>
    
  2. 通过SqlSessionFactoryBuilder绑定资源创建了SqlSessionFactory,通过SqlSessionFactory对象获取SqlSession

    public class MybatisUtil {
        private static SqlSessionFactory sqlSessionFactory=null;
        //让以下代码进来就初始化
        static {
            String resource = "mybatis-config.xml";
            InputStream inputStream = null;
            try {
                inputStream = Resources.getResourceAsStream(resource);
            } catch (IOException e) {
                e.printStackTrace();
            }
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        }
        //返回一个SqlSession对象,操作sql需要用到
        public static SqlSession getSqlSession(){
            return sqlSessionFactory.openSession();
        }
    }
    
    
  3. SqlSession绑定接口映射器实现数据库操作

    public class TestUserMapper {
        @Test
        public void test(){
            //获取sqlsession对象
            SqlSession sqlSession = MybatisUtil.getSqlSession();
            //获取mapper接口类
            UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
            //调用方法执行其对应的sql
            List<User> userList = userMapper.getUserList();
    
            //打印内容
            for (User user : userList) {
                System.out.println(user);
            }
            
            //关闭sqlsession
            sqlSession.close();
        }
    }
    
    

使用数据源配置文件

我们一般会将数据库的相关信息抽出成一个properties文件

db.properties

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis_test?useSSL=false&amp;useUnicode=true&amp;characterEncoding=UTF8
username=root
password=134679
<!-- applicationContext.xml -->
<!--    加载数据库配置文件-->
    <context:property-placeholder location="classpath:db.properties"/>
<!--    获取数据源(这里使用jdbc)-->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<!--        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>-->
<!--        <property name="url" value="jdbc:mysql://localhost:3306/mybatis_test?useSSL=false&amp;useUnicode=true&amp;characterEncoding=UTF8"></property>-->
<!--        <property name="username" value="root"></property>-->
<!--        <property name="password" value="134679"></property>-->
<!--        通过拿db.propperties文件的信息-->
        <property name="driverClassName" value="${driver}"></property>
        <property name="url" value="${url}"></property>
        <property name="username" value="${username}"></property>
        <property name="password" value="${password}"></property>
    </bean>

声明式事务管理

使用mybatis时,可以通过SqlSession对象调用commit()进行事务提交,调用rollback()进行事务回滚。

使用spring整合后,我们可以使用Aop切面编程进行事务控制,来是业务处理和事务管控分离。

<!--    配置声明式事务-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
<!--    通过AOP实现事务的直入-->
<!--    配置事务通知-->
    <tx:advice id="transactionInterceptor" transaction-manager="transactionManager">
        <tx:attributes>
<!--            配置所有方法都指向事务-->
            <tx:method name="*" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>
<!--    配置事务切入-->
    <aop:config>
<!--        com.suzezhi.mapper这个包下的所有方法都执行aop切面操作-->
        <aop:pointcut id="txPoint" expression="execution(* com.suzezhi.mapper.*.*(..))"/>
        <aop:advisor advice-ref="transactionInterceptor" pointcut-ref="txPoint"></aop:advisor>
    </aop:config>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值