SpringBoot-day3

1.SpringBoot 持久化支持(MyBatis)

1.1 XML版本

1.1.1 步驟分析

  1. 新建maven project;
  2. 在pom.xml中引入相關(guān)依賴
    • (1)基本依賴,jdk版本號(hào);
    • (2)mysql驅(qū)動(dòng),mybatis依賴包,mysql分頁P(yáng)ageHelper:
  3. 創(chuàng)建啟動(dòng)類App.java
  4. 在application.properties添加配置文件;
  5. 創(chuàng)建數(shù)據(jù)庫和表
  6. 編寫domain的測(cè)試類User;
  7. 編寫UserMapper;
  8. 編寫mybatis的xml文件
  9. 編寫IUserService接口和接口的實(shí)現(xiàn)類UserServiceImpl
  10. 編寫UserController
  11. 編寫測(cè)試方法,測(cè)試service層
  12. 啟動(dòng)項(xiàng)目,測(cè)試controller層
  13. 配置事務(wù)。注解式事務(wù)
  14. 測(cè)試事務(wù)
  15. 獲取自增的主鍵id
  16. 使用插件PageHelper分頁

1.1.2 實(shí)現(xiàn)

  1. 新建maven project;
  2. 在pom.xml中引入相關(guān)依賴
    • (1)基本依賴,jdk版本號(hào)
    • (2)mysql驅(qū)動(dòng),mybatis依賴包,mysql分頁P(yáng)ageHelper
<!--子模塊中配置導(dǎo)包-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
<!-- mysql 數(shù)據(jù)庫驅(qū)動(dòng). -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <!--
                    spring-boot mybatis依賴:
                    請(qǐng)不要使用1.0.0版本,因?yàn)檫€不支持?jǐn)r截器插件,
                    1.1.1 是博主寫帖子時(shí)候的版本,大家使用最新版本即可
                 -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.1.1</version>
        </dependency>
        <!--
                MyBatis提供了攔截器接口,我們可以實(shí)現(xiàn)自己的攔截器,
                將其作為一個(gè)plugin裝入到SqlSessionFactory中。
                Github上有位開發(fā)者寫了一個(gè)分頁插件,我覺得使用起來還可以,挺方便的。
                Github項(xiàng)目地址: https://github.com/pagehelper/Mybatis-PageHelper
             -->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>4.1.0</version>
        </dependency>
  1. 創(chuàng)建啟動(dòng)類App.java
package cn.wangningbo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@MapperScan("cn.wangningbo.mapper")//注意這個(gè)注解,使用mybatis掃描包的mapper包
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }
}
  1. 在resources下創(chuàng)建配置文件application.yml
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/test
    driver-class-name: com.mysql.jdbc.Driver
    username: root
    password: apy06942
mybatis:
  type-aliases-package: cn.wangningbo.domain,cn.wangningbo.query
  1. 創(chuàng)建數(shù)據(jù)庫和表
  2. 編寫domain的測(cè)試類User;
package cn.wangningbo.domain;

public class User {
    private Long id;
    private String name;
    //提供get方法、set方法、無參構(gòu)造方法和一個(gè)name參數(shù)的構(gòu)造方法、toString方法
}
  1. 編寫UserMapper;
package cn.wangningbo.mapper;

import cn.wangningbo.domain.User;

import java.util.List;

public interface UserMapper {
    void save(User user);

    List<User> loadAll();
}
  1. 編寫mybatis的xml文件

在resources下創(chuàng)建目錄cn/wangningbo/mapper,在此目錄下創(chuàng)建相應(yīng)的映射xml,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="cn.wangningbo.mapper.UserMapper">
    <insert id="save" parameterType="cn.wangningbo.domain.User">
        INSERT into t_user (name) values (#{name})
    </insert>
    <select id="loadAll" resultType="User">
        SELECT * from t_user
    </select>
</mapper>
  1. 編寫IUserService接口和接口的實(shí)現(xiàn)類UserServiceImpl
package cn.wangningbo.service;

import cn.wangningbo.domain.User;

import java.util.List;

public interface IUserService {
    void add(User user);

    List<User> getAll();
}
package cn.wangningbo.service.impl;

import cn.wangningbo.domain.User;
import cn.wangningbo.mapper.UserMapper;
import cn.wangningbo.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserServiceImpl implements IUserService {
    @Autowired
    private UserMapper userMapper;

    public void add(User user) {
        userMapper.save(user);
    }

    public List<User> getAll() {
        return userMapper.loadAll();
    }
}
  1. 編寫UserController
package cn.wangningbo.controller;

import cn.wangningbo.domain.User;
import cn.wangningbo.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private IUserService userService;

    //保存由測(cè)試做就行,這里就不寫頁面了
    //查詢所有
    @GetMapping
    public List<User> getAll() {
        return userService.getAll();
    }
}
  1. 編寫測(cè)試方法,測(cè)試service層
