Getting Started with Spring Boot - Basics (8) - Database Operations

(1) Import mybatis-spring-boot-starter
pom.xml
    <dependency>
      <groupId>org.mybatis.spring.boot</groupId>
      <artifactId>mybatis-spring-boot-starter</artifactId>
      <version>1.2.0</version>
    </dependency>

    <dependency>
      <groupId>org.postgresql</groupId>
      <artifactId>postgresql</artifactId>
    </dependency>


src/main/resources/schema.sql
CREATE TABLE todo
(
  id serial NOT NULL,
  title character varying(50),
  details text,
  finished integer,
  CONSTRAINT todo_pkey PRIMARY KEY (id)
);


src/main/resources/application.properties
spring.datasource.url=jdbc:postgresql://localhost:5432/test
spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.username=user
spring.datasource.password=123456


src/main/java/com/rensanning/springboot/controller/TodoController.java
@RestController
public class TodoController {
	
	@Autowired
	private TodoService todoService;

	@RequestMapping(value = "/get.json", method = RequestMethod.GET)
	public Todo get(@RequestParam(value = "id") String id) {
		return todoService.select(Integer.parseInt(id));
	}
	
	@RequestMapping(value = "/set.json", method = RequestMethod.POST)
	public Todo set(@RequestParam(value = "title") String title,
			@RequestParam(value = "details") String details) {
		int id = todoService.insert(title, details);
		return todoService.select(id);
	}
	
}


src/main/java/com/rensanning/springboot/domain/Todo.java
public class Todo {
    private int id;
    private String title;
    private String details;
    private int finished;
    // setter/getter	
}


src/main/java/com/rensanning/springboot/service/TodoService.java
@Service
public class TodoService {
	
	@Autowired
	private TodoMapper todoMapper;

	public Todo select(int id) {
		return todoMapper.select(id);
	}

	public int insert(String title, String details) {
		All all = new All();
		todo.setTitle(title);
		todo.setDetails(details);
		all.setFinished(1);
		todoMapper.insert(todo);
		
		return todo.getId();
	}

}


src/main/java/com/rensanning/springboot/mapper/TodoMapper.java
@Mapper
public interface TodoMapper {
    void insert(All all);
    Todo select(int id);
}


Mapper can be automatically scanned without the @Mapper annotation
@MapperScan("com.rensanning.springboot.mapper")
@SpringBootApplication
public class MybatisDemoApplication {
    // ...
}


Mybatipse : An Eclipse plugin for MyBatis. Provides Hyperlinks for Java and XML, autocompletion in XML, error checking, etc.

