Spring integrates MyBatis and JUnit

Spring integration

Presumably by now we have a simple understanding of Spring. Spring has a container called an IoC container, which stores beans. When doing enterprise-level development, in fact, in addition to managing the Spring class written by yourself, another important part of the work is to use third-party technologies. I have already talked about how to manage third-party beans. Next, IoC and DI are combined to integrate two common technologies to further deepen the understanding of the use of Spring.

Spring integration Mybatis thinking analysis

Environmental preparation

Prepare database tables

Mybatis is to operate the database table, so first create a database and table

create database spring_db character set utf8;
use spring_db;
create table tbl_account(
    id int primary key auto_increment,
    name varchar(35),
    money double
);

Create a project to import the jar package

Add related dependencies to the pom.xml of the project

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.2.10.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.1.16</version>
    </dependency>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.6</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.47</version>
    </dependency>
</dependencies>

Create model classes from tables

public class Account implements Serializable {
    
    

    private Integer id;
    private String name;
    private Double money;
	//setter...getter...toString...方法略    
}

Create Dao interface

public interface AccountDao {
    
    

    @Insert("insert into tbl_account(name,money)values(#{name},#{money})")
    void save(Account account);

    @Delete("delete from tbl_account where id = #{id} ")
    void delete(Integer id);

    @Update("update tbl_account set name = #{name} , money = #{money} where id = #{id} ")
    void update(Account account);

    @Select("select * from tbl_account")
    List<Account> findAll();

    @Select("select * from tbl_account where id = #{id} ")
    Account findById(Integer id);
}

Create Service interface and implementation class

public interface AccountService {
    
    

    void save(Account account);

    void delete(Integer id);

    void update(Account account);

    List<Account> findAll();

    Account findById(Integer id);

}

@Service
public class AccountServiceImpl implements AccountService {
    
    

    @Autowired
    private AccountDao accountDao;

    public void save(Account account) {
    
    
        accountDao.save(account);
    }

    public void update(Account account){
    
    
        accountDao.update(account);
    }

    public void delete(Integer id) {
    
    
        accountDao.delete(id);
    }

    public Account findById(Integer id) {
    
    
        return accountDao.findById(id);
    }

    public List<Account> findAll() {
    
    
        return accountDao.findAll();
    }
}

Add jdbc.properties file

Added under the resources directory to configure the four elements of database connection

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring_db?useSSL=false
jdbc.username=root
jdbc.password=root

useSSL:关闭MySQL的SSL连接

Add Mybatis core configuration file

<?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>
    <!--读取外部properties配置文件-->
    <properties resource="jdbc.properties"></properties>
    <!--别名扫描的包路径-->
    <typeAliases>
        <package name="com.itheima.domain"/>
    </typeAliases>
    <!--数据源-->
    <environments default="mysql">
        <environment id="mysql">
            <transactionManager type="JDBC"></transactionManager>
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"></property>
                <property name="url" value="${jdbc.url}"></property>
                <property name="username" value="${jdbc.username}"></property>
                <property name="password" value="${jdbc.password}"></property>
            </dataSource>
        </environment>
    </environments>
    <!--映射文件扫描包路径-->
    <mappers>
        <package name="com.itheima.dao"></package>
    </mappers>
</configuration>

write application

public class App {
    
    
    public static void main(String[] args) throws IOException {
    
    
        // 1. 创建SqlSessionFactoryBuilder对象
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        // 2. 加载SqlMapConfig.xml配置文件
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml.bak");
        // 3. 创建SqlSessionFactory对象
        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
        // 4. 获取SqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 5. 执行SqlSession对象执行查询,获取结果User
        AccountDao accountDao = sqlSession.getMapper(AccountDao.class);

        Account ac = accountDao.findById(1);
        System.out.println(ac);

        // 6. 释放资源
        sqlSession.close();
    }
}

Integrated thought analysis

We have prepared the basic environment of Mybatis, and then we have to analyze which objects in the above content can be managed by Spring?

  • Mybatis program core object analysis

insert image description here

It can be obtained from the figure that what really needs to be handed over to Spring management isSqlSessionFactory

  • Integrating Mybatis is to hand over the content used by Mybatis to Spring management, and analyze the configuration file

insert image description here

illustrate:

  • The first line reads the external properties configuration file, and Spring provides specific solutions @PropertySource, which need to be handed over to Spring
  • The second line starts with alias package scanning, which serves SqlSessionFactory and needs to be handed over to Spring
  • The third line is mainly used for the connection pool. Before Spring, we have integrated the Druid connection pool. This part also needs to be handed over to Spring.
  • The first three lines are all used to create SqlSession objects, so use Spring to manage SqlSession objects? Recall that SqlSession is created by SqlSessionFactory, so you only need to hand over SqlSessionFactory to Spring management.
  • The fourth line is the Mapper interface and mapping file [if you use annotations, there is no such mapping file], this is used when performing specific operations after obtaining SqlSession, so it is not created at the same time as SqlSessionFactory, and may need to be separated manage.

Spring integrates Mybatis

We have analyzed the integration of Spring and Mybatis earlier, and generally need to do two things,

  • The first thing is: Spring will manage the SqlSessionFactory in MyBatis
  • The second thing is: Spring manages the scanning of the Mapper interface

Specifically how to achieve it, the specific steps are:

Step 1: Import the jar package required for integration into the project

<dependency>
    <!--Spring操作数据库需要该jar包-->
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.2.10.RELEASE</version>
</dependency>
<dependency>
    <!--
		Spring与Mybatis整合的jar包
		这个jar包mybatis在前面,是Mybatis提供的
	-->
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis-spring</artifactId>
    <version>1.3.0</version>
</dependency>

Step 2: Create Spring's main configuration class

