使用Spring Boot + Doma2进行2WaySQL的步骤

背景

最近,由于数据访问使用了S2JDBC(2WaySQL)进行开发,所以对于像Spring Data JPA那样在类文件中以字符串形式”select column1,column2 from table…”的写法感到有些不自然。正好在这个时候有机会了解到了Doma2的存在,于是想试着去尝试一下。
顺便说一下,目前我们的现场环境是使用Spring Boot + MyBatis。

    • パッと見た感じxmlでマッピング書くのがめんどくさそう

 

    • xmlがjavaクラスへの依存を持ってしまっている(resultMapとか)、etc

 

    • javaとSQLを分離したい

 

    そもそもあまり詳しくない

有这个原因,我还是觉得习惯了的2WaySQL比较好。
※如果对其他O/R映射器有更深入的了解可能会改变思考方式。

此外,本次将使用麻生さん介绍的doma-spring-boot-starter自动配置,可在Spring Boot中使用Doma。
https://github.com/domaframework/doma-spring-boot
通过此方式,无需进行任何配置即可在Spring Boot中使用Doma。

Doma是什么意思?

它是一种O/R映射器,简单来说就是O/R Mapper。由于不依赖于Seasar2,因此可以从Spring或其他框架中使用。当然,也可以使用2WaySQL。

Doma有两个主要版本,分别是1和2。
版本1是在Java6上编译的,可以在Java6、Java7和Java8上运行。
※http://doma.seasar.org/index.html
版本2是在Java8上编译的,可以在Java8上运行。
※http://doma.readthedocs.org/ja/stable/

环境

Windows 10 – Windows 十
JDK 8 – JDK 八
Spring Boot 1.3.0 – Spring Boot 一点三点零
STS 3.7.2 – STS 三点七点二
doma 2.5.1 – doma 二点五点一
H2DB 1.4.190 – H2DB 一点四点一九零
Maven 3.3.3 – Maven 三点三点三

我所参考的资料

https://github.com/domaframework/spring-boot-sample 可在此处找到domaframework的spring-boot-sample项目。
http://doma.seasar.org/ 您可以在这里访问doma.seasar.org网站。
http://doma.readthedocs.org/ja/stable/ 你可以在这里访问doma的readthedocs.org网站的日文版本,该版本为稳定版本。

制作的东西

我們將根據書籍《初めてのSpring Boot》創建一個簡單的RestAPI。另外,我們的示例原始碼已經放在以下位置:https://github.com/kenichi-nagaoka/Doma2-SpringBoot

组成

我們會按照以下的結構安排。

│  pom.xml
├─src
│  ├─main
│  │  ├─java
│  │  │  └─com
│  │  │      └─example
│  │  │          │  Application.java
│  │  │          │
│  │  │          ├─controller
│  │  │          │      CustomerController.java
│  │  │          │
│  │  │          ├─model
│  │  │          │      Customer.java
│  │  │          │
│  │  │          ├─repository
│  │  │          │      CustomerRepository.java
│  │  │          │
│  │  │          └─service
│  │  │                  CustomerService.java
│  │  │
│  │  ├─resources
│  │  │  │  application.properties
│  │  │  │  data.sql
│  │  │  │  schema.sql
│  │  │  │
│  │  │  └─META-INF
│  │  │      └─com
│  │  │          └─example
│  │  │              └─repository
│  │  │                  └─CustomerRepository
│  │  │                          selectAll.sql
│  │  │
│  │  └─webapp
│  └─test
│      └─java
│          └─com
│              └─example
│                      ApplicationTests.java
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>doma-cooperation</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <description>Demo project for Spring Boot - Doma</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.3.0.RELEASE</version>
    </parent>

    <repositories>
        <repository>
            <id>sonatype-snapshots</id>
            <name>Sonatype Snapshots</name>
            <url>https://oss.sonatype.org/content/repositories/snapshots</url>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </repository>
    </repositories>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- 冒頭でも述べた通り今回Domaとの連携は以下を利用しました、これを依存関係に追加するだけで推移的依存でDomaも使えます -->
        <dependency>
            <groupId>org.seasar.doma.boot</groupId>
            <artifactId>doma-spring-boot-starter</artifactId>
            <version>1.0.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
    </dependencies>
