【编程不良人】快速入门Spring学习笔记07---创建复杂对象及SM整合

本文详细介绍了如何在Maven项目中创建复杂对象,如接口和抽象类的实例,通过FactoryBean实现。接着,讲解了Spring和Mybatis的整合思路,包括Spring管理SqlSessionFactory、数据源配置、Mapper配置、DAO组件创建等内容。此外,还展示了Service层的事务控制和优化,以及如何通过log4j添加日志。最后,文章提到了SM整合的DAO和Service编程步骤,以及日志管理的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.创建复杂对象

复杂对象:类中没有构造方法或者构造方法不能调用,如接口类型或抽象类实例

 新建Maven-webapp工程,添加java、resources目录

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>org.example</groupId>
    <artifactId>spring03</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>
  ​
    <name>spring03 Maven Webapp</name>
    <!-- FIXME change it to the project's website -->
    <url>http://www.example.com</url>
  ​
    <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <maven.compiler.source>1.7</maven.compiler.source>
      <maven.compiler.target>1.7</maven.compiler.target>
    </properties>
  ​
    <dependencies>
      <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.11</version>
        <scope>test</scope>
      </dependency>
  ​
      <!--spring核心及相关依赖-->
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>4.3.2.RELEASE</version>
      </dependency>
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>4.3.2.RELEASE</version>
      </dependency>
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>4.3.2.RELEASE</version>
      </dependency>
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-expression</artifactId>
        <version>4.3.2.RELEASE</version>
      </dependency>
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aop</artifactId>
        <version>4.3.2.RELEASE</version>
      </dependency>
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>4.3.2.RELEASE</version>
      </dependency>
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context-support</artifactId>
        <version>4.3.2.RELEASE</version>
      </dependency>
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
        <version>4.3.2.RELEASE</version>
      </dependency>
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>4.3.2.RELEASE</version>
      </dependency>
  ​
      <!--mysql-->
      <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.38</version>
      </dependency>
  ​
      <!--mybatis-->
      <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.4</version>
      </dependency>
  ​
      <!--mybatis-spring-->
      <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis-spring</artifactId>
        <version>2.0.4</version>
      </dependency>
  ​
      <!--druid-->
      <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.1.19</version>
      </dependency>
  ​
    </dependencies>
  ​
    <build>
      <finalName>spring03</finalName>
      <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
        <plugins>
          <plugin>
            <artifactId>maven-clean-plugin</artifactId>
            <version>3.1.0</version>
          </plugin>
          <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
          <plugin>
            <artifactId>maven-resources-plugin</artifactId>
            <version>3.0.2</version>
          </plugin>
          <plugin>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.0</version>
          </plugin>
          <plugin>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.22.1</version>
          </plugin>
          <plugin>
            <artifactId>maven-war-plugin</artifactId>
            <version>3.2.2</version>
          </plugin>
          <plugin>
            <artifactId>maven-install-plugin</artifactId>
            <version>2.5.2</version>
          </plugin>
          <plugin>
            <artifactId>maven-deploy-plugin</artifactId>
            <version>2.8.2</version>
          </plugin>
        </plugins>
      </pluginManagement>
    </build>
  </project>
  ​

1.1 抽象类Calendar

CalendarFactoryBean.java

  
  package factorybean;
  ​
  import org.springframework.beans.factory.FactoryBean;
  ​
  import java.util.Calendar;
  ​
  /**
   * @ClassName CalendarFactoryBean
   * @Description 用来在工厂中创建复杂对象Calendar
   * @Author Jiangnan Cui
   * @Date 2022/4/7 21:33
   * @Version 1.0
   */
  public class CalendarFactoryBean implements FactoryBean<Calendar> {
      //用来书写复杂对象的创建方式
      @Override
      public Calendar getObject() throws Exception {
          return Calendar.getInstance();
      }
  ​
      //指定创建的复杂对象类型
      @Override
      public Class<?> getObjectType() {
          return Calendar.class;
      }
  ​
      //用来指定创建的对象模式 true表示单例,false表示多例
      @Override
      public boolean isSingleton() {
          return true;
      }
  }
  ​

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"
         xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
      <!--管理组件对象-->
      <bean class="factorybean.CalendarFactoryBean" id="calendar"/>
  </beans>

CalendarTest.java

  
package test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.Calendar;

/**
 * @ClassName CalendarTest
 * @Description TODO
 * @Author Jiangnan Cui
 * @Date 2022/4/7 21:39
 * @Version 1.0
 */
