From 901c9d7ef5ad4845aa2684311193df7d1c6482d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BD=97=E7=A5=A5?= <1366971433@qq.com> Date: Fri, 5 Apr 2019 09:42:43 +0800 Subject: [PATCH] =?UTF-8?q?Spring+Mybtais+Phoenix=E6=95=B4=E5=90=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- notes/Spring+Mybtais+Phoenix整合.md | 385 +++++++++++++++++++++++ pictures/spring-boot-mybatis-phoenix.png | Bin 0 -> 12775 bytes pictures/spring-mybatis-phoenix.png | Bin 0 -> 15053 bytes 4 files changed, 386 insertions(+), 1 deletion(-) create mode 100644 notes/Spring+Mybtais+Phoenix整合.md create mode 100644 pictures/spring-boot-mybatis-phoenix.png create mode 100644 pictures/spring-mybatis-phoenix.png diff --git a/README.md b/README.md index 9b9e34b..9dcae7e 100644 --- a/README.md +++ b/README.md @@ -78,13 +78,13 @@ ## 十、HBase 1. [HBase基本环境搭建(Standalone /pseudo-distributed mode)](https://github.com/heibaiying/BigData-Notes/blob/master/notes/installation/Hbase%E5%9F%BA%E6%9C%AC%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA.md) - 2. [HBase系统架构及数据结构](https://github.com/heibaiying/BigData-Notes/blob/master/notes/Hbase%E7%B3%BB%E7%BB%9F%E6%9E%B6%E6%9E%84%E5%8F%8A%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84.md) 3. [HBase常用Shell命令](https://github.com/heibaiying/BigData-Notes/blob/master/notes/Hbase%20Shell.md) 4. HBase Java API 5. HBase 协处理器 6. HBase 备份与恢复 7. [HBase的SQL中间层——Phoenix](https://github.com/heibaiying/BigData-Notes/blob/master/notes/Hbase%E7%9A%84SQL%E5%B1%82%E2%80%94%E2%80%94Phoenix.md) +8. [Spring/Spring Boot 整合 Mybatis + Phoenix]() ## 十一、Kafka ## 十二、Zookeeper ## 十三、Scala diff --git a/notes/Spring+Mybtais+Phoenix整合.md b/notes/Spring+Mybtais+Phoenix整合.md new file mode 100644 index 0000000..aa27ba2 --- /dev/null +++ b/notes/Spring+Mybtais+Phoenix整合.md @@ -0,0 +1,385 @@ +# Spring/Spring Boot 整合 Mybatis + Phoenix + + +## 一、前言 + +使用Spring+Mybatis操作Phoenix和操作其他的关系型数据库(如Mysql,Oracle)在配置上是基本相同的,下面会分别给出Spring/Spring Boot 整合步骤,完整代码见本仓库: + ++ [Spring + Mybatis + Phoenix](https://github.com/heibaiying/BigData-Notes/tree/master/code/Phoenix/spring-mybatis-phoenix) ++ [SpringBoot + Mybatis + Phoenix](https://github.com/heibaiying/BigData-Notes/tree/master/code/Phoenix/spring-boot-mybatis-phoenix) + +## 二、Spring + Mybatis + Phoenix + +### 2.1 项目结构 + +
+ +### 2.2 主要依赖 + +除了Spring相关依赖外,还需要导入`phoenix-core`和对应的Mybatis依赖包 + +```xml + + + org.mybatis + mybatis-spring + 1.3.2 + + + org.mybatis + mybatis + 3.4.6 + + + + org.apache.phoenix + phoenix-core + 4.14.0-cdh5.14.2 + +``` + +### 2.3 数据库配置文件 + +在数据库配置文件 `jdbc.properties` 中配置数据库驱动和zookeeper地址 + +```properties +# 数据库驱动 +phoenix.driverClassName=org.apache.phoenix.jdbc.PhoenixDriver +# zookeeper地址 +phoenix.url=jdbc:phoenix:192.168.0.105:2181 +``` + +### 2.4 配置数据源和会话工厂 + +```xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +``` + +### 2.5 Mybtais参数配置 + +新建mybtais配置文件,按照需求配置额外参数, 更多settings配置项可以参考[官方文档](http://www.mybatis.org/mybatis-3/zh/configuration.html) + +```xml + + + + + + + + + + + + +``` + +### 2.6 查询接口 + +```java +public interface PopulationDao { + + List queryAll(); + + void save(USPopulation USPopulation); + + USPopulation queryByStateAndCity(@Param("state") String state, @Param("city") String city); + + void deleteByStateAndCity(@Param("state") String state, @Param("city") String city); +} +``` + +```xml + + + + + + + + + UPSERT INTO us_population VALUES( #{state}, #{city}, #{population} ) + + + + + + DELETE FROM us_population WHERE state=#{state} AND city = #{city} + + + +``` + +### 2.7 单元测试 + +```java +@RunWith(SpringRunner.class) +@ContextConfiguration({"classpath:springApplication.xml"}) +public class PopulationDaoTest { + + @Autowired + private PopulationDao populationDao; + + @Test + public void queryAll() { + List USPopulationList = populationDao.queryAll(); + if (USPopulationList != null) { + for (USPopulation USPopulation : USPopulationList) { + System.out.println(USPopulation.getCity() + " " + USPopulation.getPopulation()); + } + } + } + + @Test + public void save() { + populationDao.save(new USPopulation("TX", "Dallas", 66666)); + USPopulation usPopulation = populationDao.queryByStateAndCity("TX", "Dallas"); + System.out.println(usPopulation); + } + + @Test + public void update() { + populationDao.save(new USPopulation("TX", "Dallas", 99999)); + USPopulation usPopulation = populationDao.queryByStateAndCity("TX", "Dallas"); + System.out.println(usPopulation); + } + + + @Test + public void delete() { + populationDao.deleteByStateAndCity("TX", "Dallas"); + USPopulation usPopulation = populationDao.queryByStateAndCity("TX", "Dallas"); + System.out.println(usPopulation); + } +} +``` + +## 三、SpringBoot + Mybatis + Phoenix + +### 3.1 项目结构 + +
+ +### 3.2 主要依赖 + +```xml + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + 1.3.2 + + + + org.apache.phoenix + phoenix-core + 4.14.0-cdh5.14.2 + + +``` + +spring boot 与 mybatis 版本的对应关系: + +| MyBatis-Spring-Boot-Starter 版本 | MyBatis-Spring 版本 | Spring Boot 版本 | +| -------------------------------- | ------------------- | ---------------- | +| **1.3.x (1.3.1)** | 1.3 or higher | 1.5 or higher | +| **1.2.x (1.2.1)** | 1.3 or higher | 1.4 or higher | +| **1.1.x (1.1.1)** | 1.3 or higher | 1.3 or higher | +| **1.0.x (1.0.2)** | 1.2 or higher | 1.3 or higher | + +### 3.3 配置数据源 + +在application.yml 中配置数据源,spring boot 2.x 版本默认采用Hikari作为数据库连接池,Hikari是目前java平台性能最好的连接池,性能好于druid。 + +```yaml +spring: + datasource: + #zookeeper地址 + url: jdbc:phoenix:192.168.0.105:2181 + driver-class-name: org.apache.phoenix.jdbc.PhoenixDriver + + # 如果不想配置对数据库连接池做特殊配置的话,以下关于连接池的配置就不是必须的 + # spring-boot 2.X 默认采用高性能的 Hikari 作为连接池 更多配置可以参考 https://github.com/brettwooldridge/HikariCP#configuration-knobs-baby + type: com.zaxxer.hikari.HikariDataSource + hikari: + # 池中维护的最小空闲连接数 + minimum-idle: 10 + # 池中最大连接数,包括闲置和使用中的连接 + maximum-pool-size: 20 + # 此属性控制从池返回的连接的默认自动提交行为。默认为true + auto-commit: true + # 允许最长空闲时间 + idle-timeout: 30000 + # 此属性表示连接池的用户定义名称,主要显示在日志记录和JMX管理控制台中,以标识池和池配置。 默认值:自动生成 + pool-name: custom-hikari + #此属性控制池中连接的最长生命周期,值0表示无限生命周期,默认1800000即30分钟 + max-lifetime: 1800000 + # 数据库连接超时时间,默认30秒,即30000 + connection-timeout: 30000 + # 连接测试sql 这个地方需要根据数据库方言差异而配置 例如 oracle 就应该写成 select 1 from dual + connection-test-query: SELECT 1 + +# mybatis 相关配置 +mybatis: + configuration: + # 是否打印sql语句 调试的时候可以开启 + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl +``` + +### 3.4 新建查询接口 + +上面Spring+Mybatis我们使用了XML的方式来写SQL,为了体现Mybatis支持多种方式,这里使用注解的方式来写SQL。 + +```java +@Mapper +public interface PopulationDao { + + @Select("SELECT * from us_population") + List queryAll(); + + @Insert("UPSERT INTO us_population VALUES( #{state}, #{city}, #{population} )") + void save(USPopulation USPopulation); + + @Select("SELECT * FROM us_population WHERE state=#{state} AND city = #{city}") + USPopulation queryByStateAndCity(String state, String city); + + + @Delete("DELETE FROM us_population WHERE state=#{state} AND city = #{city}") + void deleteByStateAndCity(String state, String city); +} +``` + +### 3.5 单元测试 + +```java +@RunWith(SpringRunner.class) +@SpringBootTest +public class PopulationTest { + + @Autowired + private PopulationDao populationDao; + + @Test + public void queryAll() { + List USPopulationList = populationDao.queryAll(); + if (USPopulationList != null) { + for (USPopulation USPopulation : USPopulationList) { + System.out.println(USPopulation.getCity() + " " + USPopulation.getPopulation()); + } + } + } + + @Test + public void save() { + populationDao.save(new USPopulation("TX", "Dallas", 66666)); + USPopulation usPopulation = populationDao.queryByStateAndCity("TX", "Dallas"); + System.out.println(usPopulation); + } + + @Test + public void update() { + populationDao.save(new USPopulation("TX", "Dallas", 99999)); + USPopulation usPopulation = populationDao.queryByStateAndCity("TX", "Dallas"); + System.out.println(usPopulation); + } + + + @Test + public void delete() { + populationDao.deleteByStateAndCity("TX", "Dallas"); + USPopulation usPopulation = populationDao.queryByStateAndCity("TX", "Dallas"); + System.out.println(usPopulation); + } + +} + +``` + + + +## 附:建表语句 + +上面单元测试涉及到的测试表的建表语句如下: + +```sql +CREATE TABLE IF NOT EXISTS us_population ( + state CHAR(2) NOT NULL, + city VARCHAR NOT NULL, + population BIGINT + CONSTRAINT my_pk PRIMARY KEY (state, city)); + +-- 测试数据 +UPSERT INTO us_population VALUES('NY','New York',8143197); +UPSERT INTO us_population VALUES('CA','Los Angeles',3844829); +UPSERT INTO us_population VALUES('IL','Chicago',2842518); +UPSERT INTO us_population VALUES('TX','Houston',2016582); +UPSERT INTO us_population VALUES('PA','Philadelphia',1463281); +UPSERT INTO us_population VALUES('AZ','Phoenix',1461575); +UPSERT INTO us_population VALUES('TX','San Antonio',1256509); +UPSERT INTO us_population VALUES('CA','San Diego',1255540); +UPSERT INTO us_population VALUES('CA','San Jose',912332); +``` + diff --git a/pictures/spring-boot-mybatis-phoenix.png b/pictures/spring-boot-mybatis-phoenix.png new file mode 100644 index 0000000000000000000000000000000000000000..174451bb9d48a7da44413a91dcfa3138d6b054b4 GIT binary patch literal 12775 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 S`w@TA0K8Oq4X%_k3;jPSe{ebg literal 0 HcmV?d00001 diff --git a/pictures/spring-mybatis-phoenix.png b/pictures/spring-mybatis-phoenix.png new file mode 100644 index 0000000000000000000000000000000000000000..4e19d01aa35343eea210ce728a13ec77230c21a7 GIT binary patch literal 15053 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