//配置类注解
@Configuration
//包扫描,主要扫描的是项目中的AccountServiceImpl类
@ComponentScan("com.itheima")
public class SpringConfig {
    
    
}

Step 3: Create a configuration class for the data source

Complete the creation of the data source in the configuration class

public class JdbcConfig {
    
    
    @Value("${jdbc.driver}")
    private String driver;
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.username}")
    private String userName;
    @Value("${jdbc.password}")
    private String password;

    @Bean
    public DataSource dataSource(){
    
    
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName(driver);
        ds.setUrl(url);
        ds.setUsername(userName);
        ds.setPassword(password);
        return ds;
    }
}

Step 4: Read properties in the main configuration class and import the data source configuration class

@Configuration
@ComponentScan("com.itheima")
@PropertySource("classpath:jdbc.properties")
@Import(JdbcConfig.class)
public class SpringConfig {
    
    
}

Step 5: Create Mybatis configuration class and configure SqlSessionFactory

public class MybatisConfig {
    
    
    //定义bean,SqlSessionFactoryBean,用于产生SqlSessionFactory对象
    @Bean
    public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource){
    
    
        SqlSessionFactoryBean ssfb = new SqlSessionFactoryBean();
        //设置模型类的别名扫描
        ssfb.setTypeAliasesPackage("com.itheima.domain");
        //设置数据源
        ssfb.setDataSource(dataSource);
        return ssfb;
    }
    //定义bean,返回MapperScannerConfigurer对象
    @Bean
    public MapperScannerConfigurer mapperScannerConfigurer(){
    
    
        MapperScannerConfigurer msc = new MapperScannerConfigurer();
        msc.setBasePackage("com.itheima.dao");
        return msc;
    }
}

illustrate:

  • Use SqlSessionFactoryBean to encapsulate the environment information required by SqlSessionFactory

insert image description here

  • SqlSessionFactoryBean is a subclass of FactoryBean we explained earlier. In this class, the creation of SqlSessionFactory is encapsulated to simplify the creation of objects. We only need to set the required content.
  • There is a parameter in the method which is dataSource. The Druid data source has been created in the current Spring container, and the type is exactly the DataSource type. At this time, when initializing the SqlSessionFactoryBean object, it is found that the DataSource object needs to be used, and there is just such an object in the container. The DruidDataSource object is automatically loaded.
  • Use MapperScannerConfigurer to load the Dao interface, create a proxy object and save it in the IOC container

insert image description here

  • This MapperScannerConfigurer object is also a class in the jar package provided by MyBatis for integration, which is used to process the mappers related configuration in the original configuration file and load the Mapper interface class of the data layer
  • MapperScannerConfigurer has a core attribute basePackage, which is used to set the scanned package path

Step 6: Introduce the Mybatis configuration class into the main configuration class

@Configuration
@ComponentScan("com.itheima")
@PropertySource("classpath:jdbc.properties")
@Import({
    
    JdbcConfig.class,MybatisConfig.class})
public class SpringConfig {
    
    
}

Step 7: Write the running class

In the running class, get the Service object from the IOC container, and call the method to get the result

public class App2 {
    
    
    public static void main(String[] args) {
    
    
        ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);

        AccountService accountService = ctx.getBean(AccountService.class);

        Account ac = accountService.findById(1);
        System.out.println(ac);
    }
}

Supporting the integration of Spring and Mybatis has been completed, and the two main classes used are:

  • SqlSessionFactoryBean
  • MapperScannerConfigurer

Spring integrates Junit

There is a big difference between integrating Junit and integrating Druid and MyBatis. Why? Junit is a tool for unit testing. It is not the main body of our program, nor will it participate in the running of the final program. In terms of function, it is different from the previous ones. It is not a function, but an auxiliary tool. That's it.

Integrate Junit steps

On the basis of the above environment, let's integrate Junit.

Step 1: Introduce dependencies

pom.xml

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>5.2.10.RELEASE</version>
</dependency>

Step 2: Write the test class

Create an AccountServiceTest under test\java, the name is arbitrary

//设置类运行器
@RunWith(SpringJUnit4ClassRunner.class)
//设置Spring环境对应的配置类
@ContextConfiguration(classes = {
    
    SpringConfiguration.class}) //加载配置类
//@ContextConfiguration(locations={"classpath:applicationContext.xml"})//加载配置文件
public class AccountServiceTest {
    
    
    //支持自动装配注入bean
    @Autowired
    private AccountService accountService;
    @Test
    public void testFindById(){
    
    
        System.out.println(accountService.findById(1));

    }
    @Test
    public void testFindAll(){
    
    
        System.out.println(accountService.findAll());
    }
}

Notice:

  • Unit test, if the test is an annotation configuration class, use@ContextConfiguration(classes = 配置类.class)
  • Unit tests, if testing configuration files, use@ContextConfiguration(locations={配置文件名,...})
  • After Junit runs, it runs based on the Spring environment, so Spring provides a dedicated class runner, which must be set. This class runner is provided in Spring's test-specific package, and the imported coordinates are this thingSpringJUnit4ClassRunner
  • The above two configurations are in a fixed format. When a bean needs to be tested, use automatic assembly to load the corresponding object. The following work is exactly the same as the previous Junit unit test

Knowledge point 1: @RunWith

name @RunWith
type Test class annotation
Location above the test class definition
effect Set up the JUnit runner
Attributes value (default): The runtime to run

Knowledge point 2: @ContextConfiguration

name @ContextConfiguration
type Test class annotation
Location above the test class definition
effect Set the Spring core configuration loaded by JUnit
Attributes classes: the core configuration class, you can use the array format to load multiple configuration classes
locations: configuration files, you can use the array format to load multiple configuration file names

Guess you like

Origin blog.csdn.net/weixin_45696320/article/details/130211185