複数のデータソースの下でSpringBoot + Mybatis + Druid + PageHelperでページングを構成および実装する方法

序文

この記事では主に、Mybatis、Druid、PageHelperのSpringBoot統合、および複数のデータソースとページングの実現について説明します。その中で、SpringBootは前回の記事で説明したMybatisを統合しているので、ここではあまり説明しません。焦点は、複数のデータソースでDruidとPageHelperを構成して使用する方法にあります。

SpringBoot + Mybatis + Druid + PageHelperの調査ノートと最新のインタビューの質問

ドルイドの紹介と使用

ドルイドを使用する前に、ドルイドについて簡単に理解しましょう。

Druidはデータベース接続プールです。ドルイドは、現時点で最高のデータベース接続プールであると言えます。その優れた機能、パフォーマンス、スケーラビリティにより、開発者に支持されています。

DruidはAlibabaに600を超えるアプリケーションを展開し、1年以上にわたって大規模な本番環境で厳密にテストされています。Druidは、Alibabaによって開発されたMonitoringと呼ばれるデータベース接続プールです。

同時に、Druidはデータベース接続プールであるだけでなく、Druidコアには主に次の3つの部分が含まれています。

  • フィルターチェーンモデルに基づくプラグインシステム。

  • DruidDataSource効率的で管理しやすいデータベース接続プール。

  • SQLParser

ドルイドの主な機能は次のとおりです。

  • これは、効率的で強力かつスケーラブルなデータベース接続プールです。

  • データベースアクセスのパフォーマンスを監視できます。

  • データベースパスワードの暗号化

  • SQL実行ログを取得する

  • JDBCを拡張する

紹介については詳しく説明しません。詳細については、公式ドキュメントをご覧ください。それでは、ドルイドの使い方を紹介しましょう。

1つ目はMavenの依存関係であり、ドルイドjarを追加するだけで済みます。

<dependency>         <groupId>com.alibaba</groupId>         <artifactId>druid</artifactId>         <version>1.1.8</version>  </dependency>

構成に関しては、application.propertiesまたはapplication.ymlに以下を追加するだけで済みます。

注:ここでは2つのデータソースを使用しているため、わずかに異なります。Druid構成の説明は以下で非常に詳細に説明されているため、ここでは説明しません。

# 默认的数据源master.datasource.url=jdbc:mysql://localhost:3306/springBoot?useUnicode=true&characterEncoding=utf8&allowMultiQueries=truemaster.datasource.username=rootmaster.datasource.password=123456master.datasource.driverClassName=com.mysql.jdbc.Driver
# 另一个的数据源cluster.datasource.url=jdbc:mysql://localhost:3306/springBoot_test?useUnicode=true&characterEncoding=utf8cluster.datasource.username=rootcluster.datasource.password=123456cluster.datasource.driverClassName=com.mysql.jdbc.Driver
# 连接池的配置信息# 初始化大小,最小,最大spring.datasource.type=com.alibaba.druid.pool.DruidDataSourcespring.datasource.initialSize=5spring.datasource.minIdle=5spring.datasource.maxActive=20
# 配置获取连接等待超时的时间spring.datasource.maxWait=60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒spring.datasource.timeBetweenEvictionRunsMillis=60000
# 配置一个连接在池中最小生存的时间,单位是毫秒spring.datasource.minEvictableIdleTimeMillis=300000spring.datasource.validationQuery=SELECT 1 FROM DUALspring.datasource.testWhileIdle=truespring.datasource.testOnBorrow=falsespring.datasource.testOnReturn=false# 打开PSCache,并且指定每个连接上PSCache的大小spring.datasource.poolPreparedStatements=truespring.datasource.maxPoolPreparedStatementPerConnectionSize=20
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙spring.datasource.filters=stat,wall,log4j# 通过connectProperties属性来打开mergeSql功能;慢SQL记录spring.datasource.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000

構成ファイルを正常に追加したら、Druid関連のクラスを作成しましょう。

1つ目は、デフォルトのデータソース構成クラスであるMasterDataSourceConfig.javaクラスです。

