This is the second day of my participation in Gwen Challenge

1. SpringBoot integrates MyBatis

1.1 Preparing a Database

  • Start the database and connect through Navicat

  • Create a new database springboot, specify the database character encoding to UTF-8, and create the table T_person

  • Insert a few entries into the table

1.2 Creating a new project

1.3 Add jar dependencies to POM.xml

<! --MyBatis integrated SpringBoot startup dependency -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.3</version>
        </dependency>
        
        <! MySql driver dependencies -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
Copy the code

1.4 Configure a data source in the SpringBoot core configuration file application.properties

Modify the following based on your own database information

server:
  # configure the Tomcat port number to be embedded
  port: 8888
  servlet:
    Configure the project context root
    context-path: /springboot-web
    
# configure data source
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/springboot? useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GM T%2B8
    username: root
    password: 12345678
Copy the code

1.5 Code Implementation

1.5.1 Use Mybatis reverse engineering to generate interfaces, mapping files, and entity beans
  • Create Mybatis reverse engineering configuration file GeneratorMapper.xml
  • Add reverse engineering dependencies to the POM.xml file
<! Mybatis code generation plugin -->
            <plugin>
                <groupId>org.mybatis.generator</groupId>
                <artifactId>mybatis-generator-maven-plugin</artifactId>
                <version>1.3.6</version>
                <configuration>
                    <! -- Configuration file location -->
                    <configurationFile>GeneratorMapper.xml</configurationFile>
                    <verbose>true</verbose>
                    <overwrite>true</overwrite>
                </configuration>
            </plugin>
Copy the code
  • Modify the GeneratorMapper.xml configuration

      
<! DOCTYPEgeneratorConfiguration
        PUBLIC  "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>

    <! -- specify the location of the JDBC driver package to connect to the database, specify the full path to your local -->
    <classPathEntry location="/ Volumes/developer/workspace/Java - workspace/springboot/springboot - web/mysql connector - Java - 8.0.25. Jar"/>
    <! Select * from MyBatis3; select * from MyBatis3;
    <context id="tables" targetRuntime="MyBatis3">
        <! -- Suppress the generated comment, since the generated comment is in English, can not allow it to generate -->
        <commentGenerator>
            <property name="suppressAllComments" value="true" />
        </commentGenerator>

        <! -- Configure database connection information -->
        <jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
                        connectionURL="jdbc:mysql://localhost:3306/springboot? useUnicode=true&amp;characterEncoding=UTF-8&amp;useJDBCCompliantTimezoneShift=true&amp;useLegacyDatetimeCode=false&amp;serverTimezone=GMT%2B8&amp;nullCatalogMeansCurrent=true"
                        userId="root"
                        password="12345678">
        </jdbcConnection>
        <! -- Generate model class, targetPackage specifies the package name of model class, targetProject specifies which project to put the generated model under -->
        <javaModelGenerator targetPackage="com.mufeng.springbootweb.model"
                            targetProject="src/main/java">
            <property name="enableSubPackages" value="false" />
            <property name="trimStrings" value="false" />
        </javaModelGenerator>

        <! MyBatis mapper. XML file, targetPackage specifies the package name of mapper. XML file, targetProject specifies the generated mapper. XML file under which project -->
        <sqlMapGenerator targetPackage="com.mufeng.springbootweb.mapper"
                         targetProject="src/main/java">
            <property name="enableSubPackages" value="false" />
        </sqlMapGenerator>

        <! -- Generate MyBatis Mapper interface class file,targetPackage specifies the Mapper interface class name, targetProject specifies the generated Mapper interface under which project -->
        <javaClientGenerator type="XMLMAPPER"
                             targetPackage="com.mufeng.springbootweb.mapper" targetProject="src/main/java">
            <property name="enableSubPackages" value="false" />
        </javaClientGenerator>

        <! -- Database table name and corresponding Java model class name -->
        <table tableName="t_person" domainObjectName="Person"
               enableCountByExample="false"
               enableUpdateByExample="false"
               enableDeleteByExample="false"
        enableSelectByExample="false"
        selectByExampleQueryId="false"/>
    </context>

</generatorConfiguration>
Copy the code
  • Run the plug-in and generate the relevant files

1.5.2 Create and code the PersonController under the Controller package
package com.mufeng.springbootweb.controller;

import com.mufeng.springbootweb.model.Person;
import com.mufeng.springbootweb.services.PersonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class PersonController {

    @Autowired
    private PersonService personService;

    @RequestMapping(value = "/springboot/getPersonDetails")
    @ResponseBody
    public Object getPersonDetails(a){
        Person person = personService.findPersonById(1);
        returnperson; }}Copy the code
1.5.3 Create Service interface under Service package and write code
package com.mufeng.springbootweb.services;

import com.mufeng.springbootweb.model.Person;

public interface PersonService {

