Creating a project

1
spring init -d=web --build=maven mysite

Declare Dependencies

1
2
cd mysite
vim pom.xml
1
2
3
4
5
<dependency>
    <groupId>org.liquibase</groupId>
    <artifactId>liquibase-core</artifactId>
    <version>3.10.2</version>
</dependency>
1
2
3
4
5
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.1.3</version>
</dependency>
1
2
3
4
5
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.20</version>
</dependency>

MyBatis-Spring-Boot-Starter will:

  • Autodetect an existing DataSource
  • Will create and register an instance of a SqlSessionFactory passing that DataSource as an input using the SqlSessionFactoryBean
  • Will create and register an instance of a SqlSessionTemplate got out of the SqlSessionFactory
  • Auto-scan your mappers, link them to the SqlSessionTemplate and register them to Spring context so they can be injected into your beans

application.properties

1
2
3
4
5
6
7
8
9
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/discovery?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true&allowPublicKeyRetrieval=true
spring.datasource.driver=com.mysql.cj.jdbc.Driver

# https://docs.spring.io/spring-boot/docs/2.1.1.RELEASE/reference/html/howto-database-initialization.html#howto-execute-liquibase-database-migrations-on-startup
spring.liquibase.change-log=classpath:/db/changelog/db.changelog-master.xml
spring.liquibase.enabled=true
spring.liquibase.contexts=dev, faker

dbchangelog

1
vim src/main/resources/db/changelog/db.changelog-master.xml
1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog
        xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
	  http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.8.xsd">
    <include file="db/changelog/db.changelog-1.0.xml" relativeToChangelogFile="false"/>
</databaseChangeLog>
1
vim src/main/resources/db/changelog/db.changelog-1.0.xml
1
2
3
4
5
6
<databaseChangeLog
        xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
         http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
</databaseChangeLog>

Run a spring boot application

Hot Swapping

1
2
3
4
5
6
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <scope>runtime</scope>
        <optional>true</optional>
    </dependency>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <!-- enable forking -->
            <configuration>
                <fork>true</fork>
            </configuration>
        </plugin>
    </plugins>
</build>

Run a created application using the Spring Boot Maven Plugin.

1
vim pom.xml
1
2
3
4
<properties>
  <maven.compiler.target>1.8</maven.compiler.target>
  <maven.compiler.source>1.8</maven.compiler.source>
</properties>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<build>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>3.6.1</version>
      <configuration>
        <source>1.8</source>
        <target>1.8</target>
      </configuration>
    </plugin>
  </plugins>
</build>
1
./mvnw spring-boot:run

Database generate two table:

  • DATABASECHANGELOG
  • DATABASECHANGELOGLOCK

atabasechangelog :用于 Liquibase 操作记录,以行的形式跟踪每个*变更集*****,并由“ id”,“ author”和“ filename”列的组合标识。

databasechangeloglock :来确保一次仅运行一个 Liquibase 实例。

Create table

1
vim src/main/resources/db/changelog/db.changelog-1.0.xml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<databaseChangeLog
        xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
         http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">

    <changeSet author="liquibase-docs" id="create-city">
        <preConditions onFail="MARK_RAN">
            <not>
                <tableExists tableName="city"/>
            </not>
        </preConditions>
        <createTable remarks="城市" tableName="city">
            <column name="id" type="BIGINT" autoIncrement="true">
                <constraints primaryKey="true"/>
            </column>
            <column name="name" remarks="名称" type="VARCHAR(255)"/>
            <column name="state" remarks="州" type="VARCHAR(255)"/>
            <column name="country" remarks="国家" type="VARCHAR(255)"/>
        </createTable>
    </changeSet>

    <changeSet author="liquibase-docs" id="create-hotel">
        <preConditions onFail="MARK_RAN">
            <not>
                <tableExists tableName="hotel"/>
            </not>
        </preConditions>
        <createTable remarks="酒店" tableName="hotel">
            <column name="id" type="BIGINT"/>
            <column name="city" remarks="城市" type="VARCHAR(255)"/>
            <column name="name" remarks="名称" type="VARCHAR(255)"/>
            <column name="address" remarks="地址" type="VARCHAR(255)"/>
            <column name="zip" remarks="邮编" type="VARCHAR(255)"/>
        </createTable>
    </changeSet>

</databaseChangeLog>

Create a domain class

1
mkdir src/main/java/com/example/mysite/domain
1
vim src/main/java/com/example/mysite/City.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package com.example.mysite.domain;