@Configuration
@MapperScan(basePackages = MasterDataSourceConfig.PACKAGE, sqlSessionFactoryRef = "masterSqlSessionFactory")public class MasterDataSourceConfig {    static final String PACKAGE = "com.pancm.dao.master";    static final String MAPPER_LOCATION = "classpath:mapper/master/*.xml";    
@Value("${master.datasource.url}")    private String url;    
@Value("${master.datasource.username}")    private String username;    
@Value("${master.datasource.password}")    private String password;    
@Value("${master.datasource.driverClassName}")    private String driverClassName;    
@Value("${spring.datasource.initialSize}")    private int initialSize;    
@Value("${spring.datasource.minIdle}")    private int minIdle;    
@Value("${spring.datasource.maxActive}")    private int maxActive;   
@Value("${spring.datasource.maxWait}")    private int maxWait;    
@Value("${spring.datasource.timeBetweenEvictionRunsMillis}")    private int timeBetweenEvictionRunsMillis;    
@Value("${spring.datasource.minEvictableIdleTimeMillis}")    private int minEvictableIdleTimeMillis;    
@Value("${spring.datasource.validationQuery}")    private String validationQuery;    
@Value("${spring.datasource.testWhileIdle}")    private boolean testWhileIdle;    
@Value("${spring.datasource.testOnBorrow}")    private boolean testOnBorrow;    
@Value("${spring.datasource.testOnReturn}")    private boolean testOnReturn;    
@Value("${spring.datasource.poolPreparedStatements}")    private boolean poolPreparedStatements;    
@Value("${spring.datasource.maxPoolPreparedStatementPerConnectionSize}")    private int maxPoolPreparedStatementPerConnectionSize;    
@Value("${spring.datasource.filters}")    private String filters;    
@Value("{spring.datasource.connectionProperties}")    private String connectionProperties;    
@Bean(name = "masterDataSource")    
@Primary    
public DataSource masterDataSource() {        
DruidDataSource dataSource = new DruidDataSource();        
dataSource.setUrl(url);        
dataSource.setUsername(username);       
 dataSource.setPassword(password);        
dataSource.setDriverClassName(driverClassName);        //具体配置        
dataSource.setInitialSize(initialSize);        
dataSource.setMinIdle(minIdle);        
dataSource.setMaxActive(maxActive);        
dataSource.setMaxWait(maxWait);        
dataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);        
dataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);        
dataSource.setValidationQuery(validationQuery);        
dataSource.setTestWhileIdle(testWhileIdle);        
dataSource.setTestOnBorrow(testOnBorrow);        
dataSource.setTestOnReturn(testOnReturn);       
dataSource.setPoolPreparedStatements(poolPreparedStatements);        
dataSource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);        
try {            dataSource.setFilters(filters);       
 } catch (SQLException e) {           
 e.printStackTrace();       
 }        dataSource.setConnectionProperties(connectionProperties);        
return dataSource;    }  

  
@Bean(name = "masterTransactionManager")    
@Primary    public DataSourceTransactionManager masterTransactionManager() {       
 return new DataSourceTransactionManager(masterDataSource());    }    

@Bean(name = "masterSqlSessionFactory")    
@Primary    public SqlSessionFactory masterSqlSessionFactory(@Qualifier("masterDataSource") DataSource masterDataSource)            throws Exception {       
 final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();        sessionFactory.setDataSource(masterDataSource);       
 sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()                
.getResources(MasterDataSourceConfig.MAPPER_LOCATION));        return sessionFactory.getObject();    }}

これらの2つの注釈は次のことを説明しています。

  • @Primary:同じタイプの複数のBeanの候補である場合、このBeanが最初に考慮されることをマークします。複数のデータソースを構成する場合は、プライマリデータソースが必要であることに注意し、@ Primaryを使用してBeanをマークします。

  • @MapperScan:Mapperインターフェースとコンテナー管理をスキャンします。

sqlSessionFactoryRefは、一意のSqlSessionFactoryインスタンスを定義することを意味することに注意してください。

上記の構成が完了したら、Druidを接続プールとして使用できます。ただし、Druidは単なる接続プールではなく、監視アプリケーションとも言えます。Web監視インターフェイスが付属しており、SQL関連の情報を明確に確認できます。

SpringBootでDruidの監視機能を使用するには、StatViewServletクラスとWebStatFilterクラスを記述して、登録サービスとフィルタリングルールを実装するだけです。ここでは、@ Configurationと@Beanを使用して、これら2つを一緒に記述できます。

理解を容易にするために、関連する構成手順もコードに記述されているため、ここでは繰り返しません。

コードは次のように表示されます。