public class CalendarTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("factorybean/spring.xml");
        Calendar calendar = (Calendar) context.getBean("calendar");
        System.out.println(calendar);
        Calendar calendar1 = (Calendar) context.getBean("calendar");
        System.out.println(calendar1);
        System.out.println(calendar==calendar1);
    }
}

1.2 接口Connection

ConnectionFactoryBean.java

  
  package factorybean;
  ​
  import org.springframework.beans.factory.FactoryBean;
  ​
  import java.sql.Connection;
  import java.sql.DriverManager;
  ​
  /**
   * @ClassName ConnectionFactoryBean
   * @Description 用工厂创建复杂对象Connection
   * @Author Jiangnan Cui
   * @Date 2022/4/7 21:43
   * @Version 1.0
   */
  public class ConnectionFactoryBean implements FactoryBean<Connection> {
      @Override
      public Connection getObject() throws Exception {
          Class.forName("com.mysql.jdbc.Driver");
          return DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis","root","123456");
      }
  ​
      @Override
      public Class<?> getObjectType() {
          return Connection.class;
      }
  ​
      @Override
      public boolean isSingleton() {
          return false;
      }
  }
  ​

spring.xml

  
  <bean class="factorybean.ConnectionFactoryBean" id="connection"/>

ConnectionTest.java

  
  package test;
  ​
  import org.springframework.context.ApplicationContext;
  import org.springframework.context.support.ClassPathXmlApplicationContext;
  ​
  import java.sql.Connection;
  ​
  /**
   * @ClassName ConnectionTest
   * @Description TODO
   * @Author Jiangnan Cui
   * @Date 2022/4/7 21:48
   * @Version 1.0
   */
  public class ConnectionTest {
      public static void main(String[] args) {
          ApplicationContext context = new ClassPathXmlApplicationContext("factorybean/spring.xml");
          Connection connection = (Connection) context.getBean("connection");
          System.out.println(connection);
          Connection connection1 = (Connection) context.getBean("connection");
          System.out.println(connection1);
          System.out.println(connection==connection1);
      }
  }
  ​

2. SM整合思路

配套视频:【编程不良人】快速入门Spring,SpringBoot、SpringCloud学不好完全是因为Spring没有掌握!_哔哩哔哩_bilibili

2.1 spring框架的作用

spring框架 项目管理框架 主要负责项目中组件对象的创建

2.2 Mybatis框架的作用

Mybatis框架 持久层框架 主要用来简化数据库访问的操作

2.3 整合思路

整合思路: 两个框架作用不同,貌似没有什么联系,更深入看才能看出所谓Spring整合Mybatis,其实就是通过spring框架接管mybatis框架中核心对象的创建

2.4 Mybatis中的核心对象

Mybatis的核心对象为: SqlSessionFactory

整合就是通过Spring管理SqlSessionFactory对象的创建

2.5 整合思路

总体示意图:

 Spring整合Mybatis思路分析:

 Spring整合Mybatis编程步骤:

2.6 具体实现

(1)引入依赖

      <!--spring核心及相关依赖-->
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>4.3.2.RELEASE</version>
      </dependency>
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>4.3.2.RELEASE</version>
      </dependency>
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>4.3.2.RELEASE</version>
      </dependency>
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-expression</artifactId>
        <version>4.3.2.RELEASE</version>
      </dependency>
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aop</artifactId>
        <version>4.3.2.RELEASE</version>
      </dependency>
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>4.3.2.RELEASE</version>
      </dependency>
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context-support</artifactId>
        <version>4.3.2.RELEASE</version>
      </dependency>
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
        <version>4.3.2.RELEASE</version>
      </dependency>
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>4.3.2.RELEASE</version>
      </dependency>
  ​
      <!--mysql-->
      <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.38</version>
      </dependency>
  ​
      <!--mybatis-->
      <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.4</version>
      </dependency>
  ​
      <!--mybatis-spring-->
      <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis-spring</artifactId>
        <version>2.0.4</version>
      </dependency>
  ​
      <!--druid-->
      <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.1.19</version>
      </dependency>
  ​

(2)配置spring.xml

  
      <!--创建sqlSessionFactory对象-->
      <bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sqlSessionFactory">
          <!--依赖数据源对象-->
          <property name="dataSource" ref="dataSource"/>
          <!--依赖mapper文件注册-->
  ​
      </bean>
  ​
      <!--创建数据源对象druid,需要引入druid依赖,类似的数据源还有C3p0、dbcp等-->
      <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
          <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
          <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
          <property name="username" value="root"/>
          <property name="password" value="123456"/>
      </bean>
  ​