src/main/java/com/rensanning/springboot/mapper/TodoMapper.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="com.rensanning.springboot.mapper.TodoMapper">
    <insert id="insert" useGeneratedKeys="true" keyProperty="id">
        INSERT INTO todo (title, details, finished) VALUES (#{title}, #{details}, #{finished})
    </insert>
    <select id="select" resultType="com.rensanning.springboot.domain.Todo">
        SELECT id, title, details, finished FROM todo WHERE id = #{id}
    </select>
</mapper>


The startup application is src/main/resources/schema.sql will be automatically executed:
quote
2017-02-10 15:13:24.614  INFO 7520 --- [           main] o.s.jdbc.datasource.init.ScriptUtils     : Executing SQL script from URL [file:/D:/springbootsample/MybatisDemo/target/classes/schema.sql]
2017-02-10 15:13:24.657  INFO 7520 --- [           main] o.s.jdbc.datasource.init.ScriptUtils     : Executed SQL script from URL [file:/D:/springbootsample/MybatisDemo/target/classes/schema.sql] in 43 ms.


Automatic execution can be turned off by setting
src/main/resources/application.properties
quote
spring.datasource.initialize=false


POST一条数据
http://localhost:8080/set.json?details=this+is+details&title=test
quote
{"id":1,"title":"test","details":"this is details","finished":1}


GET a piece of data
http://localhost:8080/get.json?id=1
quote
{"id":1,"title":"test","details":"this is details","finished":1}


(2) Set the log level

src/main/resources/application.properties
quote
spring.datasource.initialize=false
logging.level.com.rensanning.springboot.mapper=TRACE


访问 http://localhost:8080/get.json?id=1
quote
2017-02-10 15:28:57.706 DEBUG 1976 --- [nio-8080-exec-1] c.r.springboot.mapper.TodoMapper.select  : ==>  Preparing: SELECT id, title, details, finished FROM todo WHERE id = ?
2017-02-10 15:28:57.720 DEBUG 1976 --- [nio-8080-exec-1] c.r.springboot.mapper.TodoMapper.select  : ==> Parameters: 1(Integer)
2017-02-10 15:28:57.738 TRACE 1976 --- [nio-8080-exec-1] c.r.springboot.mapper.TodoMapper.select  : <==    Columns: id, title, details, finished
2017-02-10 15:28:57.738 TRACE 1976 --- [nio-8080-exec-1] c.r.springboot.mapper.TodoMapper.select  : <==        Row: 1, test, this is details, 1
2017-02-10 15:28:57.743 DEBUG 1976 --- [nio-8080-exec-1] c.r.springboot.mapper.TodoMapper.select  : <==      Total: 1


Log4jdbc output operation log

MyBatis can configure the output of SQL statements, but outputting statements with question marks is not a complete and runnable SQL. Log4jdbc uses proxy mode to intercept JDBC Driver operations and record real SQL. Log4jdbc-log4j2 adds tabular display of ResultSet.

pom.xml
<dependency>
    <groupId>org.bgee.log4jdbc-log4j2</groupId>
    <artifactId>log4jdbc-log4j2-jdbc4.1</artifactId>
    <version>1.16</version>
</dependency>


src/main/resources/application.properties
   spring.datasource.url             = jdbc:postgresql://localhost:5432/mydb
   spring.datasource.driverClassName = org.postgresql.Driver
->
   spring.datasource.url             = jdbc:log4jdbc:postgresql://localhost:5432/mydb
   spring.datasource.driverClassName = net.sf.log4jdbc.sql.jdbcapi.DriverSpy


src/main/resources/log4jdbc.log4j2.properties
log4jdbc.spylogdelegator.name=net.sf.log4jdbc.log.slf4j.Slf4jSpyLogDelegator


src/main/resources/logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <include resource="org/springframework/boot/logging/logback/base.xml"/>
    <!-- log4jdbc-log4j2 -->
    <logger name="jdbc.sqlonly"        level="DEBUG"/>
    <logger name="jdbc.sqltiming"      level="INFO"/>
    <logger name="jdbc.audit"          level="OFF"/>
    <logger name="jdbc.resultset"      level="ERROR"/>
    <logger name="jdbc.resultsettable" level="DEBUG"/>
    <logger name="jdbc.connection"     level="OFF"/>
</configuration>


访问 http://localhost:8080/get.json?id=1
quote
2017-02-10 15:44:24.206 DEBUG 2560 --- [nio-8080-exec-1] jdbc.sqlonly                             :  org.apache.ibatis.executor.statement.PreparedStatementHandler.query(PreparedStatementHandler.java:63)
10. SELECT id, title, details, finished FROM todo WHERE id = 1

2017-02-10 15:44:24.216  INFO 2560 --- [nio-8080-exec-1] jdbc.sqltiming                           : SELECT id, title, details, finished FROM todo WHERE id = 1
{executed in 10 msec}
2017-02-10 15:44:24.229  INFO 2560 --- [nio-8080-exec-1] jdbc.resultsettable                      :
|---|------|----------------|---------|
|id |title |details         |finished |
|---|------|----------------|---------|
|1  |test  |this is details |1        |
|---|------|----------------|---------|


(3) HikariCP connection pool

adopts Tomcat JDBC Connection Pool by default .

pom.xml
<dependency>
    <groupId>com.zaxxer</groupId>
    <artifactId>HikariCP</artifactId>
</dependency>


src/main/resources/application.properties
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
spring.datasource.hikari.maximum-pool-size=5
spring.datasource.hikari.connection-timeout=5000


quote
2017-02-10 16:05:12.749  INFO 2328 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Located MBean 'dataSource': registering with JMX server as MBean [com.zaxxer.hikari:name=dataSource,type=HikariDataSource]


Two problems when packaging into jar

If the mapper file of mybatis is placed in the same directory as java, the xml file cannot be included in the jar file when the jar package is packaged, and the following plugins need to be used.
            <plugin>
              <groupId>org.codehaus.mojo</groupId>
              <artifactId>build-helper-maven-plugin</artifactId>
              <executions>
                  <execution>
                      <id>add-resource</id>
                      <phase>generate-resources</phase>
                      <goals>
                          <goal>add-resource</goal>
                      </goals>
                      <configuration>
                          <resources>
                              <resource>
                                  <directory>src/main/java</directory>
                                  <includes>
                                      <include>**/*.xml</include>
                                  </includes>
                              </resource>
                          </resources>
                      </configuration>
                  </execution>
              </executions>
            </plugin>


When packaged into a jar, setTypeAliasesPackage("xxx") cannot find the class. MyBatis scans through VFS. In Spring Boot, because it is a nested Jar, Mybatis's default VFS implementation DefaultVFS cannot scan the classes in the nested Jar, and needs to be changed to SpringBootVFS scanning.
    @Bean
    public ConfigurationCustomizer mybatisConfigurationCustomizer() {
        return new ConfigurationCustomizer() {
          @Override
          public void customize(org.apache.ibatis.session.Configuration config) {
            config.setVfsImpl(SpringBootVFS.class);
            config.getTypeAliasRegistry().registerAliases(Constants.BASE_PACKAGE_ALIAS);
          }
        };
    }

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326677076&siteId=291194637