@Configurationpublic class DruidConfiguration {    
@Bean    public ServletRegistrationBean druidStatViewServle() {        

//注册服务        ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(               
 new StatViewServlet(), "/druid/*");      
  
// 白名单(为空表示,所有的都可以访问,多个IP的时候用逗号隔开)        servletRegistrationBean.addInitParameter("allow", "127.0.0.1");        
// IP黑名单 (存在共同时,deny优先于allow)        servletRegistrationBean.addInitParameter("deny", "127.0.0.2");        
// 设置登录的用户名和密码        servletRegistrationBean.addInitParameter("loginUsername", "pancm");        servletRegistrationBean.addInitParameter("loginPassword", "123456");        
// 是否能够重置数据.        servletRegistrationBean.addInitParameter("resetEnable", "false");       
 return servletRegistrationBean;    }    
@Bean    public FilterRegistrationBean druidStatFilter() {        
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(                new WebStatFilter());        
// 添加过滤规则        filterRegistrationBean.addUrlPatterns("/*");        
// 添加不需要忽略的格式信息        filterRegistrationBean.addInitParameter("exclusions",               
 "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");        System.out.println("druid初始化成功!");        return filterRegistrationBean;    }}

書き込み後、プログラムを起動し、ブラウザにhttp://127.0.0.1:8084/druid/index.htmlと入力してから、Webインターフェイスにアクセスするために設定されたユーザー名とパスワードを入力します。

複数のデータソース構成

複数のデータソースを設定する前に、springBootおよびspringBoot_testのmysqlデータベースでそれぞれ次のスクリプトを実行してください。

