Spring Boot ではマルチデータベース構成について簡単に説明します。

必要とする:

Spring Boot で複数のデータベースが発生する可能性がある場合、これをどのように構成すればよいでしょうか?私の中心的な要件は、構成がどのように構成されていても、最初のデータベースのデフォルト構成とコードの記述方法に影響を与えてはならず、トランザクションの通常の実行が保証されることです。

コード:

1. 最初のデータベースを通常どおりに設定しましょう。

プロジェクトを作成する

関連する依存関係を選択します。ここでは、jdbcTemplate を使用してテストします。最初のデータベースは mysql を使用し、2 番目のデータベースは oracle を使用します。

2. データベース構成ファイルを変更する

        私は yml 設定ファイルを使用することを好むため、application.properties の名前を application.yml に変更しました。ここでは、両方のデータベースが一度に完全に構​​成されます。

spring:
    datasource:
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/test
        username: root
        password: mysql

second:
    datasource:
        driver-class-name: oracle.jdbc.driver.OracleDriver
        url: jdbc:oracle:thin:localhost:1521:orcl
        username: system
        password: manager

ここのスプリング: は最初のデータベース構成です。デフォルトでは、誰もがこのように構成します。これ以上言うことはありません。そして 2 番目: は自分で定義した 2 番目のデータベース構成です。インターネットで情報を検索するとき、複数のデータ ソースの多くの構成では url: を jdbc-url: に変更する必要がありますが、このように変更したくありません。最初のデータベースが 2 番目のデータベースの影響を受けないようにする必要があります。 。

3. jdbcTemplate をカプセル化します。

        基本的に、誰もが jdbcTemplate を使用するときはそれをカプセル化しますが、直接使用する人はほとんどいません。また、主にページング クエリ関数を追加するために、ここでもカプセル化します。

package com.example.databasetest.tools;

import java.util.Map;
import java.util.HashMap;
import java.util.List;
import javax.sql.DataSource;
import org.springframework.jdbc.core.JdbcTemplate;

/**
 * 功能:JdbcTemplate封装类<br>
 * 作者:我是小木鱼(Lag)<br>
 */
public class JdbcTemplatePackage extends JdbcTemplate
{
    /** 数据库类型(ORACLE,MYSQL,DB2)*/
    private String databaseType = "MYSQL";

    public JdbcTemplatePackage(){}

    /**
     * 功能:初始化需要注入数据源<br>
     * 备注:非常重要<br>
     */
    public JdbcTemplatePackage(DataSource dataSource){super(dataSource);}

    /**
     * 功能:执行SQL查询语句并将结果以Map对象返回。
     * @param sql 查询语句
     * @return 仅返回符合条件的第一条数据,无则返回空值。
     */
    @Override
    public Map<String,Object> queryForMap(String sql)
    {
        return this.queryForMap(sql,null);
    }

    /**
     * 功能:执行SQL查询语句并将结果以Map对象返回。
     * @param sql 查询语句
     * @param args 查询参数
     * @return 仅返回符合条件的第一条数据,无则返回空值。
     */
    @Override
    public Map<String,Object> queryForMap(String sql, Object[] args)
    {
        List<Map<String,Object>> list = this.queryForList(sql,args);
        if(list.size() > 0)
        {
            return list.get(0);
        }
        else
        {
            return null;
        }
    }

    /**
     * 功能:执行SQL查询语句并将数据总数以int对象返回。
     * @param sql 查询语句
     * @return -1-语句出错,0-未查询到符合条件的数据,>0-已查询到符合条件的数据。
     */
    public int queryForInt(String sql)
    {
        return this.queryForInt(sql,null);
    }

    /**
     * 功能:执行SQL查询语句并将数据总数以int对象返回。
     * @param sql 查询语句
     * @param args 查询参数
     * @return -1-语句出错,0-未查询到符合条件的数据,>0-已查询到符合条件的数据。
     */
    public int queryForInt(String sql, Object[] args)
    {
        int rowCount = -1;

        Map<String,Object> map = this.queryForMap(sql,args);
        if(map != null)
        {
            //遍历取值
            for (Map.Entry<String, Object> stringObjectEntry : map.entrySet())
            {
                rowCount = Integer.parseInt(stringObjectEntry.getValue().toString());
            }
        }

        return rowCount;
    }