    /** * Get user details based on user id *@param id
     * @return* /
    Person findPersonById(Integer id);

}
Copy the code
Create and code the Service interface in the service.impl package
package com.mufeng.springbootweb.services.impl;

import com.mufeng.springbootweb.mapper.PersonMapper;
import com.mufeng.springbootweb.model.Person;
import com.mufeng.springbootweb.services.PersonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class PersonServiceImpl implements PersonService {

    @Autowired
    private PersonMapper personMapper;

    @Override
    public Person findPersonById(Integer id) {
        returnpersonMapper.selectByPrimaryKey(id); }}Copy the code
1.5.5 Adding a Mapper annotation to the StudentMapper Interface Generated by Mybatis Reverse engineering

Mybatis automatically scans the mapping file of data persistence layer and the relationship between DAO interface

package com.mufeng.springbootweb.mapper;

import com.mufeng.springbootweb.model.Person;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface PersonMapper {
    int deleteByPrimaryKey(Integer id);

    int insert(Person record);

    int insertSelective(Person record);

    Person selectByPrimaryKey(Integer id);

    int updateByPrimaryKeySelective(Person record);

    int updateByPrimaryKey(Person record);
}
Copy the code

Note: By default, MyBatis XML mapping files are not compiled to target’s class directory, so we need to configure resource in pm.xml

        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>
                        **/*.xml
                    </include>
                </includes>
            </resource>
        </resources>
Copy the code

1.6 Starting Application applications and accessing tests

1.7 Add mapper scan annotations to running main classes

Comment out the @mapper annotation on the PersonMapper interface

package com.mufeng.springbootweb.mapper;

import com.mufeng.springbootweb.model.Person;
import org.apache.ibatis.annotations.Mapper;

//@Mapper
public interface PersonMapper {
    int deleteByPrimaryKey(Integer id);

    int insert(Person record);

    int insertSelective(Person record);

    Person selectByPrimaryKey(Integer id);

    int updateByPrimaryKeySelective(Person record);

    int updateByPrimaryKey(Person record);
}
Copy the code

Run in the main class Application and add @ MapperScan (” com. Mufeng. Springbootweb. Mapper “)

package com.mufeng.springbootweb;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@MapperScan("com.mufeng.springbootweb.mapper")
public class SpringbootWebApplication {

    public static void main(String[] args) { SpringApplication.run(SpringbootWebApplication.class, args); }}Copy the code

Run test results

1.8 Separating interfaces from Mapping Files

  • Modify generatorMapper. XML file Mapper file generation target location, the target points to resources Mapper folder
        <! MyBatis mapper. XML file, targetPackage specifies the package name of mapper. XML file, targetProject specifies the generated mapper. XML file under which project -->
        <sqlMapGenerator targetPackage="mapper"
                         targetProject="src/main/resources">
            <property name="enableSubPackages" value="false" />
        </sqlMapGenerator>
Copy the code
  • Rerun the code generation plug-in

Delete the previously generated mapping file

  • The location of the mapping file needs to be specified in the application.yml configuration file. This configuration needs to be specified only if the interface and mapping file are no longer in the same package
mybatis:
  mapper-locations: classpath:mapper/*.xml
Copy the code

2. SpringBoot transaction support

Using transactions in SpringBoot is very simple, and the underlying layer is still the transaction management provided by Spring itself

  • Use annotations in the entrance class @ EnableTransactionManagement open transaction support
  • Add the @Transactional annotation to the Service method that accesses the database
Add a method to update the user in the PersonController
    @RequestMapping(value = "/springboot/updatePersonById")
    @ResponseBody
    public Object updatePersonById(a){
        int count = 0;
        try{
            Person person = new Person();
            person.setId(1);
            person.setName("MuFeng_update");
            person.setAge(20);
            count = personService.updatePersonById(person);
        }catch (Exception e){
            e.printStackTrace();
            return "fail";
        }
        return count;
    }
Copy the code
Add a method to update the user in the PersonService interface
    /** * Update user information based on user ID *@param person
     * @return* /
    int updatePersonById(Person person);
Copy the code
Implement this by updating the user information method in the PersonServiceImpl interface implementation class and actively making an exception thrown
    @Override
    public int updatePersonById(Person person) {
        int updateCount = personMapper.updateByPrimaryKeySelective(person);
        System.out.println("Update result:" + updateCount);
        // Construct an exception with a divisor of 0 to test whether the transaction works
        int a = 10/0;
        return updateCount;
    }
Copy the code
Run and test if the transaction is not enabled

The exception was thrown but the modification was successful, so what we need to do is roll back all the add, delete, or modify operations when the action is abnormal

Add the @Transactional annotation to the implementation method of the PersonServiceImpl update
    @Override
    @Transactional
    public int updatePersonById(Person person) {
        int updateCount = personMapper.updateByPrimaryKeySelective(person);
        System.out.println("Update result:" + updateCount);
        // Construct an exception with a divisor of 0 to test whether the transaction works
        int a = 10/0;
        return updateCount;
    }
Copy the code
@ EnableTransactionManagement notes on Application class start transaction support
@SpringBootApplication
@MapperScan("com.mufeng.springbootweb.mapper")
@EnableTransactionManagement
public class SpringbootWebApplication {

    public static void main(String[] args) { SpringApplication.run(SpringbootWebApplication.class, args); }}Copy the code

@ EnableTransactionManagement is optional, but must add @ Transactional affairs on business method to take effect

Modify the code for modifying user information of Controller
@RequestMapping(value = "/springboot/updatePersonById")
    @ResponseBody
    public Object updatePersonById(a){
        int count = 0;
        try{
            Person person = new Person();
            person.setId(1);
            person.setName("MuFeng_update");
            person.setAge(25);
            count = personService.updatePersonById(person);
        }catch (Exception e){
            e.printStackTrace();
            return "fail";
        }
        return count;
    }
Copy the code
Run the test

The same exception is thrown, but the age of the database is still 20, which is not changed, indicating that our transaction started successfully