</project>

数据表定义

当使用Spring Boot时,如果在类路径下(src/main/resources下)存在以下文件,它将在启动时自动执行:
1. 执行schema-(platform).sql文件
2. 执行schema.sql文件
3. 执行data-(platform).sql文件
4. 执行data.sql文件
本次将使用H2数据库进行内存中的数据操作。因此,在启动时将创建表格并插入数据。

CREATE table IF NOT EXISTS customers(id int primary key, name varchar(30));
INSERT INTO customers(id, name) VALUES(1, 'JAY-Z');
INSERT INTO customers(id, name) VALUES(2, 'NAS');
INSERT INTO customers(id, name) VALUES(3, 'DMX');
INSERT INTO customers(id, name) VALUES(4, '2PAC');

Application.java 的汉语释义可以是 “应用程序.java”。

这是一个作为入口点的类。似乎没有什么特别值得注意的地方。

package com.example;

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

@SpringBootApplication
public class Application {

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

顾客控制器.java

这是一个控制器类。它将URL“/customers”和方法“getCustomers”进行了映射。

package com.example.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.example.model.Customer;
import com.example.service.CustomerService;

@RestController
public class CustomerController {

    @Autowired
    CustomerService customerService;

    @RequestMapping(value = "customers", method = RequestMethod.GET)
    public List<Customer> getCustomers() {
        return customerService.getCustomers();
    }
}

客户服务.java

这是与领域层服务相关的内容。只是调用DAO的CustomerRepository的selectAll方法。

package com.example.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.example.model.Customer;
import com.example.repository.CustomerRepository;

@Service
@Transactional
public class CustomerService {

    @Autowired
    CustomerRepository customerRepository;

    public List<Customer> getCustomers() {
        return customerRepository.selectAll();
    }
}

顾客.java

这是一个实体类(查询结果集类)。
必须使用@Entity注解,需要注意的是要使用”org.seasar.doma.Entity”注解。请注意,@Entity有多个,需要注意。另外,如果在内存中使用数据库(如H2或HSQL等),使用@Entity注解并在启动时会自动删除/创建与实体对应的表。因此,在这种情况下,上述的schema.sql文件是不必要的。
@Table注解用于明确指定表名。如果没有这个注解,表名将使用实体类的简单名称,列名将使用属性名称。
更详细的信息如下:
http://doma.seasar.org/reference/entity.html

package com.example.model;

import org.seasar.doma.Entity;
import org.seasar.doma.Id;
import org.seasar.doma.Table;

@Entity
@Table(name = "customers")
public class Customer {

    @Id
    public Integer id;

    public String name;
}

顾客仓库.java

我认为关键点可能是在这里,即DAO。
在Doma中,DAO的实现类通常是通过apt自动生成的。因此,我们要给它加上@Dao注解作为注释。实现类会在编译时自动生成。
接下来的@ConfigAutowireable是使用了前面提到的doma-spring-boot-starter的自动配置。这是为了将自动生成的DAO实现类纳入容器管理所必需的。
详细信息请参见以下链接:
http://doma.seasar.org/reference/dao.html
用这个方法几乎已经完成了。

package com.example.repository;

import java.util.List;

import org.seasar.doma.Dao;
import org.seasar.doma.Select;
import org.seasar.doma.boot.ConfigAutowireable;

import com.example.model.Customer;

@Dao
@ConfigAutowireable
public interface CustomerRepository {