    /**
     * 功能:分页执行SQL查询语句
     * @param sql 查询语句
     * @param pageNo 查询页码
     * @param pageSize 每页行数
     * @return Map对象{"rowCount" :总行数 ,"pageCount" :总页数 ,"queryData" :查询数据列表}
     */
    public Map<String,Object> queryForPage(String sql, int pageNo, int pageSize)
    {
        return this.queryForPage(sql,null,pageNo,pageSize);
    }

    /**
     * 功能:分页执行SQL查询语句
     * @param sql 查询语句
     * @param args 查询参数
     * @param pageNo 查询页码
     * @param pageSize 每页行数
     * @return Map对象{"rowCount" :总行数 ,"pageCount" :总页数 ,"queryData" :查询数据列表}
     */
    public Map<String,Object> queryForPage(String sql, Object[] args, int pageNo, int pageSize)
    {
        int rowCount;					//总行数
        int pageCount;					//总页数
        int rowBegin;					//起始行
        int rowEnd;						//截止行
        Map<String,Object> rtnMap = new HashMap<>();

        //数据库类型不允许为空
        if("".equals(this.databaseType)){throw new RuntimeException("数据库类型为空,请用setDatabaseType(...)函数添加数据库类型!");}

        //得到总行数
        rowCount = this.queryForInt("select count(*) from ("+sql+") tempTableForCount",args);

        if(rowCount < 1)   //没有数据直接返回
        {
            rtnMap.put("rowCount",rowCount);
            rtnMap.put("pageCount",0);
            rtnMap.put("queryData",null);
            return rtnMap;
        }

        //得到总页数
        if(rowCount % pageSize == 0)
        {
            pageCount = rowCount / pageSize;
        }
        else
        {
            pageCount = rowCount / pageSize + 1;
        }

        //检验当前页码
        if(pageNo < 1)
        {
            pageNo = 1;
        }
        else if(pageNo > pageCount)
        {
            pageNo = pageCount;
        }

        //计算起始行与截止行
        rowBegin = (pageNo - 1) * pageSize + 1;
        rowEnd = pageNo * pageSize;
        if(rowEnd > rowCount){rowEnd = rowCount;}

        //重新生成SQL语句
        if("ORACLE".equals(databaseType))
        {
            sql = "select * from (select rownum myrownum,a.* from ("+sql+") a where rownum <= "+ rowEnd +") tempTableForPage where myrownum >= "+ rowBegin;		//虚拟顺序号rownum变成真实顺序号rownum
        }
        else if("MYSQL".equals(databaseType) || "MARIADB".equals(databaseType))
        {
            sql = "select * from ("+sql+") tempTableForPage limit "+ (rowBegin - 1) +","+ pageSize +"";
        }
        else if("DB2".equals(databaseType))
        {
            sql = "select * from (select rownumber() over() as myrownum,a.* from ("+sql+") a) tempTableForPage where myrownum between "+ rowBegin +" and "+ rowEnd;
        }
        else
        {
            throw new RuntimeException("这取得的数据库类型["+this.databaseType+"]我也找不到啊!");
        }

        rtnMap.put("rowCount",rowCount);
        rtnMap.put("pageCount",pageCount);
        rtnMap.put("queryData",this.queryForList(sql,args));

        return rtnMap;
    }

    /**
     * 功能:设置数据库类型<br>
     * @param databaseType(ORACLE,MYSQL,DB2)
     */
    public void setDatabaseType(String databaseType)
    {
        this.databaseType = databaseType;
    }

}

JdbcTemplatePackage クラスを解析します。

1) パラメーターのないコンストラクターと、DataSource パラメーターを含むコンストラクター、および super(dataSource) が必要です。これを忘れずに記述してください。これについては、あまり言う必要はありません。誰もが知っています。

2) queryForPage(...) を呼び出してページング関数をクエリする場合、各データベースの構文が異なるため、どのデータベースが呼び出されるかを知る必要があります。そこで変数を追加しました

/** データベースの種類 (ORACLE、MYSQL、DB2) */
プライベート文字列データベースタイプ = "MYSQL";

デフォルトでは、参照は mysql データベースです。このパラメータ値は、最初と 2 番目のデータベース Bean をアセンブルするときに指定する必要があります。

