我们在上篇文章中已经学习了 如果使用phoenix的shell命令行工具进行 增删改查,同时明确了 phoenix要查询hbase原生建立的表 需要创建映射表或者 映射视图。
hadoop组件—面向列的开源数据库(七)–phoenix查询hbase–映射和常用命令
本篇 记录 使用 java使用phoenix进行 增删改查。
java 使用Phoenix
加载jar包项目中
加载jar包方式一 使用maven
可以在maven的仓库中查找 自己需要的版本对应的包–搜索关键词 phoenix client
如图,选择合适自己安装版本的包。
在项目的pom.xml文件中加入包依赖,如下:
1
2
3
4
5
6
7
8 1<!-- https://mvnrepository.com/artifact/org.apache.phoenix/phoenix-client -->
2<dependency>
3 <groupId>org.apache.phoenix</groupId>
4 <artifactId>phoenix-client</artifactId>
5 <version>4.14.0-cdh5.13.2</version>
6</dependency>
7
8
注意版本的对应关系,cdh5.13 使用phoenix 4.14以上的版本都支持,所以也可以使用
1
2
3
4
5
6
7 1<dependency>
2 <groupId>org.apache.phoenix</groupId>
3 <artifactId>phoenix-client</artifactId>
4 <version>4.14.1-HBase-1.2</version>
5</dependency>
6
7
可能遇到的问题–Could not transfer artifact org.apache.phoenix:phoenix-client:jar:4.14.0-cdh5.13.2
下载包失败,只能使用手动加载的方式,或者 找到 phoenix-4.14.0-cdh5.13.2-client包,放入maven的repository中,修改名字为 phoenix-client-4.14.0-cdh5.13.2.jar(注意win10系统有没有显示后缀名)
clean一下项目。
加载jar包方式一 手动加载
自行将phoenix-4.x.x-client.jar(可以在下载的安装包中找到该jar包)添加到项目的classpath中
可能遇到的问题–引入phoenix的包后pom.xml报错Missing artifact jdk.tools:jdk.tools:jar:1.8
原因是 使用phoenix的包 需要 用到jdk的tools.jar这个包,但是目前的环境中没有加载到。
需要指定该包在 本机中的路径,例如我的tools.jar包在jdk的安装目录下 路径为 C:\Program Files\Java\jdk1.8.0_112\lib
解决方法 增加如下 依赖
1
2
3
4
5
6
7
8
9
10
11 1
2<dependency>
3 <groupId>jdk.tools</groupId>
4 <artifactId>jdk.tools</artifactId>
5 <version>1.8</version>
6 <scope>system</scope>
7 <systemPath>C:\Program Files\Java\jdk1.8.0_112\lib/tools.jar</systemPath>
8</dependency>
9
10
11
使用java查询phoenix的流程格式
1
2
3
4
5
6
7
8
9
10
11
12 1//加载驱动
2Class.forName("org.apache.phoenix.jdbc.PhoenixDriver");
3//通过DriverManager获取连接
4Connection conn = DriverManager.getConnection("jdbc:phoenix:192.168.1.80,192.168.1.81,192.168.1.82:2181);
5//创建Statement实例
6Statement statement = conn.prepareStatement(sql);
7//执行增、删、改、查等操作
8execute(sql)
9executeUpdate(sql)
10executeQuery(sql)
11
12
创建常用的方法类PhoenixHbaseDB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294 1package com.biologic.util;
2
3
4
5import java.sql.Connection;
6import java.sql.DatabaseMetaData;
7import java.sql.DriverManager;
8import java.sql.PreparedStatement;
9import java.sql.ResultSet;
10import java.sql.ResultSetMetaData;
11import java.sql.SQLException;
12import java.util.ArrayList;
13import java.util.HashMap;
14import java.util.List;
15import java.util.Map;
16
17
18
19public class PhoenixHbaseDB {
20
21
22 private static final String PHOENIX_DRIVER = "org.apache.phoenix.jdbc.PhoenixDriver";
23
24 private static final String PHOENIX_URL = "jdbc:phoenix:192.168.30.217:2181";
25 //private static final String PHOENIX_URL = "jdbc:phoenix:192.168.30.217,192.168.30.218,192.168.30.219:2181";
26
27 public Connection getConnection() {
28 try {
29 // load driver
30 Class.forName(PHOENIX_DRIVER);
31
32 // get connection
33 // jdbc 的 url 类似为 jdbc:phoenix [ :<zookeeper quorum> [ :<port number> ] [ :<root node> ] ],
34 // 需要引用三个参数:hbase.zookeeper.quorum、hbase.zookeeper.property.clientPort、and zookeeper.znode.parent,
35 // 这些参数可以缺省不填而在 hbase-site.xml 中定义。
36 return DriverManager.getConnection(PHOENIX_URL);
37 } catch (Exception e) {
38 e.printStackTrace();
39 return null;
40 }
41 }
42
43
44 /**
45 * 获取Phoenix中的表(系统表除外)
46 */
47 public List<String> getTables() throws Exception {
48 List<String> tables = new ArrayList<>();
49 DatabaseMetaData metaData = getConnection().getMetaData();
50 String[] types = {"TABLE"}; //"SYSTEM TABLE"
51 ResultSet resultSet = metaData.getTables(null, null, null, types);
52 while (resultSet.next()) {
53 tables.add(resultSet.getString("TABLE_NAME"));
54 }
55 return tables;
56 }
57
58 /**
59 * 获取表中的所有数据
60 */
61 public List<Map<String, String>> getList(String tableName) throws Exception {
62 String sql = "SELECT * FROM " + tableName;
63 PreparedStatement preparedStatement = getConnection().prepareStatement(sql);
64 ResultSet resultSet = preparedStatement.executeQuery();
65 ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
66 List<Map<String, String>> resultList = new ArrayList<>();
67 while (resultSet.next()) {
68 Map<String, String> result = new HashMap<>();
69 for (int i = 1, len = resultSetMetaData.getColumnCount(); i <= len; i++) {
70 result.put(resultSetMetaData.getColumnName(i), resultSet.getString(i));
71 }
72 resultList.add(result);
73 }
74 return resultList;
75 }
76
77
78
79 public void create() {
80 Connection conn = null;
81 try {
82 // get connection
83 conn = getConnection();
84
85 // check connection
86 if (conn == null) {
87 System.out.println("conn is null...");
88 return;
89 }
90
91 // check if the table exist
92 ResultSet rs = conn.getMetaData().getTables(null, null, "USER",
93 null);
94 if (rs.next()) {
95 System.out.println("table user is exist...");
96 return;
97 }
98 // create sql
99 String sql = "CREATE TABLE user (id varchar PRIMARY KEY,INFO.account varchar ,INFO.passwd varchar)";
100
101 PreparedStatement ps = conn.prepareStatement(sql);
102
103 // execute
104 ps.execute();
105 System.out.println("create success...");
106
107 } catch (SQLException e) {
108 e.printStackTrace();
109 } finally {
110 if (conn != null) {
111 try {
112 conn.close();
113 } catch (SQLException e) {
114 e.printStackTrace();
115 }
116 }
117 }
118
119 }
120
121
122
123 public void upsert() {
124
125 Connection conn = null;
126 try {
127 // get connection
128 conn = getConnection();
129
130 // check connection
131 if (conn == null) {
132 System.out.println("conn is null...");
133 return;
134 }
135
136 // create sql
137 String sql = "upsert into user(id, INFO.account, INFO.passwd) values('001', 'admin', 'admin')";
138
139 PreparedStatement ps = conn.prepareStatement(sql);
140
141 // execute upsert
142 String msg = ps.executeUpdate() > 0 ? "insert success..."
143 : "insert fail...";
144
145 // you must commit
146 conn.commit();
147 System.out.println(msg);
148
149 } catch (SQLException e) {
150 e.printStackTrace();
151 } finally {
152 if (conn != null) {
153 try {
154 conn.close();
155 } catch (SQLException e) {
156 e.printStackTrace();
157 }
158 }
159 }
160 }
161
162
163 public void query() {
164
165 Connection conn = null;
166 try {
167 // get connection
168 conn = getConnection();
169
170 // check connection
171 if (conn == null) {
172 System.out.println("conn is null...");
173 return;
174 }
175
176 // create sql
177 String sql = "select * from user";
178
179 PreparedStatement ps = conn.prepareStatement(sql);
180
181 ResultSet rs = ps.executeQuery();
182
183 System.out.println("id" + "\t" + "account" + "\t" + "passwd");
184 System.out.println("======================");
185
186 if (rs != null) {
187 while (rs.next()) {
188 System.out.print(rs.getString("id") + "\t");
189 System.out.print(rs.getString("account") + "\t");
190 System.out.println(rs.getString("passwd"));
191 }
192 }
193
194 } catch (SQLException e) {
195 e.printStackTrace();
196 } finally {
197 if (conn != null) {
198 try {
199 conn.close();
200 } catch (SQLException e) {
201 e.printStackTrace();
202 }
203 }
204 }
205
206 }
207
208
209
210
211
212 public void delete() {
213
214 Connection conn = null;
215 try {
216 // get connection
217 conn = getConnection();
218
219 // check connection
220 if (conn == null) {
221 System.out.println("conn is null...");
222 return;
223 }
224
225 // create sql
226 String sql = "delete from user where id='001'";
227
228 PreparedStatement ps = conn.prepareStatement(sql);
229
230 // execute upsert
231 String msg = ps.executeUpdate() > 0 ? "delete success..."
232 : "delete fail...";
233
234 // you must commit
235 conn.commit();
236 System.out.println(msg);
237
238 } catch (SQLException e) {
239 e.printStackTrace();
240 } finally {
241 if (conn != null) {
242 try {
243 conn.close();
244 } catch (SQLException e) {
245 e.printStackTrace();
246 }
247 }
248 }
249
250 }
251
252
253
254
255 public void drop() {
256
257 Connection conn = null;
258 try {
259 // get connection
260 conn = getConnection();
261
262 // check connection
263 if (conn == null) {
264 System.out.println("conn is null...");
265 return;
266 }
267
268 // create sql
269 String sql = "drop table user";
270
271 PreparedStatement ps = conn.prepareStatement(sql);
272
273 // execute
274 ps.execute();
275
276 System.out.println("drop success...");
277
278 } catch (SQLException e) {
279 e.printStackTrace();
280 } finally {
281 if (conn != null) {
282 try {
283 conn.close();
284 } catch (SQLException e) {
285 e.printStackTrace();
286 }
287 }
288 }
289
290 }
291}
292
293
294
创建使用类PhoenixTest
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 1package com.biologic.util;
2
3
4import java.util.List;
5
6import com.biologic.util.PhoenixHbaseDB;
7
8public class PhoenixTest {
9 public static void main(String[] args) throws Exception {
10 PhoenixHbaseDB phoenixHbaseDB = new PhoenixHbaseDB();
11// List<String> tables = phoenixHbaseDB.getTables();
12// for (String tableName : tables) {
13// System.out.println(phoenixHbaseDB.getList(tableName));
14// }
15 phoenixHbaseDB.create();
16 phoenixHbaseDB.upsert();
17 phoenixHbaseDB.query();
18 phoenixHbaseDB.delete();
19 phoenixHbaseDB.drop();
20 }
21}
22
23
24
运行输出如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 12020-01-07 19:14:01 INFO ZooKeeper:100 - Client environment:java.io.tmpdir=C:\Users\38396\AppData\Local\Temp\
22020-01-07 19:14:01 INFO ZooKeeper:100 - Client environment:java.compiler=<NA>
32020-01-07 19:14:01 INFO ZooKeeper:100 - Client environment:os.name=Windows 10
42020-01-07 19:14:01 INFO ZooKeeper:100 - Client environment:os.arch=amd64
52020-01-07 19:14:01 INFO ZooKeeper:100 - Client environment:os.version=10.0
62020-01-07 19:14:01 INFO ZooKeeper:100 - Client environment:user.name=38396
72020-01-07 19:14:01 INFO ZooKeeper:100 - Client environment:user.home=C:\Users\38396
82020-01-07 19:14:01 INFO ZooKeeper:100 - Client environment:user.dir=E:\eclipseworkspace\platform\report-api
92020-01-07 19:14:01 INFO ZooKeeper:438 - Initiating client connection, connectString=host217:2181 sessionTimeout=60000 watcher=hconnection-0x2d7275fc0x0, quorum=host217:2181, baseZNode=/hbase
102020-01-07 19:14:02 INFO ClientCnxn:975 - Opening socket connection to server host217/192.168.30.217:2181. Will not attempt to authenticate using SASL (unknown error)
112020-01-07 19:14:02 INFO ClientCnxn:852 - Socket connection established to host217/192.168.30.217:2181, initiating session
122020-01-07 19:14:02 INFO ClientCnxn:1235 - Session establishment complete on server host217/192.168.30.217:2181, sessionid = 0x16c4c6a7f5ed611, negotiated timeout = 60000
132020-01-07 19:14:02 INFO ConnectionQueryServicesImpl:427 - HConnection established. Stacktrace for informational purposes: hconnection-0x2d7275fc java.lang.Thread.getStackTrace(Unknown Source)
14org.apache.phoenix.util.LogUtil.getCallerStackTrace(LogUtil.java:55)
15org.apache.phoenix.query.ConnectionQueryServicesImpl.openConnection(ConnectionQueryServicesImpl.java:427)
16org.apache.phoenix.query.ConnectionQueryServicesImpl.access$400(ConnectionQueryServicesImpl.java:267)
17org.apache.phoenix.query.ConnectionQueryServicesImpl$12.call(ConnectionQueryServicesImpl.java:2523)
18org.apache.phoenix.query.ConnectionQueryServicesImpl$12.call(ConnectionQueryServicesImpl.java:2499)
19org.apache.phoenix.util.PhoenixContextExecutor.call(PhoenixContextExecutor.java:76)
20org.apache.phoenix.query.ConnectionQueryServicesImpl.init(ConnectionQueryServicesImpl.java:2499)
21org.apache.phoenix.jdbc.PhoenixDriver.getConnectionQueryServices(PhoenixDriver.java:255)
22org.apache.phoenix.jdbc.PhoenixEmbeddedDriver.createConnection(PhoenixEmbeddedDriver.java:150)
23org.apache.phoenix.jdbc.PhoenixDriver.connect(PhoenixDriver.java:221)
24java.sql.DriverManager.getConnection(Unknown Source)
25java.sql.DriverManager.getConnection(Unknown Source)
26com.biologic.util.PhoenixHbaseDB.getConnection(PhoenixHbaseDB.java:36)
27com.biologic.util.PhoenixHbaseDB.create(PhoenixHbaseDB.java:83)
28com.biologic.util.PhoenixTest.main(PhoenixTest.java:15)
29
302020-01-07 19:14:06 INFO HBaseAdmin:790 - Created USER
31create success...
32insert success...
33id account passwd
34======================
35001 admin admin
36delete success...
372020-01-07 19:14:06 INFO HBaseAdmin:1378 - Started disable of USER
382020-01-07 19:14:11 INFO HBaseAdmin:1407 - Disabled USER
392020-01-07 19:14:13 INFO HBaseAdmin:963 - Deleted USER
40drop success...
41
42
43
可能遇到的问题–TableNotFoundException: ERROR 1012 (42M03): Table undefined. tableName=TEST_TABLE
在运行getTables()方法时 只能获取到 通过phoenix创建的 table,如果存在原生的hbase表,而且没做映射时,不存在表的元数据 则会报错。
解决方法
创建 该表的映射 或者 删除该表。
可能遇到的问题–ailed to locate the winutils binary in the hadoop binary path–Could not locate executable null\bin\winutils.exe in the Hadoop binaries
运行程序的机子 需要有hadoop的环境,否则会报错。
解决方案就是安装hadoop并配置环境变量
1.下载winutils的windows版本
GitHub上,有人提供了winutils的windows的版本,项目地址是:https://github.com/srccodes/hadoop-common-2.2.0-bin
直接下载此项目的zip包,下载后是文件名是hadoop-common-2.2.0-bin-master.zip,随便解压到一个目录
例如 C:\hadoop\hadoop-common-2.2.0-bin-master
2.配置环境变量
增加用户变量HADOOP_HOME,值是下载的zip包解压的目录。
确认变量生效:
点击开始菜单,运行=》cmd
打印当前变量:echo %HADOOP_HOME%
看看输出是否是
C:\hadoop\hadoop-common-2.2.0-bin-master
注意,需要重启一下 eclipse,才会重新加载环境变量。
重启一下 eclipse,再次运行程序,正常执行。
可能遇到的问题 —Caused by: java.lang.IllegalAccessError: tried to access method com.google.common.base.Stopwatch.()V from class org.apache.hadoop.hbase.zookeeper.MetaTableLocator–conn is null
连接总是获取不到,一直报空指针,hbase集群没问题,zookeeper连接没问题,phoenix客户端也没问题,配置连接字符串没问题。
这是因为guava的版本冲突了。
当前项目中其他包也在用的guava包版本为guava 18
hbase-client的版本需要与 guava版本对应。
hbase1.2.1:guava12-16,运行无误;
hbase1.3: guava17-18
解决方案一 调整引入的包的版本与 当前项目中的guava包匹配
例如之前使用的是
1
2
3
4
5
6
7 1<dependency>
2 <groupId>org.apache.phoenix</groupId>
3 <artifactId>phoenix-client</artifactId>
4 <version>4.14.1-HBase-1.2</version>
5</dependency>
6
7
修改为
1
2
3
4
5
6
7 1<dependency>
2 <groupId>org.apache.phoenix</groupId>
3 <artifactId>phoenix-client</artifactId>
4 <version>4.14.1-HBase-1.3</version>
5</dependency>
6
7
这里hbase与 服务的hbase集群的hbase版本不一致后续容易报错 nofoundMethod。所以最好还是使用hbase对应的版本,不要随便升级。
解决方案二(推荐)–手动解决冲突—升级或者降级guava包–可能影响得到项目的其他功能
Stopwatch在google的guava包下,在maven包管理器中查找guava,发现项目里有两个版本的guava,对着guava包18.0右键选择exclude删除掉guava-18.0.0.jar,保留与当前hbase版本匹配的另一个,运行成功。
这时候 查看pom.xml中的配置发现 其他包含有 guava包的jar包已经包含有
1
2
3
4
5
6
7
8 1<exclusions>
2 <exclusion>
3 <groupId>com.google.guava</groupId>
4 <artifactId>guava</artifactId>
5 </exclusion>
6 </exclusions>
7
8
如图
phoenix的包需要保留,去掉 exclusions如下:
1
2
3
4
5
6
7 1<dependency>
2 <groupId>org.apache.phoenix</groupId>
3 <artifactId>phoenix-client</artifactId>
4 <version>4.14.1-HBase-1.2</version>
5</dependency>
6
7
可能遇到的问题—NoClassDefFoundError: org/apache/hadoop/hbase/protobuf/generated/MasterProtos$MasterService$BlockingInterface
原因有多种情况,需要在maven的包管理器中查找下是哪种情况
1、缺少protobuf-java 2.5.0的jar包
2、多个protobuf jar包互相冲突
3、由于其他jar包中已经引用了protobuf-java的源码,jar加载时,如果其他jar包先加载,就会出现这个问题,需要让protobuf-java-2.5.0.jar先加载
我的项目情况 可能2和3都存在。
解决方案
排除高版本的引用
1
2
3
4
5
6
7
8
9
10
11
12
13 1 <dependency>
2 <groupId>com.mofang</groupId>
3 <artifactId>ribbon-dynamic-config-servers</artifactId>
4 <version>1.2.13</version>
5 <exclusions>
6 <exclusion>
7 <groupId>com.google.protobuf</groupId>
8 <artifactId>protobuf-java</artifactId>
9 </exclusion>
10 </exclusions>
11 </dependency>
12
13
明确加载对应版本的包和 包
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 1 <!-- https://mvnrepository.com/artifact/org.apache.hbase/hbase-protocol -->
2<dependency>
3 <groupId>org.apache.hbase</groupId>
4 <artifactId>hbase-protocol</artifactId>
5 <version>1.3.1</version>
6</dependency>
7
8
9<!-- https://mvnrepository.com/artifact/com.google.protobuf/protobuf-java -->
10<dependency>
11 <groupId>com.google.protobuf</groupId>
12 <artifactId>protobuf-java</artifactId>
13 <version>2.5.0</version>
14</dependency>
15
16
可能遇到的问题—Caused by: java.net.UnknownHostException: host250
因为在hbase-site.xml配置中使用的是host250这些主机名,而不是ip,但是在运行 java程序的机子中又没有主机名和ip的映射,所以无法识别。
解决方案
修改host文件增加对应映射
在windows7的时候修改host文件非常简单,可以直接修改,但是到了windows8、8.1以后的系统版本中,系统权限被收回,一般登录的账号都不是Administrator账号,在
/windows/system32/drivers/etc目录下修改host文件就会提示没有权限
鼠标右键点击桌面左下角的开始菜单,选择“命令提示符(管理员)”
在打开的黑色命令提示符窗口中输入 notepad,敲回车;
打开的记事本页面中点右上角的文件,然后点打开
在弹出的窗口中双击dirvers,然后再双击etc
点右下角的文本文档,然后选择所有文件,就看到显示出来了host等多个文件,鼠标选择host,然后点打开;
在打开的host文件中修改你要添加的内容,比如我这里要改的内容是
192.168.30.250 host250
192.168.30.217 host217
192.168.30.252 host252
192.168.30.253 host253
修改完成后点击文件,再点保存,发现这个时候就可以正常保存了。
让host文件生效
在cmd命令行中运行
ipconfig /flushdns //刷新DNS