    @Select
    List<Customer> selectAll();
}

创建一个SQL文件

只需创建SQL文件。SQL文件必须放置在已经配置了类路径的 META-INF 目录下。
规则如下:
Meta-INF/Dao 下的类的完全限定名转换为目录名/Dao 的方法名.sql
也就是说,在这个例子中,
META-INF/com/example/repository/CustomerRepository/selectAll.sql

select id, name from customers order by id;

编译

由于这次使用了Maven,因此我们将尝试用以下命令进行编译。
mvn compile
结果如下所示。

[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building doma-cooperation 1.0.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ doma-cooperation ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 1 resource
[INFO] Copying 3 resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ doma-cooperation ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 5 source files to C:\Development\sts-bundle\workspace\doma-cooperation\target\classes
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 22.281 s
[INFO] Finished at: 2015-12-13T21:28:22+09:00
[INFO] Final Memory: 21M/93M

maven-resources-plugin会将SQL文件从src/main/resources/META-INF复制到target/classes中。这是因为如果不先复制,编译时会找不到SQL文件并报错。
接下来,maven-compiler-plugin会使用apt生成DAO实现类,并进行编译。
有关Maven构建的详细信息,请参见以下链接:
http://doma.seasar.org/reference/app_build.html#Maven%E3%81%AB%E3%82%88%E3%82%8B%E3%83%93%E3%83%AB%E3%83%89
请注意,尽管maven-resources-plugin和maven-compiler-plugin没有在这个pom.xml中定义,但可以通过父级的父级pom(奇怪的表达方式)即Spring Boot Dependencies.pom来使用它们。

尝试执行

我会立即执行。我将启动Spring Boot并在浏览器上访问以下网址:
http://localhost:8080/customers
结果如下所示。正如期望的那样。
[{“id”:1,”name”:”JAY-Z”},{“id”:2,”name”:”NAS”},{“id”:3,”name”:”DMX”},{“id”:4,”name”:”2PAC”}]

STS的控制台如下所示(由于没有进行日志设置,所以文字会乱码,但是可以看到正在读取SQL文件)。

2015-12-13 21:57:52.519  INFO 8620 --- [nio-8080-exec-4] o.s.doma.jdbc.UtilLoggingJdbcLogger      : [DOMA2220] ENTER  : 繧ッ繝ゥ繧ケ=[com.example.repository.CustomerRepositoryImpl], 繝。繧ス繝?繝?=[selectAll]
2015-12-13 21:57:52.531  INFO 8620 --- [nio-8080-exec-4] o.s.doma.jdbc.UtilLoggingJdbcLogger      : [DOMA2076] SQL繝ュ繧ー : SQL繝輔ぃ繧、繝ォ=[META-INF/com/example/repository/CustomerRepository/selectAll.sql],
select id, name from customers order by id
2015-12-13 21:57:52.534  INFO 8620 --- [nio-8080-exec-4] o.s.doma.jdbc.UtilLoggingJdbcLogger      : [DOMA2221] EXIT   : 繧ッ繝ゥ繧ケ=[com.example.repository.CustomerRepositoryImpl], 繝。繧ス繝?繝?=[selectAll]

通过这个,我们可以说Spring Boot和Doma2已成功地实现了集成。

摘要/我沉迷过的事情

暫時而言,通過Spring Boot + Doma2的整合,現在可以使用2WaySQL,但在實際應用中似乎需要進一步驗證。例如,這次的例子中只使用了SELECT語句,那麼在INSERT、UPDATE、DELETE等語句中如何處理回滾和異常處理等相關部分就成為了驗證的重點。此外,因為本身對Doma不是很了解,所以理解這部分花了一些時間。不過,無論是Doma1還是Doma2,由於有豐富的日文文檔,所以入門比較容易。這次並沒有進行Eclipse的Annotation Processing設定,因為這樣做會和mvn compile的設定產生衝突,讓人感到困惑。

最后,似乎有Spring Boot + Doma2的实践记录。

下一步,我打算尝试写一些关于INSERT、UPDATE和DELETE的内容。

这就是以上的内容。

广告
将在 10 秒后关闭
bannerAds