3) JdbcTemplatePackage クラスは通常のクラスであり、 は @Component アノテーションが付いた Bean にアセンブルされません

4. 最初のデータベースのBeanを生成します。

package com.example.databasetest.tools;

import org.springframework.stereotype.Component;
import javax.sql.DataSource;

@Component
public class MyJdbcTemplate extends JdbcTemplatePackage
{
    public MyJdbcTemplate(DataSource dataSource)
    {
        super(dataSource);
        super.setDatabaseType("MYSQL");
    }

}

MyJdbcTemplate クラスの解析:

1) このクラスは JdbcTemplatePackage を継承しており、コンストラクターはデフォルトのデータ ソースを追加し、それを mysql データベースに設定します。

2) このクラスは @Component アノテーションを使用して Bean を生成します。ユーザーは通常、このタイプの Bean を呼び出してデータベースを操作できます。

3) 複数のデータベースがある場合は、後で追加するトランザクション マネージャー TransactionManager をこのクラスに追加します。

5. 最初のデータベースの Bean をテストします。

(1) まず、Spring Boot が MyJdbcTemplate Bean を自動的にアセンブルしたかどうかを確認してみましょう。

スタートアップ クラス DatabaseTestApplication を変更します。

package com.example.databasetest;

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

@SpringBootApplication
public class DatabaseTestApplication
{

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

        //看看spring boot给我们都自动装配了哪些bean
        ConfigurableApplicationContext run = SpringApplication.run(DatabaseTestApplication.class, args);
        String[] names = run.getBeanDefinitionNames();
        for(String name: names)
        {
            System.out.println("===Bean:"+name);
        }

        System.out.println("====================我是快乐的分割线===================");


    }

}

このクラスを実行して結果を確認します

ほら、自動的に組み立てられてるよ(笑)!

(2) 最初のデータベースのテーブル t_001 のデータ

(3) テスト Web ページのカテゴリを追加します。

package com.example.databasetest.test;

import java.util.Map;
import java.util.List;
import com.example.databasetest.tools.MyJdbcTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class Test
{
    @Autowired
    MyJdbcTemplate myJT;

    @RequestMapping("/db1")
    public String say()
    {
        //分页查询t_001表数据,第2页,每页显示2条数据,该函数返回Map对象,其中的key包括总行数,总页数与具体的查询数据。
        Map mapQry = this.myJT.queryForPage("select * from t_001", 2, 2);
        List list = (List)mapQry.get("queryData");  //得到Map中的具体查询数据

        return "我是第一数据库的测试方法:" + list.toString();
    }


}

Test クラスを解析します。

1) @RestController このアノテーションは説明がなく、退屈です。

2) @Autowired MyJdbcTemplate myJT; MyJdbcTemplate Bean を使用します。 @Autowired は、そのタイプに基づいて Bean を検索します。 @Resourceとは異なります。

(4) 返された結果を確認します。

 これは非常に成功し、5 つのデータのうち 2 つが返され、ページは実際にページ分割されました。

(5) トランザクションの追加

package com.example.databasetest.test;

import java.util.Map;
import java.util.List;
import com.example.databasetest.tools.MyJdbcTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class Test
{
    @Autowired MyJdbcTemplate myJT;

    @RequestMapping("/db1")
    @Transactional
    public String say()
    {
        //分页查询t_001表数据,第2页,每页显示2条数据,该函数返回Map对象,其中的key包括总行数,总页数与具体的查询数据。
        Map mapQry = this.myJT.queryForPage("select * from t_001", 2, 2);
        List list = (List)mapQry.get("queryData");  //得到Map中的具体查询数据
        System.out.println("我是第一数据库的测试方法:"+list.toString());

        //事务
        this.myJT.update("insert into t_001 (c01,c02,c03) values ('999','国王',100)");
        //故意抛出异常
        int i = 1/0;

        return "我是第一数据库的测试方法:" + list.toString();
    }


}

ここでは、RuntimeException をロールバックするトランザクション アノテーション @Transactional を追加します。結果を確認するために意図的に例外をスローしました。

データは変更されていません。これで最初のデータベース Bean テストが完了しました。​ 

6. 2番目のデータベースのBeanを作成します ここがポイントです。

package com.example.databasetest.tools;