package cn.wangningbo.service;

import cn.wangningbo.App;
import cn.wangningbo.domain.User;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.List;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = App.class)
public class IUserServiceTest {
    @Autowired
    private IUserService userService;

    @Test
    public void add() {
        userService.add(new User("二狗"));
        userService.add(new User("張三"));
    }

    @Test
    public void getAll() {
        List<User> list = userService.getAll();
        for (User user : list) {
            System.out.println(user);
        }
    }
}
  1. 啟動(dòng)項(xiàng)目,測(cè)試controller層
http://localhost:8080/user
  1. 配置事務(wù)。注解式事務(wù)

在service層加入事務(wù)

//類級(jí)別值只讀事務(wù)
@Transactional(propagation = Propagation.SUPPORTS,readOnly = true)

//在類里面寫方法上面打?qū)懯聞?wù),下面這兩種的效果是一樣的
//@Transactional(propagation = Propagation.REQUIRED,readOnly = false)
@Transactional

package cn.wangningbo.service.impl;

import cn.wangningbo.domain.User;
import cn.wangningbo.mapper.UserMapper;
import cn.wangningbo.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

//類級(jí)別值只讀,在類里面寫方法上面打?qū)懯聞?wù)
@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
public class UserServiceImpl implements IUserService {
    @Autowired
    private UserMapper userMapper;

    //@Transactional(propagation = Propagation.REQUIRED,readOnly = false)
    @Transactional
    public void add(User user) {
        userMapper.save(user);
        // int i = 1/0;
    }

    public List<User> getAll() {
        return userMapper.loadAll();
    }
}
  1. 測(cè)試事務(wù)

由于在service那里的add方法弄了一個(gè)int i = 1/0;事務(wù)成功了就不會(huì)添加到數(shù)據(jù)庫,注釋掉那一行 int i = 1/0;就會(huì)添加到數(shù)據(jù)庫。

  1. 獲取自增的主鍵id