(3)测试SqlSessionFactory是否创建成功

  
  package test;
  ​
  import org.apache.ibatis.session.SqlSessionFactory;
  import org.springframework.context.ApplicationContext;
  import org.springframework.context.support.ClassPathXmlApplicationContext;
  ​
  /**
   * @ClassName SqlSessionFactoryTest
   * @Description 测试SqlSessionFactory是否创建成功
   * @Author Jiangnan Cui
   * @Date 2022/4/8 16:59
   * @Version 1.0
   */
  public class SqlSessionFactoryTest {
      public static void main(String[] args) {
          ApplicationContext context = new ClassPathXmlApplicationContext("factorybean/spring.xml");
          SqlSessionFactory sqlSessionFactory = (SqlSessionFactory) context.getBean("sqlSessionFactory");
          System.out.println(sqlSessionFactory);
  ​
      }
  }
  ​

测试结果:

  
  org.apache.ibatis.session.defaults.DefaultSqlSessionFactory@2d2e5f00

3. SM整合DAO编程步骤

配套视频:【编程不良人】快速入门Spring,SpringBoot、SpringCloud学不好完全是因为Spring没有掌握!_哔哩哔哩_bilibili

3.0 整合思路

SM整合编码之DAO层思路分析流程:

 SM整合之DAO层编程步骤:

3.1 引入mybatis的依赖jar包

  
  <dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.2.8</version>
  </dependency>

3.2 引入Spring相关jar包

  
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>4.3.2.RELEASE</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>4.3.2.RELEASE</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context-support</artifactId>
    <version>4.3.2.RELEASE</version>
  </dependency>
  <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>4.3.2.RELEASE</version>
    </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aop</artifactId>
    <version>4.3.2.RELEASE</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-beans</artifactId>
    <version>4.3.2.RELEASE</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-expression</artifactId>
    <version>4.3.2.RELEASE</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
    <version>4.3.2.RELEASE</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-tx</artifactId>
    <version>4.3.2.RELEASE</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>4.3.2.RELEASE</version>
  </dependency>

3.3 mybatis-spring整合jar

  
  <dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis-spring</artifactId>
    <version>1.3.1</version>
  </dependency>

3.4 引入数据库驱动jar

  
  <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.40</version>
  </dependency>
  <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid</artifactId>
      <version>1.1.12</version>
  </dependency>