import java.io.Serializable;

public class City implements Serializable {

  private static final long serialVersionUID = 1L;

  private Long id;

  private String name;

  private String state;

  private String country;

  public Long getId() {
    return this.id;
  }

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

  public String getName() {
    return this.name;
  }

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

  public String getState() {
    return this.state;
  }

  public void setState(String state) {
    this.state = state;
  }

  public String getCountry() {
    return this.country;
  }

  public void setCountry(String country) {
    this.country = country;
  }

  @Override
  public String toString() {
    return getId() + "," + getName() + "," + getState() + "," + getCountry();
  }

}
1
vim src/main/java/com/example/mysite/domain/Hotel.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package com.example.mysite.domain;

import java.io.Serializable;

public class Hotel implements Serializable {

  private static final long serialVersionUID = 1L;

  private Long city;

  private String name;

  private String address;

  private String zip;

  public Long getCity() {
    return city;
  }

  public void setCity(Long city) {
    this.city = city;
  }

  public String getName() {
    return name;
  }

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

  public String getAddress() {
    return address;
  }

  public void setAddress(String address) {
    this.address = address;
  }

  public String getZip() {
    return zip;
  }

  public void setZip(String zip) {
    this.zip = zip;
  }

  @Override
  public String toString() {
    return getCity() + "," + getName() + "," + getAddress() + "," + getZip();
  }

}

Create a DAO

1
mkdir src/main/java/com/example/mysite/dao
1
vim src/main/java/com/example/mysite/dao/CityDao.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
package com.example.mysite.dao;

import org.apache.ibatis.session.SqlSession;
import org.springframework.stereotype.Component;

import com.example.mysite.domain.City;

@Component
public class CityDao {

    private final SqlSession sqlSession;

    public CityDao(SqlSession sqlSession) {
        this.sqlSession = sqlSession;
    }

    public City selectCityById(long id) {
      return this.sqlSession.selectOne("selectCityById", id);
    }

}
Create a mapper interface
1
mkdir src/main/java/com/example/mysite/mapper
1
vim src/main/java/com/example/mysite/mapper/HotelMapper.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
package com.example.mysite.mapper;

import org.apache.ibatis.annotations.Mapper;

import com.example.mysite.domain.Hotel;

@Mapper
public interface HotelMapper {
  Hotel selectByCityId(int cityId);
}
Writer mapper file
1
mkdir -p src/main/resources/com/example/mysite/mapper
1
vim src/main/resources/com/example/mysite/mapper/CityMapper.xml
1
2
3
4
5
6
7
8
9
<?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.example.mysite.mapper.CityMapper">
    <select id="selectCityById" resultType="City">
        select id, name, state, country from city where id = #{id}
    </select>
</mapper>
1
vim src/main/resources/com/example/mysite/mapper/HotelMapper.xml
1
2
3
4
5
6
7
8
9
<?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.example.mysite.mapper.HotelMapper">
    <select id="selectByCityId" resultType="Hotel">
        select city, name, address, zip from hotel where city = #{id}
    </select>
</mapper>
Modify a spring boot application class
1
vim src/main/java/com/example/mysite/DemoApplication.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package com.example.mysite;

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

import com.example.mysite.dao.CityDao;
import com.example.mysite.mapper.HotelMapper;

@SpringBootApplication
public class DemoApplication implements CommandLineRunner {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

    private final CityDao cityDao;
    private final HotelMapper hotelMapper;

    public DemoApplication(CityDao cityDao, HotelMapper hotelMapper) {
        this.cityDao = cityDao;
        this.hotelMapper = hotelMapper;
    }

    @Override
    @SuppressWarnings("squid:S106")
    public void run(String... args) {
        System.out.println(this.cityDao.selectCityById(1));
        System.out.println(this.hotelMapper.selectByCityId(1));
    }

}
Mybatis Configuration
1
vim src/main/resources/application.properties
1
2
3
mybatis.config-location=classpath:mybatis-config.xml
logging.level.root=WARN
logging.level.com.example.mysite.mapper=TRACE
1
vim src/main/resources/mybatis-config.xml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <typeAliases>
        <package name="com.example.mysite.domain"/>
    </typeAliases>
    <mappers>
        <mapper resource="com/example/mysite/mapper/CityMapper.xml"/>
        <mapper resource="com/example/mysite/mapper/HotelMapper.xml"/>
    </mappers>
</configuration>