SAP Hana是个内存数据库
驱动
<dependency>
<groupId>com.sap.cloud.db.jdbc</groupId>
<artifactId>ngdbc</artifactId>
<version>2.4.64</version>
</dependency>
package com.df.rpc.jdbc;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import java.io.PrintWriter;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.LinkedList;
import java.util.logging.Logger;
import javax.annotation.PostConstruct;
import javax.sql.DataSource;
/**
* 原生的jdbc连接池
*/
@SuppressWarnings("all")
@Slf4j
@Component
public class HanaJDBCPool implements DataSource {
private static LinkedList<Connection> listConnections = new LinkedList<Connection>();
@Value("${hana.db.driver}")
String driver;
@Value("${hana.db.url}")
String url;
@Value("${hana.db.username}")
String username;
@Value("${hana.db.password}")
String password;
@Value("${hana.db.initsize}")
Integer jdbcPoolInitSize;
@Value("${hana.db.poolmax}")
Integer jdbcPoolMax;//必须大于init 的两倍
@PostConstruct
public void initHanaConnection(){
try {
Class.forName(driver);
for(int i = 0;i< jdbcPoolInitSize;i++){
Connection conn = DriverManager.getConnection(url, username, password);
listConnections.add(conn);
}
} catch (Exception e) {
throw new ExceptionInInitializerError(e);
}
}
@Async
private void createConnection(){
try {
Class.forName(driver);
for(int i = 0;i< jdbcPoolInitSize;i++){
Connection conn = DriverManager.getConnection(url, username, password);
listConnections.add(conn);
}
} catch (Exception e) {
throw new ExceptionInInitializerError(e);
}
}
@Override
public Connection getConnection() throws SQLException {
if (listConnections.size() <= jdbcPoolMax/2){
createConnection();
}
if (listConnections.size() > 0) {
Connection conn1 = listConnections.removeFirst();
log.debug("linkedlist1数据库连接池大小是" + listConnections.size());
return (Connection) Proxy.newProxyInstance(conn1.getClass().getClassLoader(),
new Class[]{Connection.class}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (!method.getName().equalsIgnoreCase("close")) {
return method.invoke(conn1, args);
} else {
listConnections.add(conn1);
log.debug(conn1 + "对象被释放,重新放回linkedlist集合中!");
log.debug("此时Linkedlist集合中有" + listConnections.size() + "个数据库连接对象!");
return null;
}
}
});
} else {
log.error(url +" 连接数据库失败!");
}
return null;
}
@Override
public Connection getConnection(String username, String password) throws SQLException {
return null;
}
@Override
public PrintWriter getLogWriter() throws SQLException {
return null;
}
@Override
public void setLogWriter(PrintWriter out) throws SQLException {
}
@Override
public void setLoginTimeout(int seconds) throws SQLException {
}
@Override
public int getLoginTimeout() throws SQLException {
return 0;
}
@Override
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
return null;
}
@Override
public <T> T unwrap(Class<T> iface) throws SQLException {
return null;
}
@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException {
return false;
}
}
package com.df.rpc.jdbc;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
@SuppressWarnings("all")
@Slf4j
@Component
public class HanaJDBCRpc {
@Autowired
private HanaJDBCPool pool;
/**
* * 获取资源
*/
public Connection getConnection() throws SQLException {
return pool.getConnection();
}
/**
* * 关闭资源
* * @param resultSet 查询返回的结果集,没有为空
* * @param statement
* * @param connection
*/
public void close(ResultSet resultSet, Statement statement, Connection connection) {
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
resultSet = null;
}
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
}
查询结果包装
package com.df.rpc.utils;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 数据库查询结果POJO转换
*
* @author chenyl
*/
public class HanaDbUtil {
private static final char SEPARATOR = '_';
public static <T> T toBean(Class<T> clazz, ResultSet rs) throws Exception {
if (!rs.next()) {
return null;
}
T t = clazz.newInstance();
ResultSetMetaData rsmd = rs.getMetaData();
int len = rsmd.getColumnCount();
Map<String, Method> mm = getSetMethod(clazz);
for (int i = 1; i <= len; i++) {
String label = rsmd.getColumnLabel(i);
Method m = mm.get(lineToCamel(label, true));
if (m != null) {
m.invoke(t, rs.getObject(label));
}
}
return t;
}
public static Map<String, Object> toMap(ResultSet rs) throws Exception {
Map<String, Object> map = new HashMap<String, Object>();
if (!rs.next()) {
return null;
}
ResultSetMetaData rsmd = rs.getMetaData();
int len = rsmd.getColumnCount();
for (int i = 1; i <= len; i++) {
String label = rsmd.getColumnLabel(i);
map.put(lineToCamel(label, false), rs.getObject(label));
}
return map;
}
public static Map<String, Object> toStrMap(ResultSet rs) throws Exception {
Map<String, Object> map = new HashMap<String, Object>();
if (!rs.next()) {
return null;
}
ResultSetMetaData rsmd = rs.getMetaData();
int len = rsmd.getColumnCount();
for (int i = 1; i <= len; i++) {
String label = rsmd.getColumnLabel(i);
Object obj = rs.getObject(label);
if (obj instanceof java.sql.Timestamp) {
java.sql.Timestamp ts = (java.sql.Timestamp) obj;
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
map.put(lineToCamel(label, false), format.format(new Date(ts.getTime())));
} else if (obj instanceof java.util.Date) {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
map.put(lineToCamel(label, false), format.format((Date) obj));
} else {
map.put(lineToCamel(label, false), rs.getString(label));
}
}
return map;
}
public static <T> List<T> toList(Class<T> clazz, ResultSet rs) throws Exception {
List<T> list = new ArrayList<T>();
while (true) {
T t = toBean(clazz, rs);
if (t == null) {
break;
}
list.add(t);
}
return list;
}
public static List toList(ResultSet rs) throws Exception {
List list = new ArrayList();
while (true) {
Map m = toMap(rs);
if (m == null) {
break;
}
list.add(m);
}
return list;
}
public static List toStrList(ResultSet rs) throws Exception {
List list = new ArrayList();
while (true) {
Map m = toStrMap(rs);
if (m == null) {
break;
}
list.add(m);
}
return list;
}
private static Map<String, Method> getSetMethod(Class<?> clazz) {
Map<String, Method> map = new HashMap<String, Method>();
Method[] array = clazz.getMethods();
int len = array.length;
for (int i = 0; i < len; i++) {
Method m = array[i];
if (m.getName().startsWith("set") && m.getParameterTypes().length == 1) {
map.put(m.getName().substring(3), m);
}
}
return map;
}
public static String lineToCamel(String str, boolean firstUpperCase) {
if (str == null || str.length() == 0) {
return str;
}
str = str.toLowerCase();
int len = str.length();
StringBuffer sb = new StringBuffer();
boolean upperCase = firstUpperCase;
for (int i = 0; i < len; i++) {
char c = str.charAt(i);
if (c == SEPARATOR) {
upperCase = true;
continue;
}
if (upperCase) {
sb.append(Character.toUpperCase(str.charAt(i)));
upperCase = false;
} else {
sb.append(str.charAt(i));
}
}
return sb.toString();
}
public static String camelToLine(String str) throws Exception {
if (str == null || str.length() == 0) {
return str;
}
StringBuilder sb = new StringBuilder();
boolean nextIsUpperCase = false;
int len = str.length();
for (int i = 0; i < len; i++) {
char c = str.charAt(i);
if (i < len - 1) {
nextIsUpperCase = Character.isUpperCase(str.charAt(i + 1));
} else {
nextIsUpperCase = false;
}
if (Character.isLowerCase(c) && nextIsUpperCase) {
if (i < len - 1) {
sb.append(c).append(SEPARATOR).append(Character.toLowerCase(str.charAt(i + 1)));
i++;
} else {
sb.append(c).append(SEPARATOR);
}
} else if (Character.isUpperCase(c) && !nextIsUpperCase && i > 0) {
sb.append(SEPARATOR).append(Character.toLowerCase(str.charAt(i)));
} else {
sb.append(Character.toLowerCase(c));
}
}
return sb.toString();
}
public static void close(ResultSet rs) throws SQLException {
if (rs != null) {
rs.close();
}
}
public static void close(Connection conn) throws SQLException {
if (conn != null) {
conn.close();
}
}
}
配置文件
hana.db.name=poc-hana
hana.db.driver = com.sap.db.jdbc.Driver
#jdbc:sap://192.168.0.102:39015??DatabaseName=HXE&reconnect=true
hana.db.url=jdbc:sap://192.168.1.5:39015?reconnect=true
hana.db.username=SYSTEM
hana.db.password=Hana2021@123
hana.db.initsize=5
#必须大于init 的两倍
hana.db.poolmax=12