3.5 建表

  
  CREATE TABLE `t_user` (
    `id` varchar(40) NOT NULL,
    `name` varchar(40) DEFAULT NULL,
    `age` int(3) DEFAULT NULL,
    `bir` timestamp NULL DEFAULT NULL,
    PRIMARY KEY (`id`)
  ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

3.6 编写实体类

  package entity;
  ​
  import java.util.Date;
  ​
  /**
   * @ClassName User
   * @Description TODO
   * @Author Jiangnan Cui
   * @Date 2022/4/8 17:44
   * @Version 1.0
   */
  public class User {
      private String id;
      private String name;
      private Integer age;
      private Date bir;
  ​
      public User() {
      }
  ​
      public User(String id, String name, Integer age, Date bir) {
          this.id = id;
          this.name = name;
          this.age = age;
          this.bir = bir;
      }
  ​
      public String getId() {
          return id;
      }
  ​
      public void setId(String id) {
          this.id = id;
      }
  ​
      public String getName() {
          return name;
      }
  ​
      public void setName(String name) {
          this.name = name;
      }
  ​
      public Integer getAge() {
          return age;
      }
  ​
      public void setAge(Integer age) {
          this.age = age;
      }
  ​
      public Date getBir() {
          return bir;
      }
  ​
      public void setBir(Date bir) {
          this.bir = bir;
      }
  ​
      @Override
      public String toString() {
          return "User{" +
                  "id='" + id + '\'' +
                  ", name='" + name + '\'' +
                  ", age=" + age +
                  ", bir=" + bir +
                  '}';
      }
  }
  ​

3.7 书写DAO接口

  package dao;
  ​
  import entity.User;
  ​
  import java.util.List;
  ​
  /**
   * @ClassName UserDAO
   * @Description TODO
   * @Author Jiangnan Cui
   * @Date 2022/4/8 17:46
   * @Version 1.0
   */
  public interface UserDAO {
      //根据id查询用户信息
      User findById(String id);
  ​
      //查询所有用户信息
      List<User> findAll();
  ​
      //新增用户
      void insert(User user);
  ​
      //根据id修改用户
      void update(User user);
  ​
      //根据id删除用户
      void delete(String id);
  }
  ​

3.8 编写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" >
  <!--
      mapper为映射的根节点,用来管理DAO接口
      namespace指定DAO接口的完整类名,表示mapper配置文件管理哪个DAO接口(包.接口名)
      mybatis会依据这个接口动态创建一个实现类去实现这个接口,而这个实现类是一个Mapper对象
   -->
  <mapper namespace="dao.UserDAO">
      <!--
          id = "接口中的方法名"
          parameterType = "接口中传入方法的参数类型"
          resultType = "返回实体类对象:包.类名"  处理结果集 自动封装
          注意:sql语句后不要出现";"号
              查询:select标签
              增加:insert标签
              修改:update标签
              删除:delete标签
      -->
      <!--根据id查询用户信息-->
      <select id="findById" parameterType="String" resultType="entity.User">
          select id,name,age,bir from t_user where id=#{id}
      </select>
  ​
      <!--查询所有用户信息-->
      <select id="findAll" resultType="entity.User">
          select id,name,age,bir from t_user
      </select>
  ​
      <!--新增用户-->
      <insert id="insert" parameterType="entity.User">
          insert into t_user values(#{id},#{name},#{age},#{bir});
      </insert>
  ​
      <!--根据id修改用户-->
      <update id="update" parameterType="entity.User">
          update t_user set name=#{name},age=#{age},bir=#{bir} where id=#{id}
      </update>
  ​
      <!--根据id删除用户-->
      <delete id="delete" parameterType="String">
          delete from t_user where id=#{id}
      </delete>
  ​
  </mapper>

3.9 编写Spring-myabtis整合配置文件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"
         xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
  ​
      <!--创建sqlSessionFactory-->
      <bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sqlSessionFactory">
          <!--依赖数据源-->
          <property name="dataSource" ref="dataSource"/>
          <!--注入mapper配置文件-->
          <property name="mapperLocations">
              <array>
                  <!--依次注册mapper-->
                  <value>classpath:mapper/UserDAOMapper.xml</value>
              </array>
          </property>
      </bean>
  ​
      <!--创建dataSource-->
      <bean class="com.alibaba.druid.pool.DruidDataSource" id="dataSource">
          <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
          <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
          <property name="username" value="root"/>
          <property name="password" value="123456"/>
      </bean>
  ​
      <!--创建DAO组件类-->
      <bean class="org.mybatis.spring.mapper.MapperFactoryBean" id="userDAO">
          <!--注入SqlSessionFactory-->
          <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
          <!--注入创建的DAO接口类型(接口的全限定名:包名.接口名)-->
          <property name="mapperInterface" value="dao.UserDAO"/>
      </bean>
  ​
  </beans>

3.10 启动工厂测试

  package test;
  ​
  ​
  import dao.UserDAO;
  import entity.User;
  import org.apache.ibatis.session.SqlSessionFactory;
  import org.junit.Test;
  import org.springframework.context.ApplicationContext;
  import org.springframework.context.support.ClassPathXmlApplicationContext;
  import org.springframework.web.bind.annotation.RestController;
  ​
  import java.util.Date;
  import java.util.List;
  import java.util.UUID;
  ​
  /**
   * @ClassName UserDAOTest
   * @Description TODO
   * @Author Jiangnan Cui
   * @Date 2022/4/8 17:55
   * @Version 1.0
   */
  public class UserDAOTest {
      public static void main(String[] args) {
          ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
          //SqlSessionFactory sqlSessionFactory = (SqlSessionFactory) context.getBean("sqlSessionFactory");
          //SqlSession sqlSession = sqlSessionFactory.openSession();
          //System.out.println(sqlSession);
          //UserDAO userDAO = sqlSession.getMapper(UserDAO.class);
          //mybatis-spring  jar  MapperFactoryBean  创建DAO对象一个类
          // 1.依赖于SqlSessionFactory 2.依赖创建DAO全限定名
          UserDAO userDAO = (UserDAO) context.getBean("userDAO");
          List<User> users = userDAO.findAll();
          users.forEach(user-> System.out.println("user = " + user));
      }
  ​
      @Test
      public void findByIdTest(){
          ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
          UserDAO userDAO = (UserDAO) context.getBean("userDAO");
          User user1 = userDAO.findById("1");
          System.out.println("user1 = " + user1);
      }
  ​
      @Test
      public void findAllTest(){
          ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
          UserDAO userDAO = (UserDAO) context.getBean("userDAO");
          List<User> users = userDAO.findAll();
          users.forEach(user -> System.out.println("user = " + user));
      }
  ​
      @Test
      public void insertTest(){
          ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
          UserDAO userDAO = (UserDAO) context.getBean("userDAO");
          String id = UUID.randomUUID().toString();
          userDAO.insert(new User(id,"lisi",60,new Date()));
      }
  ​
      @Test
      public void updateTest(){
          ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
          UserDAO userDAO = (UserDAO) context.getBean("userDAO");
          userDAO.update(new User("4","wangwu",25,new Date()));
      }
  ​
      @Test
      public void deleteTest(){
          ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
          UserDAO userDAO = (UserDAO) context.getBean("userDAO");
          userDAO.delete("4");
      }
  }
  ​

补充:SM整合编码之DAO细节优化

 即:

(1)mapper配置文件注入方式

a. 以数组形式单个注入

  <property name="mapperLocations">
      <array>
          <!--依次注册mapper-->
          <value>classpath:mapper/UserDAOMapper.xml</value>
      </array>
  </property>

b. 通用mapper配置文件扫描注入(推荐使用)

  <property name="mapperLocations" value="classpath:mapper/*.xml"/>

+ 补充:起别名

  <!--
      注入别名相关配置typeAliasesPackage:用来给指定包中所有类起别名
      默认的别名:类名/类名首字母小写
  -->
  <!--指定包-->
  <property name="typeAliasesPackage" value="entity"/>

(2)创建DAO组件类

a. 单个注入

  <bean class="org.mybatis.spring.mapper.MapperFactoryBean" id="userDAO">
      <!--注入SqlSessionFactory-->
      <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
      <!--注入创建的DAO接口类型(接口的全限定名:包名.接口名)-->
      <property name="mapperInterface" value="dao.UserDAO"/>
  </bean>

b. 一次性注入所有(推荐使用)

  <!--
      一次项目创建项目中所有DAO对象 
      MapperScannerConfigurer:
      默认创建对象在工厂中的唯一标识为接口首字母小写
      例如:UserDAO->userDAO    Userdao->userdao
           OrderDAO->orderDAO  Orderdao->orderdao
           EmpDAO->empDAO
  -->
  <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
      <!--注入SqlSessionFactory对象-->
      <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
      <!--扫描DAO接口所在包-->
      <property name="basePackage" value="dao"/>
  </bean>

优化后如下:

  
      <!--创建dataSource-->
      <bean class="com.alibaba.druid.pool.DruidDataSource" id="dataSource">
          <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
          <property name="url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=UTF-8"/>
          <property name="username" value="root"/>
          <property name="password" value="123456"/>
      </bean>
  ​
      <!--创建sqlSessionFactory-->
      <bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sqlSessionFactory">
          <!--依赖数据源-->
          <property name="dataSource" ref="dataSource"/>
          <!--通用mapper配置文件扫描注入,推荐使用-->
          <property name="mapperLocations" value="classpath:mapper/*.xml"/>
          <!--
              注入别名相关配置typeAliasesPackage:用来给指定包中所有类起别名
              默认的别名:类名/类名首字母小写
          -->
          <!--指定包-->
          <property name="typeAliasesPackage" value="entity"/>
      </bean>
  ​
      <!--创建DAO组件类:一次项目创建项目中所有DAO对象-->
      <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
          <!--注入SqlSessionFactory对象-->
          <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
          <!--扫描DAO接口所在包-->
          <property name="basePackage" value="dao"/>
      </bean>

4. SM整合Service编程步骤

配套视频:【编程不良人】快速入门Spring,SpringBoot、SpringCloud学不好完全是因为Spring没有掌握!_哔哩哔哩_bilibili

4.1 整合思路

SM整合之Service层事务控制思路分析:

 SM整合DAO和Service部分编程步骤:

 具体实现:

4.2 开发Service接口

  
  package service;
  ​
  import entity.User;
  ​
  import java.util.List;
  ​
  /**
   * @ClassName UserService
   * @Description TODO
   * @Author Jiangnan Cui
   * @Date 2022/4/9 17:13
   * @Version 1.0
   */
  public interface UserService {
      //查询所有用户
      List<User> findAll();
  ​
      //插入用户数据
      void insert(User user);
  }
  ​

4.3 开发Service实现类

  
  package service;
  ​
  import dao.UserDAO;
  import entity.User;
  import org.springframework.transaction.PlatformTransactionManager;
  import org.springframework.transaction.TransactionDefinition;
  import org.springframework.transaction.TransactionStatus;
  import org.springframework.transaction.support.DefaultTransactionDefinition;
  ​
  import java.util.List;
  import java.util.UUID;
  ​
  /**
   * @ClassName UserServiceImpl
   * @Description TODO
   * @Author Jiangnan Cui
   * @Date 2022/4/9 17:14
   * @Version 1.0
   */
  public class UserServiceImpl implements UserService{
      //Service层需要调用DAO层
      private UserDAO userDAO;
  ​
      public void setUserDAO(UserDAO userDAO) {
          this.userDAO = userDAO;
      }
  ​
      //生成事务管理器
      private PlatformTransactionManager platformTransactionManager;
  ​
      public void setPlatformTransactionManager(PlatformTransactionManager platformTransactionManager) {
          this.platformTransactionManager = platformTransactionManager;
      }
  ​
      //查询所有用户信息
      //注意:查询不需要事务管理
      @Override
      public List<User> findAll() {
          return userDAO.findAll();
      }
  ​
      //插入用户信息
      //注意:增删改需要事务管理
      @Override
      public void insert(User user) {
          //int i = 1/0;
          //创建事务配置对象
          TransactionDefinition transactionDefinition = new DefaultTransactionDefinition();
          //获取事务状态
          TransactionStatus status = platformTransactionManager.getTransaction(transactionDefinition);
          try {
              //处理业务
              user.setId(UUID.randomUUID().toString());
              //调用业务
              //注意:在DAO层进行数据库增删改时,也能操作成功的原因是因为DAO层提供了方法测试的小事务,方便测试DAO
              //     当外部存在事务时,小事务自动消失
              userDAO.insert(user);
              platformTransactionManager.commit(status);
          } catch (Exception e) {
              e.printStackTrace();
              platformTransactionManager.rollback(status);
          }
  ​
      }
  }
  ​

4.4 编写spring.xml

      <!--配置数据源事务管理器-->
      <bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager">
          <!--注入数据源对象 DataSource-->
          <property name="dataSource" ref="dataSource"/>
      </bean>
  ​
      <!--管理Service组件-->
      <bean class="service.UserServiceImpl" id="userService">
          <!--Service组件需要DAO组件,需要注入-->
          <property name="userDAO" ref="userDAO"/>
          <!--需要在Service进行事务管理-->
          <property name="platformTransactionManager" ref="transactionManager"/>
      </bean>

4.5 启动工厂测试

  
  package test;
  ​
  import entity.User;
  import org.springframework.context.ApplicationContext;
  import org.springframework.context.support.ClassPathXmlApplicationContext;
  import service.UserService;
  ​
  import java.util.Date;
  ​
  /**
   * @ClassName UserServiceTest
   * @Description TODO
   * @Author Jiangnan Cui
   * @Date 2022/4/9 17:41
   * @Version 1.0
   */
  public class UserServiceTest {
      public static void main(String[] args) {
          ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
          UserService userService = (UserService) context.getBean("userService");
          //System.out.println(userService.getClass());
          userService.insert(new User(null,"小超超",36,new Date()));
          userService.findAll().forEach(user -> System.out.println("user = " + user));
      }
  }
  ​

4.6 小结

配套视频:【编程不良人】快速入门Spring,SpringBoot、SpringCloud学不好完全是因为Spring没有掌握!_哔哩哔哩_bilibili

5. SM整合Service层事务优化思路分析

配套视频:【编程不良人】快速入门Spring,SpringBoot、SpringCloud学不好完全是因为Spring没有掌握!_哔哩哔哩_bilibili

spring中的两种事务管理方式:

 spring中声明式事务分析思路:

 具体实现如下:

5.1 在spring-mybatis.xml文件中添加配置

  <!--管理Service组件-->
      <bean class="service.UserServiceImpl" id="userService">
          <!--Service组件需要DAO组件,需要注入-->
          <property name="userDAO" ref="userDAO"/>
          <!--Service组件原有的事务管理移出-->
      </bean>
  ​
  <!--创建数据源事务管理器-->
  <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
      <!--注入数据源对象 DataSource-->
      <property name="dataSource" ref="dataSource"/>
  </bean>
  ​
  <!--配置事务属性
          tx:advice标签
          id: 基于事务管理器创建的环绕通知对象在工厂中唯一标识
              作用:
                  1.根据指定的事务管理器在工厂中创建一个事务的环绕通知对象
                  2.对业务层方法进行细粒度事务控制
          transactionManager:指定事务管理器是谁
  -->
  <tx:advice id="txAdvice" transaction-manager="transactionManager">
      <!--事务细粒度配置-->
      <tx:attributes>
          <!--*表示任意,此处针对增删改方法添加事务管理-->
          <tx:method name="insert*"/>
          <tx:method name="delete*"/>
          <tx:method name="update*"/>
      </tx:attributes>
  </tx:advice>
  ​
  <!--配置事务切面-->
  <aop:config>
      <!--指定切点-->
      <aop:pointcut id="pc" expression="within(service.*ServiceImpl)"/>
      <!--绑定切面-->
      <aop:advisor advice-ref="txAdvice" pointcut-ref="pc"/>
  </aop:config>

5.2 配置图示

5.3 优化UserServiceImpl实现类

  package service;
  ​
  import dao.UserDAO;
  import entity.User;
  import org.springframework.transaction.PlatformTransactionManager;
  import org.springframework.transaction.TransactionDefinition;
  import org.springframework.transaction.TransactionStatus;
  import org.springframework.transaction.support.DefaultTransactionDefinition;
  ​
  import java.util.List;
  import java.util.UUID;
  ​
  /**
   * @ClassName UserServiceImpl
   * @Description TODO
   * @Author Jiangnan Cui
   * @Date 2022/4/9 17:14
   * @Version 1.0
   */
  public class UserServiceImpl implements UserService{
      //Service层需要调用DAO层
      private UserDAO userDAO;
  ​
      public void setUserDAO(UserDAO userDAO) {
          this.userDAO = userDAO;
      }
  ​
      /**
       * @MethodName findAll
       * @Description 查询所有用户信息,查询不需要事务管理
       * @return: java.util.List<entity.User>
       * @Author Jiangnan Cui
       * @Date 2022/4/11 21:31
       */
      @Override
      public List<User> findAll() {
          return userDAO.findAll();
      }
  ​
  ​
      /**
       * @MethodName insert
       * @Description 插入用户信息,需要事务管理
       * @param: user
       * @Author Jiangnan Cui
       * @Date 2022/4/11 21:29
       */
      @Override
      public void insert(User user) {
          //处理业务
          user.setId(UUID.randomUUID().toString());
          //调用业务
          //注意:在DAO层进行数据库增删改时,也能操作成功的原因是因为DAO层提供了方法测试的小事务,方便测试DAO
          //     当外部存在事务时,小事务自动消失
          userDAO.insert(user);
          //int i = 1/0;//测试异常
      }
  }
  ​

5.4 启动测试

  
  package test;
  ​
  import entity.User;
  import org.springframework.context.ApplicationContext;
  import org.springframework.context.support.ClassPathXmlApplicationContext;
  import service.UserService;
  ​
  import java.util.Date;
  ​
  /**
   * @ClassName UserServiceTest
   * @Description TODO
   * @Author Jiangnan Cui
   * @Date 2022/4/9 17:41
   * @Version 1.0
   */
  public class UserServiceTest {
      public static void main(String[] args) {
          ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
          UserService userService = (UserService) context.getBean("userService");
          //System.out.println(userService.getClass());
          //insert
          userService.insert(new User(null,"小胖墩",3,new Date()));
          //findAll
          userService.findAll().forEach(user -> System.out.println("user = " + user));
      }
  }
  ​

测试结果:

(1)不注释int i = 1/0;数据插入不成功

  
  Exception in thread "main" java.lang.ArithmeticException: / by zero
      at service.UserServiceImpl.insert(UserServiceImpl.java:63)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      at java.lang.reflect.Method.invoke(Method.java:498)
      at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:333)
      at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
      at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
      at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:280)
      at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
      at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
      at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
      at com.sun.proxy.$Proxy9.insert(Unknown Source)
      at test.UserServiceTest.main(UserServiceTest.java:23)

