自己做个java sqlite连接池,自己做javasqlite
因各种奇葩原因只能自制一个简易的连接池
虽然不是那么强大, 但是已经满足了项目的要求。
能快速的获取和定期释放连接即可,包括max,min的阈值效用定义一个对象。这没什么好说的
import java.sql.Connection;
/**
* 连接池对象容器
*
* @author Allen
* @date 2016年10月31日
*
*/
public class SqlitePojo {
private long createTime;// 时间戳
private Connection con;// 链接对象
public SqlitePojo() {
// TODO Auto-generated constructor stub
}
public SqlitePojo(long createTime, Connection con) {
this.createTime = createTime;
this.con = con;
}
public long getCreateTime() {
return createTime;
}
public void setCreateTime(long createTime) {
this.createTime = createTime;
}
public Connection getCon() {
return con;
}
public void setCon(Connection con) {
this.con = con;
}
}
我们通过配置在初始化的时候按照min进行连接预创建,并启动了回收机制
每个连接对象都有自己的时间戳,来保障回收线程可以抓到他,消灭它
创建数据库就不说了,每天创建一个。
先进先出从池子里面获取数据库链接,当链接不足的时候填满它,就那么简单,没有复杂的要求,没有复杂的规划。
import java.io.File;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;
import java.util.Vector;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.troila.core.utils.PropertiesUtils;
/**
* sqlite连接池
*
* @author Allen
* @date 2016-10-31
*
*/
public class SqliteFactory {
private static Log logger = LogFactory.getLog("interceptorLog");
private static int max = Integer.parseInt(PropertiesUtils.sourceMap.get("sqlite.max"));// 最大池链接
private static int min = Integer.parseInt(PropertiesUtils.sourceMap.get("sqlite.min"));// 初始池链接
private static int step = Integer.parseInt(PropertiesUtils.sourceMap.get("sqlite.step"));// 每次最大补充线程数量
private static String dbPath;// 数据库链接路径
private static String timeFlag;// 日期时间戳
protected static long timeout = Integer.parseInt(PropertiesUtils.sourceMap.get("sqlite.timeout"));// 超时线程回收
protected static Vector<SqlitePojo> sList = new Vector<SqlitePojo>();// 链接容器
protected static Vector<SqlitePojo> sRunList = new Vector<SqlitePojo>();// 已分配的链接容器
static {
ini();
new Thread(new Recovery()).start();
}
/**
* sqlite对象获取异常
*
* @author Allen
* @date 2016年10月31日
*
*/
final class SqlitePojoException extends Exception {
private static final long serialVersionUID = 1L;
@Override
public void printStackTrace() {
print("ERROR:[池对象创建异常]");
super.printStackTrace();
}
}
/**
* 池溢出
*
* @author Allen
* @date 2016年10月31日
*
*/
final class SqliteMaxException extends Exception {
private static final long serialVersionUID = -3970424418466308414L;
@Override
public void printStackTrace() {
print("ERROR:[连接池总数超过最大设置 max:", max);
super.printStackTrace();
}
}
/**
* 对已分配容器的操作类型不存在
*
* @author Allen
* @date 2016年10月31日
*
*/
final class ExecuteTypeIsException extends Exception {
private static final long serialVersionUID = -3970424418466308414L;
@Override
public void printStackTrace() {
print("ERROR:[对已分配容器的操作类型不存在]");
super.printStackTrace();
}
}
/**
* 初始化连接池
*
* @author Allen
* @throws SQLException
* @date 2016年10月31日
*/
private static void ini() {
Connection con = null;
Statement stmt = null;
try {
setClass();
if (timeFlag == null) {
// 启动后为时间戳设置一个当前日期
timeFlag = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
String path = new StringBuffer(PropertiesUtils.sourceMap.get("sqlite.dbpath")).append(PropertiesUtils.sourceMap.get("sqlite.dbfile").replace("{?}", timeFlag)).toString();
dbPath = path;
createDb(con, stmt);
}
addD(min);
} catch (Exception e) {
sList.clear();
print("ERROR:[池初始化失败][池容器已清空]");
e.printStackTrace();
} finally {
try {
if (con != null)
con.close();
if (stmt != null)
stmt.close();
} catch (SQLException e) {
print("ERROR:[池初始化失败][池容器已清空]");
sList.clear();
e.printStackTrace();
}
}
}
/**
* 设置驱动
*
* @throws ClassNotFoundException
* @author Allen
* @date 2016年10月31日
*/
private static void setClass() throws ClassNotFoundException {
Class.forName("org.sqlite.JDBC");
}
/**
* 创建一个新的db文件并为其创建数据库
*
* @param con
* @param stmt
* @param path
* @author Allen
* @throws SQLException
* @date 2016年10月31日
*/
private static void createDb(Connection con, Statement stmt) throws SQLException {
File f = new File(dbPath);
// 如果文件不存在则创建
// 创建新的db文件并新建表
if (!f.isFile()) {
con = DriverManager.getConnection(new StringBuffer("jdbc:sqlite:").append(dbPath).toString());
stmt = con.createStatement();
String sql = "CREATE TABLE log ("+
"id INTEGER PRIMARY KEY ASC AUTOINCREMENT NOT NULL,"+
"action_userId INT NOT NULL,"+
"action_loginId VARCHAR (100) NOT NULL,"+
"action_userName VARCHAR (20) NOT NULL,"+
"action_name VARCHAR (30) NOT NULL,"+
"action_param TEXT NOT NULL,"+
"action_result VARCHAR (20) NOT NULL,"+
"action_time TIME (25) NOT NULL DEFAULT (datetime('now', 'localtime') ),"+
"action_ip VARCHAR (20),"+
"action_role INTEGER (2) "+
");";
stmt.executeUpdate(sql);
}
}
/**
* 获取链接
*
* @return
* @author Allen
* @throws Exception
* @throws SQLException
* @throws SqliteMaxException
* @throws ExecuteTypeIsException
* @date 2016年10月31日
*/
public Connection getCon() throws SQLException, SqlitePojoException, SqliteMaxException, ExecuteTypeIsException {
/**
* 先进先出原则
*/
SqlitePojo sPojo = null;
checkLogDay();
synchronized (sList) {
checkList();
sPojo = sList.get(0);
sList.remove(0);
changeRunList(sRunList, 0, sPojo);
}
if (sPojo == null || sPojo.getCon().isClosed())
throw new SqlitePojoException();
return sPojo.getCon();
}
/**
* 同步对已分配容器进行操作
*
* @param list
* @param type
* 0 add 1 remove
* @param Object
* ob
* @throws ExecuteTypeIsException
* @author Allen
* @date 2016年10月31日
*/
protected synchronized void changeRunList(Vector<SqlitePojo> list, int type, Object... ob) throws ExecuteTypeIsException {
switch (type) {
case 0:
// add
list.add((SqlitePojo) ob[0]);
break;
case 1:
// del
list.remove(Integer.parseInt(ob[0].toString()));
break;
default:
throw new ExecuteTypeIsException();
}
}
/**
* 检查容器是否满足使用需求
*
* @throws SqliteMaxException
* @author Allen
* @throws SQLException
* @date 2016年10月31日
*/
private void checkList() throws SqliteMaxException, SQLException {
if (sList.size() == 0) {
// 超过最大线程数
int num = 0;
if ((num = max - sRunList.size() - sList.size()) <= 0)
throw new SqliteMaxException();
// 剩余可增加线程数
num = num > step ? step : num;
addD(num);
}
}
/**
* 检查日志日期
*
* @author Allen
* @throws SQLException
* @date 2016年10月31日
*/
private synchronized static void checkLogDay() {
String tempTime = null;
Connection con = null;
Statement stmt = null;
try {
if (!timeFlag.equals((tempTime = new SimpleDateFormat("yyyy-MM-dd").format(new Date())))) {
// 时间戳已过期
timeFlag = tempTime;
dbPath = new StringBuffer(PropertiesUtils.sourceMap.get("sqlite.dbpath")).append(PropertiesUtils.sourceMap.get("sqlite.dbfile").replace("{?}", timeFlag)).toString();
createDb(con, stmt);
for (int i = 0; i < sList.size(); i++) {
// 更新历史时间的list
sList.get(i).setCon(DriverManager.getConnection(new StringBuffer("jdbc:sqlite:").append(dbPath).toString()));
}
}
} catch (Exception e) {
print("ERROR:[新日期检查更新失败][池容器已清空]");
e.printStackTrace();
} finally {
try {
if (con != null)
con.close();
if (stmt != null)
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/**
* 添加新的链接到容器
*
* @param num
* @throws SQLException
* @author Allen
* @date 2016年10月31日
*/
private static void addD(int num) throws SQLException {
for (int i = 0; i < num; i++) {
checkLogDay();
sList.add(new SqlitePojo(new Date().getTime(), DriverManager.getConnection(new StringBuffer("jdbc:sqlite:").append(dbPath).toString())));
}
}
/**
* 字符串组装
*
* @param str
* @return
* @author Allen
* @date 2016年10月31日
*/
protected static void print(Object... ob) {
StringBuffer sbf = new StringBuffer();
for (Object temp : ob)
sbf.append(temp);
logger.info(sbf.toString());
}
public static void main(String[] args) {
try {
while (true) {
Scanner sc = new Scanner(System.in);
if (sc.next() != null) {
long s = System.currentTimeMillis();
new SqliteFactory().getCon();
System.out.println(System.currentTimeMillis() - s + "ms");
}
}
} catch (Exception e) {
// TODO: handle exception
}
}
}
回收线程,非常直接从池容器删掉过期容器,当然这个method是sync的
调整容器大小和循环索引
import java.sql.SQLException;
import java.util.Date;
import java.util.Vector;
/**
* 池回收线程
*
* @author Allen
* @date 2016年10月31日
*
*/
final class Recovery extends SqliteFactory implements Runnable {
public Recovery() {
}
@Override
public void run() {
while (true) {
try {
Thread.sleep(1000);
//print("INFO:[可用链接数:", sList.size(), "]", "[已用连接数:", sRunList.size(), "]");
Vector<SqlitePojo> list = sRunList;
for (int i = 0; i < list.size(); i++) {
if (list.get(i).getCon().isClosed() || new Date().getTime() - list.get(i).getCreateTime() > timeout) {
changeRunList(list, 1, i);
if (list.size() >= i)
--i;
}
}
} catch (InterruptedException e) {
sList.clear();
sRunList.clear();
print("ERROR:[池回收线程死掉]");
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} catch (ExecuteTypeIsException e) {
e.printStackTrace();
}
}
}
}
本站文章为和通数据库网友分享或者投稿,欢迎任何形式的转载,但请务必注明出处.
同时文章内容如有侵犯了您的权益,请联系QQ:970679559,我们会在尽快处理。