-- springBoot库的脚本CREATE TABLE `t_user` 
(  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增id',  `name` varchar(10) DEFAULT NULL COMMENT '姓名',  `age` in
t(2) DEFAULT NULL COMMENT '年龄',  PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT 
CHARSET=utf8-- springBoot_test库的脚本CREATE TABLE `t_student` (  `id` int(11) NOT NULL AUTO_INCREMENT,  
`name` varchar(16) DEFAULT NULL,  `age` int(11) DEFAULT NULL,  
PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8

注:怠惰になるために、2つのテーブルの構造は同じになっています!しかし、それはテストには影響しません!

これら2つのデータソースの情報はapplication.propertiesで構成されており、構成は1回投稿されているため、ここでは投稿しません。

ここでは、2番目のデータソースの構成に焦点を当てます。上記のMasterDataSourceConfig.javaと同様に、違いは@Primaryアノテーションと名前が使用されないことです。ここでの2番目のデータソースと同様に、MasterDataSourceConfig.javaはパッケージとマッパーをディレクトリに正確にスキャンすることに注意してください。

その場合、コードは次のようになります。

@Configuration@MapperScan(basePackages 
= ClusterDataSourceConfig.PACKAGE, sqlSessionFactoryRef 
= "clusterSqlSessionFactory")public class ClusterDataSourceConfig { static final String PACKAGE 
= "com.pancm.dao.cluster"; static final String MAPPER_LOCATION = "classpath:mapper/cluster/*.xml"; 
@Value("${cluster.datasource.url}") private String url; 
@Value("${cluster.datasource.username}") private String username; 
@Value("${cluster.datasource.password}") private String password; 
@Value("${cluster.datasource.driverClassName}") private String driverClass; 
// 和MasterDataSourceConfig一样,这里略 @Bean(name 
= "clusterDataSource") public DataSource clusterDataSource() {     DruidDataSource dataSource 
= new DruidDataSource();    
 dataSource.setUrl(url);     
dataSource.setUsername(username);     
dataSource.setPassword(password);    
 dataSource.setDriverClassName(driverClass);     /
/ 和MasterDataSourceConfig一样,这里略 ...     
return dataSource; } @Bean(name 
= "clusterTransactionManager") public DataSourceTransactionManager clusterTransactionManager() {   
  return new DataSourceTransactionManager(clusterDataSource()); } @Bean(name 
= "clusterSqlSessionFactory") public SqlSessionFactory clusterSqlSessionFactory(@Qualifier("clusterDataS
ource") DataSource clusterDataSource)         throws Exception {     final SqlSessionFactoryBean 
sessionFactory 
= new SqlSessionFactoryBean();     sessionFactory.setDataSource(clusterDataSource);     sessionFactory.s
etMapperLocations(new PathMatchingResourcePatternResolver().getResources(ClusterDataSourceConfig.
MAPPER_LOCATION));     return sessionFactory.getObject(); }}

構成を正常に書き込んだ後、プログラムを起動してテストします。

springBootおよびspringBoot_testライブラリのインターフェースを使用してデータを追加します。

t_user

POST http://localhost:8084/api/user{"name":"张三","age":25}{"name":"李四","age":25}{"name":"王五","age":25}

t_student

POST http://localhost:8084/api/student{"name":"学生A","age":16}{"name":"学生B","age":17}{"name":"学生C","age":18}

データが正常に追加されたら、さまざまなインターフェイスを呼び出してクエリを実行します。

リクエスト:

GET http:// localhost:8084 / api / user?name =李四

戻り値:

{    "id": 2,    "name": "李四",    "age": 25}

リクエスト:

GET http:// localhost:8084 / api / student?name =学生C

戻り値:

{    "id": 1,    "name": "学生C",    "age": 16}

データから、複数のデータソースが正常に構成されていることがわかります。

PageHelperページネーションの実装

PageHelperはMybatisのページングプラグインで、非常に使いやすいです!ここで強くお勧めします!

PageHelperの使用は非常に簡単で、Mavenにpagehelperの依存関係を追加するだけです。

Mavenの依存関係は次のとおりです。

<dependency>   
<groupId>com.github.pagehelper</groupId>   
<artifactId>pagehelper-spring-boot-starter</artifactId> 
  <version>1.2.3</version></dependency>

注:ここではspringBootバージョンを使用しています!他のバージョンも使用できます。

依存関係を追加した後は、次の構成またはコードを追加するだけで済みます。

1つ目は、application.propertiesまたはapplication.ymlを追加することです。

pagehelper:  helperDialect: mysql  offsetAsPageNum: true  rowBoundsWithCount: true  reasonable: false

2つ目は、mybatis.xml構成を追加することです。

<bean 
id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">    <property name="dataSourc
e" ref="dataSource" />    <!-- 扫描mapping.xml文件 --
>    <property name="mapperLocations" value="classpath:mapper/*.xml"></property>    <!-- 配置分页插件 --
>     <property name="plugins">        <array>          <bean class="com.github.pagehelper.PageHelper">            
<property name="properties">              <value>                helperDialect=mysql                offsetAsPageNum=t
rue                rowBoundsWithCount=true                reasonable=false              </value>            </property>       
   </bean>        </array>      </property>  </bean>

3つ目は、コードを追加し、@ Beanアノテーションを使用してプログラムの起動時に初期化することです。


@Bean  public PageHelper pageHelper(){    PageHelper pageHelper = new PageHelper();   Properties 
properties = new Properties();   //数据库   properties.setProperty("helperDialect", "mysql");   //是否将参数
offset作为PageNum使用   properties.setProperty("offsetAsPageNum", "true");   
//是否进行count查
询   properties.setProperty("rowBoundsWithCount", "true");   
//是否分页合理
化   properties.setProperty("reasonable", "false");   pageHelper.setProperties(properties);  }

ここでは複数のデータソースを使用しているため、ここでの構成は少し異なります。ここでsessionFactoryで構成する必要があります。これは、MasterDataSourceConfig.javaに対応する変更です。

masterSqlSessionFactoryメソッドに、次のコードを追加します。

@Bean(name = "masterSqlSessionFactory")    
@Primary    public SqlSessionFactory masterSqlSessionFactory(
@Qualifier("masterDataSource") DataSource masterDataSource)            
throws Exception {        final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();        
sessionFactory.setDataSource(masterDataSource);        
sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()               
 .getResources(MasterDataSourceConfig.MAPPER_LOCATION));        
//分页插件        Interceptor interceptor = new PageInterceptor();        Properties properties = new Properties();        
//数据库        properties.setProperty("helperDialect", "mysql");        
//是否将参数offset作为PageNum使用        properties.setProperty("offsetAsPageNum", "true");        
//是否进行count查询        properties.setProperty("rowBoundsWithCount", "true");        
//是否分页合理化        
properties.setProperty("reasonable", "false");        interceptor.setProperties(properties);        sessionFactory.
setPlugins(new Interceptor[] {interceptor});    return sessionFactory.getObject();  }

注:他のデータソースもページングが必要な場合は、上記のコードを参照してください。

ここで注意する必要があるのは、妥当なパラメーターです。これは、ページングが合理化され、デフォルト値がfalseであることを意味します。このパラメーターがtrueに設定されている場合、最初のページはpageNum <= 0のときに照会され、最後のページはpageNum> pagesのときに照会されます(総数を超えた場合)。デフォルトがfalseの場合、パラメーターに基づいて直接クエリを実行します。

PageHelperを設定した後、それを使用する場合は、クエリsqlの前にPageHelper.startPage(pageNum、pageSize);を追加するだけで済みます。総数を知りたい場合は、それを購入してpage.getTotal()を追加できます。クエリSQLステートメントの後。

コード例:

public List<T> findByListEntity(T entity) {        List<T> list = null;        
try {            Page<?> page =PageHelper.startPage(1,2);            
System.out.println(getClassName(entity)+"设置第一页两条数据!");          
  list = getMapper().findByListEntity(entity);            
System.out.println("总共有:"+page.getTotal()+"条数据,实际返回:"+list.size()+"两条数据!");        } catch (Exception e) {          
  logger.error("查询"+getClassName(entity)+"失败!原因是:",e);        }      
  return list;    }

コードが書かれた後、最終テストが始まります。

t_userテーブル内のすべてのデータをクエリし、ページングを実行します。

リクエスト:

GET http:// localhost:8084 / api / user

戻り値:

[    {        "id": 1,        "name": "张三",        "age": 25    },    
{        "id": 2,        "name": "李四",        "age": 25    }]

コンソール印刷:


开始查询...User设置第一页两条数据!2018-04-27 19:55:50.769 DEBUG 6152 --- [io-8084-exec-
10] c.p.d.m.UserDao.findByListEntity_COUNT :
 ==> Preparing: SELECT count(0) FROM t_user 
WHERE 1 = 12018-04-27 19:55:50.770 DEBUG 6152 --- [io-8084-exec-
10] c.p.d.m.UserDao.findByListEntity_COUNT :
 ==> Parameters:2018-04-27 19:55:50.771 DEBUG 6152 --- 
[io-8084-exec-10] c.p.d.m.UserDao.findByListEntity_COUNT : 
<== Total: 12018-04-
27 19:55:50.772 DEBUG 6152 --- [io-8084-exec-10] c.p.dao.master.UserDao.findByListEntity :
 ==> 
Preparing: select id, name, age from t_user where 1=1 LIMIT ?2018-04-27 19:55:50.773 DEBUG 6152 --- 
[io-8084-exec-10] c.p.dao.master.UserDao.findByListEntity : 
==> Parameters: 2(Integer)2018-04-
27 19:55:50.774 DEBUG 6152 --- [io-8084-exec-10] c.p.dao.master.UserDao.findByListEntity : 
<== Total: 2总共有:3条数据,实际返回:2两条数据!

t_studentテーブルのすべてのデータをクエリし、ページングを実行します。

リクエスト:

GET http:// localhost:8084 / api / student

戻り値:

[    
{        "id": 1,        "name": "学生A",        "age": 16    },  
  {        "id": 2,        "name": "学生B",        "age": 17    }]

コンソール印刷:

开始查询...Studnet设置第一页两条数据!2018-04-27 19:54:56.155 DEBUG 6152 ---
[nio-8084-exec-8] c.p.d.c.S.findByListEntity_COUNT : 
==> Preparing: SELECT count(0) FROM t_student WHERE 1 = 12018-04-27 19:54:56.155 DEBUG 6152 --- [nio-8084-exec-8] c.p.d.c.S.findByListEntity_COUNT : 
==> Parameters:2018-04-27 19:54:56.156 DEBUG 6152 --- [nio-8084-exec-8] c.p.d.c.S.findByListEntity_COUNT :
 <== Total: 12018-04-27 19:54:56.157 DEBUG 6152 --- [nio-8084-exec-8] c.p.d.c.StudentDao.findByListEntity : 
==> Preparing: select id, name, age from t_student where 1=1 LIMIT ?2018-04-27 19:54:56.157 DEBUG 6152 --- [nio-8084-exec-8] c.p.d.c.StudentDao.findByListEntity : 
=
=> Parameters: 2(Integer)2018-04-27 19:54:56.157 DEBUG 6152 --- [nio-8084-exec-8] c.p.d.c.StudentDao.findByListEntity :

 <== Total: 2总共有:3条数据,实际返回:2两条数据!

クエリが完了したら、Druidの監視インターフェイスを見てみましょう。

ブラウザに入力します:http://127.0.0.1:8084 / druid / index.html

画像

運転記録がはっきりとわかります!

ドルイドについてもっと知りたい場合は、公式文書をチェックしてください!

結論

この記事はようやく完成しました。コードを書いているときに、たくさんの問題に遭遇し、それを解決するための情報をゆっくりと見つけました。この記事では、これらの関連する使用法を簡単に紹介するだけであり、実際のアプリケーションはもっと複雑になる可能性があります。より良いアイデアや提案があれば、議論のためにメッセージを残してください!


参考記事:https://www.bysocket.com/?p = 1712

Duridの公式アドレス:https://github.com/alibaba/druid

PageHelperの公式アドレス:https://github.com/pagehelper/Mybatis-PageHelper

おすすめ

転載: blog.csdn.net/fly1north/article/details/115288850