import javax.sql.DataSource;
import javax.annotation.PostConstruct;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class MyJdbcTemplate2 extends JdbcTemplatePackage
{
    @Value("${second.datasource.driver-class-name}")
    private String driverClassName ;

    @Value("${second.datasource.url}")
    private String url ;

    @Value("${second.datasource.username}")
    private String userName ;

    @Value("${second.datasource.password}")
    private String password ;

    @PostConstruct
    public void init()
    {
        System.out.println("=====@PostConstruct===========================");
        HikariConfig config = new HikariConfig();
        config.setDriverClassName(driverClassName);
        config.setJdbcUrl(url);
        config.setUsername(userName);
        config.setPassword(password);
        DataSource ds = new HikariDataSource(config);
        super.setDataSource(ds);
        super.setDatabaseType("ORACLE");
    }

}

MyJdbcTemplate2 クラスを解析します。

1) このクラスは JdbcTemplatePackage から継続しています。

2) @Value アノテーションを使用して、構成ファイル application.yml 内の 2 番目のデータベースのパラメーターを取得します。

3) これらのパラメータを使用して新しいデータ ソース DataSource を生成し、それを親クラスに割り当てる必要があります。しかし、非常に重要な質問があります! @ValueはデフォルトではBean生成後に有効となり、コンストラクタでは取得できない(全く使えないわけではなくパラメータとして使えば良いが、面倒で汎用的ではない)ため、 @PostConstruct アノテーションを使用する。これは Spring コンテナーの開始時に実行されます。したがって、2 番目のデータベース Bean が生成される前に、@PostConstruct アノテーションが付けられた関数が実行され、2 番目のデータベース ソースが生成されて親クラスに割り当てられ、デフォルトのデータ ソースが置き換えられます。

4) @Component アノテーションを使用して、このクラスを Bean として登録します。

Spring Boot を起動して、Bean がロードされるのを確認してみましょう。

ご覧のとおり、@PostConstruct が最初にロードされ、次に 2 つのデータベース MyJdbcTemplate と MyJdbcTemplate2 の Bean が生成されます。

7. 2 番目のデータベースの Bean をテストする

(1) 2 番目のデータテーブルを見てみましょう

(2) テスト Web ページを変更する

package com.example.databasetest.test;

import java.util.Map;
import java.util.List;
import com.example.databasetest.tools.MyJdbcTemplate;
import com.example.databasetest.tools.MyJdbcTemplate2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class Test
{
    @Autowired
    MyJdbcTemplate myJT;

    @Autowired
    MyJdbcTemplate2 myJT2;

    @RequestMapping("/db1")
    @Transactional
    public String say()
    {
        //分页查询t_001表数据,第2页,每页显示2条数据,该函数返回Map对象,其中的key包括总行数,总页数与具体的查询数据。
        Map mapQry = this.myJT.queryForPage("select * from t_001", 2, 2);
        List list = (List)mapQry.get("queryData");  //得到Map中的具体查询数据
        System.out.println("我是第一数据库的测试方法:"+list.toString());

        //事务
        this.myJT.update("insert into t_001 (c01,c02,c03) values ('999','国王',100)");
        //故意抛出异常
        //int i = 1/0;

        return "我是第一数据库的测试方法:" + list.toString();
    }

    @RequestMapping("/db2")
    public String say2()
    {
        //分页查询t_test表数据,第2页,每页显示2条数据,该函数返回Map对象,其中的key包括总行数,总页数与具体的查询数据。
        Map mapQry = this.myJT2.queryForPage("select * from t_test", 2, 2);
        List list = (List)mapQry.get("queryData");  //得到Map中的具体查询数据
        System.out.println("我是第二数据库的测试方法:"+list.toString());

        return "我是第二数据库的测试方法:" + list.toString();
    }
}

Test クラスを解析します。

1) 2 番目のデータベースの @Autowired MyJdbcTemplate2 myJT2; Bean を追加します。

2) 新しい関数say2()を追加

