继续我们的冒险体验,之前综述了一些构建一个项目的大致流程,相信大家对于系统的框架已经了然于胸。 今天我们就来谈一谈,如何构建数据的桥梁。
这里我们使用commons-dbutils 来简单的封装一个jdbc template, 帮助我们实现快速的CRUD. 废话不多讲直接上代码。
package org.foothold.learn2.helper;
import org.apache.commons.dbcp2.BasicDataSource;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.MapListHandler;
import org.foothold.learn2.util.PropsUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
/**
* Created by Jaden.Gu on 2018/11/16.
*/
public class DatabaseHelper {
private static final Logger logger = LoggerFactory.getLogger(DatabaseHelper.class);
private static final QueryRunner QUERY_RUNNER = new QueryRunner();
private static final ThreadLocal<Connection> CONNECTION_HOLDER = new ThreadLocal<>();
private static final BasicDataSource basicDataSource;
private static final String DRIVER;
private static final String URL;
private static final String USERNAME;
private static final String PASSWORD;
static {
Properties properties = PropsUtil.loadProps("db.properties");
basicDataSource = new BasicDataSource();
DRIVER = properties.getProperty("jdbc.driver");
URL = properties.getProperty("jdbc.url");
USERNAME = properties.getProperty("jdbc.username");
PASSWORD = properties.getProperty("jdbc.password");
basicDataSource.setDriverClassName(DRIVER);
basicDataSource.setUrl(URL);
basicDataSource.setUsername(USERNAME);
basicDataSource.setPassword(PASSWORD);
// try {
// Class.forName(DRIVER);
// } catch (ClassNotFoundException ex) {
// logger.error("DatabaseHelper ClassNotFoundException", ex);
// }
}
public static Connection getConnection() {
Connection conn = null;
try {
if(CONNECTION_HOLDER.get() == null) {
// conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
conn = basicDataSource.getConnection();
CONNECTION_HOLDER.set(conn);
}
} catch (SQLException ex) {
logger.error("getConnection", ex);
}
return CONNECTION_HOLDER.get();
}
public static void closeConnection() {
if(CONNECTION_HOLDER.get() != null) {
try {
CONNECTION_HOLDER.get().close();
} catch (SQLException ex) {
logger.error("closeConnection", ex);
}
}
}
public static <T> List<T> queryEntityList(Class<T> entityClass, String sql, Object... params) {
List<T> entityList = null;
try {
entityList = QUERY_RUNNER.query(getConnection(), sql, new BeanListHandler<T>(entityClass), params);
}catch (SQLException ex) {
logger.error("query entity list failure", ex);
throw new RuntimeException(ex);
} finally {
closeConnection();
}
return entityList;
}
public static <T> T queryEntity(Class<T> entityClass, String sql, Object... params) {
T entity = null;
try {
Connection connection = getConnection();
entity = QUERY_RUNNER.query(connection, sql, new BeanHandler<T>(entityClass), params);
} catch (SQLException ex) {
logger.error("queryEntity sql exception", ex);
throw new RuntimeException(ex);
} finally {
closeConnection();
}
return entity;
}
public static List<Map<String, Object>> executeQuery(String sql, Object... params) {
List<Map<String, Object>> result = null;
try{
Connection conn = getConnection();
result = QUERY_RUNNER.query(conn, sql, new MapListHandler(), params);
} catch (SQLException ex) {
logger.error("executeQuery sql exception", ex);
throw new RuntimeException(ex);
} finally {
closeConnection();
}
return result;
}
public static int executeUpdate(String sql, Object... params) {
int rows = 0;
try{
rows = QUERY_RUNNER.update(getConnection(), sql, params);
} catch (SQLException ex) {
logger.error("executeUpdate sql exception", ex);
throw new RuntimeException(ex);
} finally {
closeConnection();
}
return rows;
}
public static <T> boolean insertEntity(Class<T> entityClass, Map<String, Object> fieldMap) {
if(fieldMap.isEmpty()) {
logger.error("Can't insert entity : field is empty");
return false;
}
String sql = String.format("INSERT INTO %s", getTableName(entityClass));
StringBuilder columns = new StringBuilder("(");
StringBuilder values = new StringBuilder("(");
for(String column : fieldMap.keySet()) {
columns.append(column).append(", ");
values.append("?, ");
}
columns.replace(columns.lastIndexOf(", "), columns.length(), ")");
values.replace(values.lastIndexOf(", "), values.length(), ")");
sql += columns + " VALUES " + values;
Object[] parmas = fieldMap.values().toArray();
return executeUpdate(sql, parmas) == 1;
}
public static <T> boolean updateEntity(Class<T> entityClass, Map<String, Object> fieldMap, long id) {
if(fieldMap.isEmpty()) {
logger.error("Can't update entity : field is empty");
return false;
}
String sql = "UPDATE " + getTableName(entityClass) + " SET ";
StringBuilder columns = new StringBuilder();
for(String column : fieldMap.keySet()) {
columns.append(String.format(" %s = ? ", column));
}
sql += columns.substring(0, columns.length() -1) + " WHERE id = ? ";
List<Object> paramList = new ArrayList<>();
paramList.addAll(fieldMap.values());
paramList.add(id);
Object[] params = paramList.toArray();
return executeUpdate(sql, params) == 1;
}
public static <T> boolean deleteEntity(Class<T> entityClass, long id) {
String sql = "DELETE FROM " + getTableName(entityClass) + " WHERE id = ?";
return executeUpdate(sql, id) == 1;
}
private static String getTableName(Class<?> entityClass) {
return entityClass.getSimpleName().toLowerCase();
}
}
在static 代码快里,我们读取了配置文件,然后通过配置的数据库驱动类,数据库用户名、密码。初始化一个dpcp2 的数据源,然后通过dpcp2数据库连接池管理数据库连接,这样有助于减少频繁创建数据库所带来的昂贵开销。另外我们把从连接池中取到的连接放到了ThreadLocal中,实现了统一请求的连接复用。
若要使用dpcp2我们需要在pom.xml里添加以下依赖:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>2.1.1</version>
</dependency>
若想了解数据库连接池可以点击下方链接:
https://www.cnblogs.com/aspirant/p/6747238.html