(2)注释掉int i = 1/0;数据插入成功

  
  user = User{id='1', name='张三', age=10, bir=Fri Apr 01 00:00:00 CST 2022}
  user = User{id='2', name='李四', age=20, bir=Sat Apr 02 00:00:00 CST 2022}
  user = User{id='2f278828-6422-432d-ab1b-a727b33c23bc', name='小胖墩', age=3, bir=Mon Apr 11 21:43:57 CST 2022}
  user = User{id='3', name='王五', age=30, bir=Sun Apr 03 00:00:00 CST 2022}
  user = User{id='4', name='灰太狼', age=60, bir=Sun Apr 10 09:56:17 CST 2022}
  user = User{id='5', name='小超超', age=36, bir=Sun Apr 10 09:55:41 CST 2022}
  user = User{id='6', name='小呆呆', age=60, bir=Sun Apr 10 09:55:43 CST 2022}
  user = User{id='7', name='小超超', age=36, bir=Sun Apr 10 09:55:44 CST 2022}
  user = User{id='8', name='胖嘟嘟', age=50, bir=Sun Apr 10 09:55:39 CST 2022}
  user = User{id='9', name='小崔', age=25, bir=Sun Apr 10 09:55:52 CST 2022}
  user = User{id='e3863fd3-173c-46f4-a753-c72f7c92ad56', name='小猫咪', age=3, bir=Mon Apr 11 21:36:31 CST 2022}

