磐维数据库,简称"PanWeiDB"。是中国移动信息技术中心首个基于中国本土开源数据库打造的面向ICT基础设施的自研数据库产品。其产品内核能力基于华为openGauss开源软件,并进一步提升了系统稳定性。
本文将介绍磐维数据库租户项目遇到的几个常见JDBC案例。
磐维数据库2.0 JDBC驱动包下载链接:
postgresql风格URL使用方式
jdbc:postgresql://ip:port/database_name
panweidb风格URL使用方式
jdbc:panweidb://ip:port/database_name
1.用户查询模式
JDBC里可以设置currentSchema参数:
jdbc:panweidb://ip:port/database_name?currentSchema=schema_name
不过更好的方式是在数据库服务端,对业务db或者user进行永久性设置,参考命令如下:
alter database my_db set search_path = my_schema_name; alter user my_user set search_path = my_schema_name; alter user my_user in database my_db set search_path to my_schema_name;
可以选择在db级别或者user级别进行设置,或者两者组合进行设置。
如果是后台脚本访问数据库,需要设置查询模式,也可参考使用如下三种方式之一。
方式一:使用-c设置参数,使用-f执行脚本
$ psql -c "set search_path to my_schema_name" -f script.sql
方式二:通过环境变量设置
$ env PGOPTIONS="-c search_path=my_schema_name" psql
方式三:通过连接参数设置
$ psql "dbname=postgres options=-csearch_path=my_schema_name"
2.客户端编码
如果客户端编码与数据库服务端编码不一致,可以显式设置客户端编码
使用psql连接时,可使用环境变量PGCLIENTENCODING进行设置:
export PGCLIENTENCODING='GBK' && psql -r
JDBC里需要使用两个参数:allowEncodingChanges和characterEncoding
jdbc:panweidb://ip:port/database_name?allowEncodingChanges=true&characterEncoding=GBK
3.批量插入
使用psql进行数据插入时可使用copy或\copy元命令对数据文件进行批量操作,在JDBC里有两种方式。
方式一:使用reWriteBatchedInserts参数,可将多条insert合并为一条insert,使用insert…values(?),(?)…多values的形式
jdbc:panweidb://ip:port/database_name?reWriteBatchedInserts=true&batchMode=off
注意需要设置batchMode=off,否则会出现如下错误:
batchMode and reWriteBatchedInserts can not both set true!
方式二:使用batchMode=on
jdbc:panweidb://ip:port/database_name?batchMode=on
行存表场景建议使用batchMode=on,插入性能提升更明显。
4.upsert与autoGeneratedKeys同时使用
connection.prepareStatement("insert into tab1(id,name) values(?,?) ON DUPLICATE KEY update name=excluded.name returning *", Statement.RETURN_GENERATED_KEYS);
上面的java代码里,使用insert on duplicate,同时打开了autoGeneratedKeys参数,则会出现如下错误:
ERROR: RETURNING clause is not yet supported within INSERT ON DUPLICATE KEY UPDATE statement.
经过测试oracle风格的upsert语句不能同时与autoGeneratedKeys参数使用。
在PanWeiDB 2.0.0版本里,PG兼容性模式下是可以正常使用。
首先在psql里进行测试,语法正常
panweidb=# insert into tab1(id,name) values(100,'panweidb') ON CONFLICT(id) do update set name=excluded.name returning *; id | name -----+---------- 100 | panweidb (1 row) INSERT 0 1
接着在java代码里进行如下测试,也能正常执行:
connection.prepareStatement("insert into tab1(id,name) values(?,?) ON DUPLICATE KEY update name=excluded.name returning *", Statement.RETURN_GENERATED_KEYS);
5.自动保存
psql可使用内置变量ON_ERROR_ROLLBACK,设置为on时允许事务块内的语句遇到错误时,可以被忽略,不回滚整个事务而继续执行。
它的原理是对事务块里的每个语句执行前都创建一个SAVEPOINT保存点,遇到语句执行出错后ROLLBACK到失败语句的保存点,然后继续往下执行。
JDBC里也可以设置autosave参数,功能类似于psql里的ON_ERROR_ROLLBACK。
jdbc:panweidb://ip:port/database_name?autosave=always
如果不使用autosave参数,应用端可能会遇到如下的错误提示信息:
current transaction is aborted, commands ignored until end of transaction block
使用autosave=always参数进行批量插入时,会创建较多的保存点,可能造成导入较慢,因为保存点未及时清理释放。
6.druid连接池案例
案例一:如果druid未显式配置dbType参数,可能遇到如下错误:dbType not support
com.alibaba.druid.pool.DruidDataSource:910 - {dataSource-1} init error
java.lang.IllegalStateException: dbType not support : null,
at com.alibaba.druid.wall.WallFilter.init(WallFilter.java:159)
配置druid的dbType参数为postgresql即可。
案例二:使用druid连接,应用端偶尔会出现如下错误:buffer is empty
处理方法:开启druid的keepalive参数,同时关闭testOnReturn,另外在JDBC URL增加 socketTimeout=30和connectTimeout=30参数。
案例三:使用druid配置filters防注入,分页语法使用LIMIT 0,10时,提示如下错误:
Error querying database. Cause: java.sql.SQLException: sql injection violation, syntax error: syntax error, error in :'imit 0,1',expect COMMA, actual COMMA limit
需要设置druid的limitZeroAllow=true。
上面使用了MySQL风格的分页方式,如下:
SELECT *
FROM t
ORDER BY id DESC LIMIT 0,10;
磐维2.0里还支持如下两种分页方式:
风格二:LIMIT … OFFSET… ,LIMIT控制返回的行数,OFFSET控制起始行。
SELECT *
FROM t
ORDER BY id DESC
LIMIT 10
OFFSET 0;
风格三:OFFSET … FETCH… ,OFFSET控制起始行,FETCH控制返回的行数。
SELECT *
FROM t
ORDER BY id DESC
OFFSET 0
FETCH FIRST 10 ROWS ONLY;