@RequestMapping("/db2")
public String Say2()
{
    //ページングで t_test テーブル データをクエリします。2 ページ目では、各ページに 2 つのデータが表示されます。この関数は Map オブジェクトを返します。そのキーには行の総数、ページの総数、および特定のクエリ データが含まれます。 
    マップ mapQry = this.myJT2.queryForPage("select * from t_test", 2, 2);
    List list = (List)mapQry.get("queryData"); // マップ内の特定のクエリ データを取得します
    System.out.println("私は 2 番目のデータベースのテスト メソッドです:"+list.toString());

    return "私は 2 番目のデータベースのテスト メソッドです:" + list.toString();
}

3) 最初のデータベース Bean テスト関数 Say() の例外をコメント アウトし、しばらくして 2 つのデータベースを一緒にテストしました。

        //トランザクション
        this.myJT.update("t_001 (c01,c02,c03) の値 ('999','King',100) に挿入"); 
        // 意図的に例外をスローする
// int i = 1/0;

テストを開始する

まず最初のデータベースをテストします

http://localhost:8080/db1

例外をコメントしたため、データの挿入は成功しました。

2 番目のデータベース Bean を再度テストします

http://localhost:8080/db2

 

 成功!

8. 最後の 2 つの項目は、データベース Bean を生成するトランザクションです。

注: この場合、システムには 2 つのトランザクション マネージャーがあるため、2 番目のデータベース Bean のトランザクション マネージャーを生成したいのですが、最初のデータベース Bean の @Transactional はどれを使用するかわからないため、@ Primary を使用する必要があります。それを伝えます。

MyJdbcTemplate クラスを変更し、デフォルトのトランザクション マネージャーを追加します。

package com.example.databasetest.tools;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Component;
import org.springframework.transaction.PlatformTransactionManager;

import javax.sql.DataSource;

@Component
public class MyJdbcTemplate extends JdbcTemplatePackage
{
    public MyJdbcTemplate(DataSource dataSource)
    {
        super(dataSource);
        super.setDatabaseType("MYSQL");
    }

    @Bean
    @Primary
    public PlatformTransactionManager oneManager(){
        System.out.println("=====这是第1个数据库事务===");
        return new DataSourceTransactionManager(this.getDataSource());
    }

}

新しいトランザクション マネージャーがこのクラスに追加され、デフォルトとして設定されます。

次に、トランザクション マネージャーをクラス MyJdbcTemplate2 に追加します。

package com.example.databasetest.tools;

import javax.sql.DataSource;
import javax.annotation.PostConstruct;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Component;
import org.springframework.transaction.PlatformTransactionManager;

@Component
public class MyJdbcTemplate2 extends JdbcTemplatePackage
{
    @Value("${second.datasource.driver-class-name}")
    private String driverClassName ;

    @Value("${second.datasource.url}")
    private String url ;

    @Value("${second.datasource.username}")
    private String userName ;

    @Value("${second.datasource.password}")
    private String password ;

    @PostConstruct
    public void init()
    {
        System.out.println("=====@PostConstruct===========================");
        HikariConfig config = new HikariConfig();
        config.setDriverClassName(driverClassName);
        config.setJdbcUrl(url);
        config.setUsername(userName);
        config.setPassword(password);
        DataSource ds = new HikariDataSource(config);
        super.setDataSource(ds);
        super.setDatabaseType("ORACLE");
    }

    @Bean
    public PlatformTransactionManager twoManager(){
        System.out.println("=====这是第2个数据库事务===");
        return new DataSourceTransactionManager(this.getDataSource());
    }
}

これら 2 つのトランザクション マネージャーの Bean が生成されるかどうかを確認してみましょう。

Spring Bootを実行し、

 Bean が正常に生成されたことがわかります。

9. 最後の項目、マルチデータベーストランザクションのテストの開始

(1) 最初のデータベース Bean トランザクションを最初にテストします

テスト Web ページの Say() 関数を次のように変更します。

@RequestMapping("/db1")
@トランザクション
public String Say()
{
    //ページングで t_001 テーブルのデータをクエリします。2 ページ目では、各ページに 2 つのデータが表示されます。この関数は Map オブジェクトを返します。そのキーには、行の合計数、ページの合計数、および特定のページ数が含まれます。クエリデータ。 
    マップ mapQry = this.myJT.queryForPage("select * from t_001", 2, 2);
    List list = (List)mapQry.get("queryData"); // マップ内の特定のクエリ データを取得します
    System.out.println("私は最初のデータベース テスト メソッドです:"+list.toString());

    // トランザクション
    //this.myJT.update("t_001 (c01,c02,c03) の値 ('999','King',100) に挿入");
}
    return "私は最初のデータベース テスト メソッドです:" + list.toString();
    int i = 1/0;
    // 意図的に例外をスローする
    this.myJT.update("t_001 (c01,c02,c03) の値 ('000','beggar',0) に挿入");