只需要在Mapper.xml里面的添加方法配置一下useGeneratedKeys="true" keyProperty="id" keyColumn="id"

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="cn.wangningbo.mapper.UserMapper">
    <insert id="save" parameterType="cn.wangningbo.domain.User"
            useGeneratedKeys="true"
            keyProperty="id"
            keyColumn="id">
        INSERT into t_user (name) values (#{name})
    </insert>
    <select id="loadAll" resultType="User">
        SELECT * from t_user
    </select>
</mapper>

測(cè)試是否獲得主鍵id,執(zhí)行測(cè)試方法輸出查看是否有id

    @Test
    public void add() {
        User user = new User("二狗");
        System.out.println(user.getId());
        userService.add(user);
        System.out.println(user.getId());
    }

輸出結(jié)果:
null
6

  1. 使用插件PageHelper分頁

PageHelper是mybatis一個(gè)插件,可以用它完成分頁

步驟:導(dǎo)入jaar,在配置類里面配置Bean,測(cè)試

導(dǎo)入jar

        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>4.1.0</version>
        </dependency>

配置

package cn.wangningbo.config;

import com.github.pagehelper.PageHelper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Properties;

@Configuration
public class MyConfig {
    @Bean
    public PageHelper pageHelper() {
        System.out.println("MyBatisConfiguration.pageHelper()");
        PageHelper pageHelper = new PageHelper();
        Properties p = new Properties();
        p.setProperty("offsetAsPageNum", "true");
        p.setProperty("rowBoundsWithCount", "true");
        p.setProperty("reasonable", "true");
        pageHelper.setProperties(p);
        return pageHelper;
    }
}

service層進(jìn)行分頁

    public List<User> getAll() {
        PageHelper.startPage(1, 3);
        return userMapper.loadAll();
    }

測(cè)試

@Test
    public void getAll() {
        //此時(shí)list已經(jīng)不是傳統(tǒng)list,相當(dāng)于原來pageList
        Page<User> list = (Page<User>) userService.getAll();
        //class com.github.pagehelper.Page
        System.out.println(list.getClass());

        //還有分頁信息
        System.out.println(list.getTotal());
        System.out.println(list.getPageNum());

        //獲取數(shù)據(jù):本身也是一個(gè)繼承與ArraList的List
        for (User user : userService.getAll()) {
            System.out.println(user);
        }
    }

輸出結(jié)果

class com.github.pagehelper.Page
5
1
User{id=1, name='二狗'}
User{id=2, name='張三'}
User{id=4, name='二狗'}

1.2 注解版

注解版與xml版很相似,我只簡單說幾句不一樣的地方

  1. 注解版使用mybatis的時(shí)候,只需要在Mapper接口那里的方法頭上打注解即可,以前使用xml版本的時(shí)候都是在xml里面寫的查詢,添加等方法!
package cn.wangningbo.mapper;

import cn.wangningbo.domain.User;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Options;
import org.apache.ibatis.annotations.Select;

import java.util.List;

public interface UserMapper {
    @Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")
    @Insert("insert into t_user(name) values (#{name})")
    void save(User user);

    @Select("select * from t_user")
    List<User> loadAll();
}

2. SpringBoot啟動(dòng)分析

2.1 創(chuàng)建SpringApplication對(duì)象

initialize(sources);
private void initialize(Object[] sources) {
    //保存主配置類
    if (sources != null && sources.length > 0) {
        this.sources.addAll(Arrays.asList(sources));
    }
    //判斷當(dāng)前是否一個(gè)web應(yīng)用
    this.webEnvironment = deduceWebEnvironment();
    //從類路徑下找到META-INF/spring.factories配置的所有ApplicationContextInitializer;然后保存起來
    setInitializers((Collection) getSpringFactoriesInstances(
        ApplicationContextInitializer.class));
    //從類路徑下找到ETA-INF/spring.factories配置的所有ApplicationListener
    setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
    //從多個(gè)配置類中找到有main方法的主配置類
    this.mainApplicationClass = deduceMainApplicationClass();
}

2.2 運(yùn)行run方法

public ConfigurableApplicationContext run(String... args) {
   StopWatch stopWatch = new StopWatch();
   stopWatch.start();
   ConfigurableApplicationContext context = null;
   FailureAnalyzers analyzers = null;
   configureHeadlessProperty();
    
   //獲取SpringApplicationRunListeners;從類路徑下META-INF/spring.factories
   SpringApplicationRunListeners listeners = getRunListeners(args);
    //回調(diào)所有的獲取SpringApplicationRunListener.starting()方法
   listeners.starting();
   try {
       //封裝命令行參數(shù)
      ApplicationArguments applicationArguments = new DefaultApplicationArguments(
            args);
      //準(zhǔn)備環(huán)境
      ConfigurableEnvironment environment = prepareEnvironment(listeners,
            applicationArguments);
            //創(chuàng)建環(huán)境完成后回調(diào)SpringApplicationRunListener.environmentPrepared();表示環(huán)境準(zhǔn)備完成
       
      Banner printedBanner = printBanner(environment);
       
       //創(chuàng)建ApplicationContext;決定創(chuàng)建web的ioc還是普通的ioc
      context = createApplicationContext();
       
      analyzers = new FailureAnalyzers(context);
       //準(zhǔn)備上下文環(huán)境;將environment保存到ioc中;而且applyInitializers();
       //applyInitializers():回調(diào)之前保存的所有的ApplicationContextInitializer的initialize方法
       //回調(diào)所有的SpringApplicationRunListener的contextPrepared();
       //
      prepareContext(context, environment, listeners, applicationArguments,
            printedBanner);
       //prepareContext運(yùn)行完成以后回調(diào)所有的SpringApplicationRunListener的contextLoaded();
       
       //刷新容器;ioc容器初始化(如果是web應(yīng)用還會(huì)創(chuàng)建嵌入式的Tomcat);Spring注解版
       //掃描,創(chuàng)建,加載所有組件的地方;(配置類,組件,自動(dòng)配置)
      refreshContext(context);
       //從ioc容器中獲取所有的ApplicationRunner和CommandLineRunner進(jìn)行回調(diào)
       //ApplicationRunner先回調(diào),CommandLineRunner再回調(diào)
      afterRefresh(context, applicationArguments);
       //所有的SpringApplicationRunListener回調(diào)finished方法
      listeners.finished(context, null);
      stopWatch.stop();
      if (this.logStartupInfo) {
         new StartupInfoLogger(this.mainApplicationClass)
               .logStarted(getApplicationLog(), stopWatch);
      }
       //整個(gè)SpringBoot應(yīng)用啟動(dòng)完成以后返回啟動(dòng)的ioc容器;
      return context;
   }
   catch (Throwable ex) {
      handleRunFailure(context, listeners, analyzers, ex);
      throw new IllegalStateException(ex);
   }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容