5.5 SM最终开发步骤

配套视频:【编程不良人】快速入门Spring,SpringBoot、SpringCloud学不好完全是因为Spring没有掌握!_哔哩哔哩_bilibili

5.6 SM中添加log4j日志

配套视频:【编程不良人】快速入门Spring,SpringBoot、SpringCloud学不好完全是因为Spring没有掌握!_哔哩哔哩_bilibili

​​​​​​​

 pom.xml中添加依赖:

  <!--log4j依赖-->
  <dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.0.2</version>
  </dependency>
  ​
  <dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.7.5</version>
  </dependency>
  </dependencies>

在src-main-resources下新建log4j.properties:

  
  ## 根日志
  ## 日志级别
  log4j.rootLogger=ERROR,stdout
  ## 输出位置
  log4j.appender.stdout=org.apache.log4j.ConsoleAppender
  ## 布局
  log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
  ## 格式
  log4j.appender.stdout.layout.conversionPattern=[%p] %d{yyyy-MM-dd} %m%n
  ​
  ## 子日志
  ## 日志级别
  log4j.logger.dao=DEBUG
  ## 监听spring框架的日志级别
  log4j.logger.org.springframework=ERROR

测试结果:

  
  [DEBUG] 2022-04-12 ==>  Preparing: insert into t_user values(?,?,?,?); 
  [DEBUG] 2022-04-12 ==> Parameters: 8a3e8ab8-5abc-44e1-9aec-31f3978d97f2(String), 小胖墩(String), 3(Integer), 2022-04-12 10:23:32.991(Timestamp)
  [DEBUG] 2022-04-12 <==    Updates: 1
  [DEBUG] 2022-04-12 ==>  Preparing: select id,name,age,bir from t_user 
  [DEBUG] 2022-04-12 ==> Parameters: 
  [DEBUG] 2022-04-12 <==      Total: 14
  user = User{id='1', name='张三', age=10, bir=Fri Apr 01 00:00:00 CST 2022}
  user = User{id='2', name='李四', age=20, bir=Sat Apr 02 00:00:00 CST 2022}
  user = User{id='2f278828-6422-432d-ab1b-a727b33c23bc', name='小胖墩', age=3, bir=Mon Apr 11 21:43:57 CST 2022}
  user = User{id='3', name='王五', age=30, bir=Sun Apr 03 00:00:00 CST 2022}
  user = User{id='4', name='灰太狼', age=60, bir=Sun Apr 10 09:56:17 CST 2022}
  user = User{id='5', name='小超超', age=36, bir=Sun Apr 10 09:55:41 CST 2022}
  user = User{id='586a5f71-836c-4171-a038-4620fe0f9354', name='葫芦娃', age=5, bir=Tue Apr 12 09:45:17 CST 2022}
  user = User{id='6', name='小呆呆', age=60, bir=Sun Apr 10 09:55:43 CST 2022}
  user = User{id='7', name='小超超', age=36, bir=Sun Apr 10 09:55:44 CST 2022}
  user = User{id='8', name='胖嘟嘟', age=50, bir=Sun Apr 10 09:55:39 CST 2022}
  user = User{id='8a3e8ab8-5abc-44e1-9aec-31f3978d97f2', name='小胖墩', age=3, bir=Tue Apr 12 10:23:33 CST 2022}
  user = User{id='9', name='小崔', age=25, bir=Sun Apr 10 09:55:52 CST 2022}
  user = User{id='cd280176-68b2-4ceb-b781-ba2f5e1fbeff', name='小胖墩', age=3, bir=Tue Apr 12 10:21:18 CST 2022}
  user = User{id='e3863fd3-173c-46f4-a753-c72f7c92ad56', name='小猫咪', age=3, bir=Mon Apr 11 21:36:31 CST 2022}
  ​

注:ERROR前还有OFF,一般不用。  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值