実行結果:http://localhost:8080/db1

 

データはロールバックされましたが、データは正常に挿入されませんでした。

最初のデータベース Bean トランザクション テストは成功しました。

(2) 2 番目のデータベース Bean トランザクションを再度テストし、トランザクションのアノテーションが変更されていることを確認します。

テスト Web ページの Say2() 関数を次のように変更します。

@RequestMapping("/db2")
@Transactional(transactionManager = "twoManager")
public String Say2()
{
    //ページングで t_test テーブル データをクエリします。2 ページ目では、各ページに 2 つのデータが表示されます。この関数は、行の合計数、ページの合計数、および特定のクエリ データをキーに含む Map オブジェクトを返します。 。 
    マップ mapQry = this.myJT2.queryForPage("select * from t_test", 2, 2);
    List list = (List)mapQry.get("queryData"); // マップ内の特定のクエリ データを取得します
    System.out.println("私は 2 番目のデータベースのテスト メソッドです:"+list.toString());

    // トランザクション
    this.myJT2.update("t_test (id,name,age) 値 ('Z','ZZZ',100) に挿入"); 
    // 意図的に例外をスローする
    int i = 1/0;

    return "私は 2 番目のデータベースのテスト メソッドです:" + list.toString();
}

トランザクション アノテーション @Transactional(transactionManager = "twoManager")

特別に指定された取引管理者

テストを開始します:http://localhost:8080/db2

 

ご覧のとおり、データは挿入されず、ロールバックされました。

これは、2 番目のデータベース Bean のトランザクションも正常にテストされたことを示しています。

テスト Web ページの完全なコードは次のとおりです。

package com.example.databasetest.test;

import java.util.Map;
import java.util.List;
import com.example.databasetest.tools.MyJdbcTemplate;
import com.example.databasetest.tools.MyJdbcTemplate2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class Test
{
    @Autowired
    MyJdbcTemplate myJT;

    @Autowired
    MyJdbcTemplate2 myJT2;

    @RequestMapping("/db1")
    @Transactional
    public String say()
    {
        //分页查询t_001表数据,第2页,每页显示2条数据,该函数返回Map对象,其中的key包括总行数,总页数与具体的查询数据。
        Map mapQry = this.myJT.queryForPage("select * from t_001", 2, 2);
        List list = (List)mapQry.get("queryData");  //得到Map中的具体查询数据
        System.out.println("我是第一数据库的测试方法:"+list.toString());

        //事务
        //this.myJT.update("insert into t_001 (c01,c02,c03) values ('999','国王',100)");
        this.myJT.update("insert into t_001 (c01,c02,c03) values ('000','乞丐',0)");
        //故意抛出异常
        int i = 1/0;

        return "我是第一数据库的测试方法:" + list.toString();
    }

    @RequestMapping("/db2")
    @Transactional(transactionManager = "twoManager")
    public String say2()
    {
        //分页查询t_test表数据,第2页,每页显示2条数据,该函数返回Map对象,其中的key包括总行数,总页数与具体的查询数据。
        Map mapQry = this.myJT2.queryForPage("select * from t_test", 2, 2);
        List list = (List)mapQry.get("queryData");  //得到Map中的具体查询数据
        System.out.println("我是第二数据库的测试方法:"+list.toString());

        //事务
        this.myJT2.update("insert into t_test (id,name,age) values ('Z','ZZZ',100)");
        //故意抛出异常
        int i = 1/0;

        return "我是第二数据库的测试方法:" + list.toString();
    }
}

さて、手動でスローされたsay()とsay2()の例外をマスクして、再度実行します。

実行: http://localhost:8080/db1  与 http://localhost: 8080/db2

 データ挿入が成功しました!

さて、この記事を書くのはとても疲れるし面倒です!ここで立ち止まって、休憩して、休憩してください!

おすすめ

転載: blog.csdn.net/lag_csdn/article/details/124730482