寫(xiě)在前面
ORM框架,關(guān)系映射框架,只需要提供持久化類和數(shù)據(jù)庫(kù)表之間的關(guān)系,就可以在運(yùn)行時(shí)候進(jìn)行數(shù)據(jù)持久化,通常javaweb使用hibernate或者mybatis,本文就是寫(xiě)了一個(gè)簡(jiǎn)易版的orm框架。。只是實(shí)現(xiàn)了部分功能
功能介紹
1.可以根據(jù)表結(jié)構(gòu)自動(dòng)生成實(shí)體類
2.可直接插入,修改刪除對(duì)象,不需要寫(xiě)sql語(yǔ)句
3.在查詢時(shí)候需要自己寫(xiě)SQL語(yǔ)句,支持多行,單行,某一個(gè)字段的查詢
4.支持自定義實(shí)體類查詢,當(dāng)在進(jìn)行連表查詢的時(shí)候,得到的數(shù)據(jù)是自定義的,可自定義一個(gè)實(shí)體類進(jìn)行接收
5.連接使用了連接池,效率相對(duì)高一點(diǎn)
1.接口設(shè)計(jì)
- Query接口:符合查詢,對(duì)外提供服務(wù)的核心類
- QueryFactory類:管理query對(duì)象
- TypeConvertor接口:負(fù)責(zé)數(shù)據(jù)類型轉(zhuǎn)換
- TableContext類:負(fù)責(zé)獲取數(shù)據(jù)庫(kù)的表結(jié)構(gòu)和類結(jié)構(gòu)的關(guān)系,并可以根據(jù)表結(jié)構(gòu)生成類結(jié)構(gòu),
- DBManager類:根據(jù)配置信息,維持連接對(duì)象的管理
工具類
JdbcUtils 用來(lái)封裝通用的jdbc操作
StringUtils 用來(lái)封裝常用的字符串操作
ReflectUtils 用來(lái)封裝反射相關(guān)的操作
PathUtils 用來(lái)操作本地文件路徑相關(guān)的操作
JavaFileUtils
核心bean - COlumnInfo 封裝表中一個(gè)字段的信息
- Configuration 封裝整個(gè)項(xiàng)目的配置信息
- TableInfo: 封裝一張表的信息
- JavaFeildInfo:用于封裝一個(gè)屬性和get set方法的數(shù)據(jù)(在自動(dòng)生成java文件的時(shí)候用)
2.具體實(shí)現(xiàn)
1.query接口設(shè)計(jì)
框架封裝了常用的幾個(gè)方法
//將某個(gè)實(shí)體類持久化到數(shù)據(jù)庫(kù)中
public void insert(Object object);
//從數(shù)據(jù)庫(kù)中刪除某個(gè)數(shù)據(jù)
public void delete(Object object)
//從數(shù)據(jù)庫(kù)中刪除某條數(shù)據(jù),指定id
public void delete(Class clazz,Object id) ;
//更新某條數(shù)據(jù)
public void update(Object object,String[] fieldNames);
//根據(jù)傳入的sql語(yǔ)句進(jìn)行 查詢數(shù)據(jù),某個(gè)類型的數(shù)據(jù)
public List queryRows(String sql,Class clazz,Object[] params);
//查找某一列的數(shù)據(jù)
public Object queryValue(String sql,Object[] params);
//執(zhí)行增刪改sql語(yǔ)句的方法
public int executeDML(String sql,Object[] params);
2.數(shù)據(jù)類型轉(zhuǎn)換器
因?yàn)椴恢理?xiàng)目用的什么數(shù)據(jù)庫(kù),所以數(shù)據(jù)類型也不一樣,類型轉(zhuǎn)換器是一個(gè)接口,提供了實(shí)現(xiàn),現(xiàn)在只提供了mysql數(shù)據(jù)類型轉(zhuǎn)換器

轉(zhuǎn)換器有兩個(gè)方法,一個(gè)是java數(shù)據(jù)類型轉(zhuǎn)換成數(shù)據(jù)庫(kù)數(shù)據(jù)類型,另一個(gè)是數(shù)據(jù)庫(kù)類型轉(zhuǎn)換成java數(shù)據(jù)類型,因?yàn)榇隧?xiàng)目需要根據(jù)數(shù)據(jù)庫(kù)表生成java文件,所以只實(shí)現(xiàn)了數(shù)據(jù)庫(kù)類型轉(zhuǎn)換成java數(shù)據(jù)類型,如果需要另外轉(zhuǎn)換,只需要反過(guò)來(lái)即可
3.Configuration封裝配置信息
配置文件是db.properties,在src下
driver = com.mysql.jdbc.Driver //數(shù)據(jù)庫(kù)驅(qū)動(dòng)
username = root //用戶名
password = 123456 //密碼
useDB = mysql //聲明使用的數(shù)據(jù)庫(kù)
url = jdbc:mysql://localhost:3306/test // 連接url
packageName = jk.zmn.sorm.pojo //聲明自動(dòng)生成的實(shí)體類放在當(dāng)前項(xiàng)目哪個(gè)包下,可不存在
這個(gè)類主要是用來(lái)封裝用戶的配置信息,將配置信息保存起來(lái),使用更方便,配置類即是將這個(gè)屬性都封裝起來(lái)
4.DBManager類
這個(gè)類主要是用來(lái),讀取用戶的配置信息然后將信息封裝到configuration類中,管理數(shù)據(jù)庫(kù)連接,等功能

圖2.3.1封裝配置信息

圖2.3.2是管理數(shù)據(jù)庫(kù)連接,后期將會(huì)增加連接池功能
4.TableContext類
此類用來(lái)連接數(shù)據(jù)庫(kù),得到庫(kù)中的表,并封裝起來(lái),并且根據(jù)表信息自動(dòng)生成java文件,當(dāng)生成java實(shí)體類的時(shí)候,需要使用map將實(shí)體類的Class文件和表信息對(duì)應(yīng)存儲(chǔ)起來(lái),用于數(shù)據(jù)持久化,后面會(huì)講到
5.自動(dòng)生成java實(shí)體類實(shí)現(xiàn)
約定:如何根據(jù)表信息生成java類呢,我們先看看平時(shí)手動(dòng)生成的java實(shí)體類是什么樣子的,如表user,或_user 或t_user 再看看字段,id,name,或者t_id,t_name,我們自己寫(xiě)實(shí)體類會(huì)寫(xiě)成什么樣子呢,Class User 屬性寫(xiě)成 id,name或tname,tid, 那我們就先來(lái)個(gè)約定,如表名user,生成的類就叫User,首字母大寫(xiě),去掉下劃線,字段也是一樣,只需要去掉下劃線,get和set方法是getId 或者setName,首字母大寫(xiě),
思路: 上面我們已經(jīng)得到了數(shù)據(jù)庫(kù)中所有的表信息,也有了生成實(shí)體類的約定,那到底怎么生成呢,1.我們確定類名,根據(jù)表名得到得到類名, 2.屬性如何生成呢,還有g(shù)et set方法,我們將一個(gè)屬性和一個(gè)getset 方法封裝在一個(gè)類中,根據(jù)表中的字段信息,來(lái)生成一個(gè)字段對(duì)應(yīng)的屬性的相關(guān)信息,然后將所有字段的信息整合在這個(gè)類中,具體實(shí)現(xiàn)一下,我們還缺一些東西
5.1 ColumnInfo 類
封裝表中一個(gè)字段的信息,什么意思,
封裝了三個(gè)屬性,
/**
* 字段名稱
*/
private String name;
/**
* 字段數(shù)據(jù)類型
*/
private String dataType;
/**
* 字段鍵類型 0普通鍵,1主鍵 2外鍵
*/
private int keyType;
5.2TableInfo
封裝一張表的信息
/**
* 表名
*/
private String name;
/**
* 存放字段信息, 字段名和字段信息
*/
private Map<String,ColumnInfo> columns;
/**
* 主鍵信息
*/
private ColumnInfo onlyPriKey;
/**
* 聯(lián)合主鍵
*/
private List<ColumnInfo> priKeys;
5.3JavaFeildInfo
用于封裝一個(gè)屬性和get set方法的數(shù)據(jù),最后拼接類文件的時(shí)候用
/**
* 屬性信息 private String feild
*/
private String feildInfo;
/**
* 封裝get方法
*/
private String getFeildInfo;
/**
* 封裝set方法
*/
private String setFeildInfo;
有了上面的基本數(shù)據(jù),就可以進(jìn)行操作了
5.4 開(kāi)始生成文件
上面介紹了tablecontext類,用來(lái)得到數(shù)據(jù)庫(kù)中的表,使用map封裝起來(lái),附上源碼,接著下面看
/**
* 表名為key,表信息對(duì)象為value
*/
public static Map<String,TableInfo> tables = new HashMap<String,TableInfo>();
/**
* 將po的class對(duì)象和表信息對(duì)象關(guān)聯(lián)起來(lái),便于重用!
*/
public static Map<Class,TableInfo> poClassTableMap = new HashMap<Class,TableInfo>();
private TableContext(){}
static {
try {
//初始化獲得表的信息
Connection con = DBManager.getConnection();
DatabaseMetaData dbmd = con.getMetaData();
ResultSet tableRet = dbmd.getTables(null, "%","%",new String[]{"TABLE"});
while(tableRet.next()){
String tableName = (String) tableRet.getObject("TABLE_NAME");
TableInfo ti = new TableInfo(tableName,
new HashMap<String, ColumnInfo>(),new ArrayList<ColumnInfo>());
tables.put(tableName, ti);
ResultSet set = dbmd.getColumns(null, "%", tableName, "%"); //查詢表中的所有字段
while(set.next()){
ColumnInfo ci = new ColumnInfo(set.getString("COLUMN_NAME"),
set.getString("TYPE_NAME"), 0);
ti.getColumns().put(set.getString("COLUMN_NAME"), ci);
}
ResultSet set2 = dbmd.getPrimaryKeys(null, "%", tableName); //查詢t_user表中的主鍵
while(set2.next()){
ColumnInfo ci2 = (ColumnInfo) ti.getColumns().get(set2.getObject("COLUMN_NAME"));
ci2.setKeyType(1); //設(shè)置為主鍵類型
ti.getPriKeys().add(ci2);
}
if(ti.getPriKeys().size()>0){ //取唯一主鍵。。方便使用。如果是聯(lián)合主鍵。則為空!
ti.setOnlyPriKey(ti.getPriKeys().get(0));
}
}
} catch (SQLException e) {
e.printStackTrace();
}
//生成java文件
updatePoFile();
//將對(duì)應(yīng)的類和表封裝起來(lái)
loadTablePoToMap();
}
/**
* 根據(jù)數(shù)據(jù)庫(kù)表結(jié)構(gòu)生成pojo類
*/
public static void updatePoFile(){
JavaFileUtils.createJavaFileToPackage();
}
/**
* 加載完數(shù)據(jù)庫(kù)中的表,生成pojo之后,把對(duì)應(yīng)的類和對(duì)應(yīng)的表關(guān)聯(lián)起來(lái)
* @date 2018/6/15 19:44
* @param
* @return void
*/
public static void loadTablePoToMap(){
for (TableInfo tableInfo : tables.values()){
//實(shí)體類
Class<?> aClass = null;
try {
aClass = Class.forName(DBManager.getConfiguration().getPackageName()
+"."+StringUtils.UpFirstString(tableInfo.getName()));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
poClassTableMap.put(aClass,tableInfo);
}
}
5.5 使用javafileutils生成java文件
講一下思路:得到了所有的表信息,如何拼接成一個(gè)類
1.首先要先得到類名
根據(jù)表信息,得到j(luò)ava文件的類名,
2.得到所有的屬性和get set方法
得到表的一個(gè)字段信息,將字段的數(shù)據(jù)類型轉(zhuǎn)換成java數(shù)據(jù)類型,將字段名轉(zhuǎn)換成類的屬性名,拼接字符串,就得到了一個(gè)定義屬性的字符串,然后封裝get和set方法,將這一個(gè)屬性的信息,封裝在FieldInfo中,循環(huán)將所有的屬性都封裝完畢,
3.拼裝整個(gè)類文件
將包名,和類名和屬性一起封裝起來(lái),然后使用io流將文件輸出,問(wèn)題來(lái)了,輸出到哪里,指定了包,包不存在,使用PathUtils,將包名穿進(jìn)去,就會(huì)自動(dòng)創(chuàng)建包,
附源碼,
PathUtils
String str=packageName; //"jk.zmn.auto.dfd";
str = str.replace(".","\\");
File file = new File("");
String canonicalPath = null;
try {
canonicalPath = file.getCanonicalPath();
} catch (IOException e) {
e.printStackTrace();
}
canonicalPath += "\\src\\"+str;
// String resource = Thread.currentThread().getContextClassLoader().getResource("/").getPath();
// resource = resource.substring(1);
// System.out.println(resource);
File packageFile = new File(canonicalPath);
if (!packageFile.exists()){
packageFile.mkdirs();
}
return canonicalPath;
}
JavaFileutils
private static Configuration configuration = DBManager.getConfiguration();
/**
* private String name;
* <p>
* private String dataType;
* <p>
* private int keyType;
*/
public static javaFeildInfo createJavaFeild(ColumnInfo columnInfo, TypeConvertorHandler convertorHandler) {
//將字段數(shù)據(jù)類型轉(zhuǎn)換成java數(shù)據(jù)類型
String javaType = convertorHandler.JdbcType2JavaType(columnInfo.getDataType());
String columnName = columnInfo.getName().toLowerCase();
javaFeildInfo feildInfo = new javaFeildInfo();
//生成屬性語(yǔ)句
feildInfo.setFeildInfo("\tprivate " + javaType + " " + StringUtils.trimUnderLine(columnName) + ";\n");
StringBuilder sb = new StringBuilder();
sb.append("\tpublic " + javaType + " " + "get" + StringUtils.UpFirstString(columnName) + "() {\n");
sb.append("\t\treturn " + columnName + ";\n");
sb.append("\t}\n");
feildInfo.setGetFeildInfo(sb.toString());
StringBuilder sb1 = new StringBuilder();
sb1.append("\tpublic void " + "set" + StringUtils.UpFirstString(columnName) + "(" + javaType + " " + columnName + ") {\n");
sb1.append("\t\t this." + columnName + " = " + columnName + ";\n");
sb1.append("\t}\n");
feildInfo.setSetFeildInfo(sb1.toString());
return feildInfo;
}
public static void createJavaFile(TableInfo tableInfo, TypeConvertorHandler typeConvertorHandler){
//得到所有的列信息
Map<String, ColumnInfo> columns = tableInfo.getColumns();
ArrayList<javaFeildInfo> javaFeildInfos = new ArrayList<>();
Collection<ColumnInfo> values = columns.values();
//生成所有的java屬性信息和get set方法
for (ColumnInfo columnInfo : values){
javaFeildInfo javaFeild = createJavaFeild(columnInfo, typeConvertorHandler);
javaFeildInfos.add(javaFeild);
}
StringBuilder sb = new StringBuilder();
sb.append("package "+configuration.getPackageName()+";\n\n");
sb.append("import java.sql.*;\n");
sb.append("import java.util.*;\n\n");
sb.append("public class "+StringUtils.UpFirstString(tableInfo.getName())+" {\n\n");
for (javaFeildInfo javaFeildInfo: javaFeildInfos){
sb.append(javaFeildInfo.getFeildInfo());
}
sb.append("\n");
for (javaFeildInfo javaFeildInfo: javaFeildInfos){
sb.append(javaFeildInfo.getGetFeildInfo());
}
for (javaFeildInfo javaFeildInfo: javaFeildInfos){
sb.append(javaFeildInfo.getSetFeildInfo());
}
sb.append("}\n");
//System.out.println(sb.toString());
String classInfo = sb.toString();
String filePathFromPackage = PathUtils.getFilePathFromPackage(configuration.getPackageName());
File file = new File(filePathFromPackage, StringUtils.UpFirstString(tableInfo.getName()) + ".java");
BufferedOutputStream bufferedOutputStream=null;
try {
bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(file));
bufferedOutputStream.write(classInfo.getBytes(),0,classInfo.getBytes().length);
bufferedOutputStream.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
bufferedOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
System.out.println("表"+tableInfo.getName()+"對(duì)應(yīng)的類"+StringUtils.UpFirstString(tableInfo.getName())+"已自動(dòng)生成..");
}
public static void createJavaFileToPackage(){
Map<String, TableInfo> tables = TableContext.tables;
TypeConvertorHandler convertorHandler = null;
if (configuration.getUseDB().equalsIgnoreCase("mysql")){
convertorHandler = new MysqlConvertorHandler();
}
for (TableInfo tableInfo:tables.values()){
createJavaFile((tableInfo),convertorHandler);
}
}
6.查詢實(shí)現(xiàn)
如今實(shí)體類已經(jīng)有了,那么如何對(duì)數(shù)據(jù)進(jìn)行操作呢
,上面我們定義了一個(gè)Query接口,不同數(shù)據(jù)庫(kù)查詢可能不一樣,所以做一個(gè)mysqlQuery的實(shí)現(xiàn)類,做mysql的查詢
簡(jiǎn)單介紹添加方法,
傳入實(shí)體類,如何持久化到數(shù)據(jù)庫(kù)呢,還記得我們前面在得到數(shù)據(jù)庫(kù)表,生成java文件的時(shí)候?qū)ⅲ瑢?shí)體類的Class對(duì)象和表名存儲(chǔ)起來(lái)嗎,現(xiàn)在用到了哦
得到該類的Class對(duì)象,從map中取出表名,拼接sql語(yǔ)句,通過(guò)反射,得到該對(duì)象的所有的屬性,判斷是否為空,將不為空的屬性插入,那么該類的屬性的值怎么獲取呢,還是反射,根據(jù)屬性的get和set方法,反射調(diào)用該方法,得到屬性的值,將值和sql一起傳入執(zhí)行sql語(yǔ)句的方法,就完成持久化了
// insert into logs(a,b) values (?,?)
//得到類對(duì)應(yīng)的表信息
Class<?> aClass = object.getClass();
TableInfo tableInfo = TableContext.poClassTableMap.get(aClass);
StringBuilder sb = new StringBuilder("insert into "+tableInfo.getName()+"(");
//得到屬性
Field[] fields = aClass.getDeclaredFields();
ArrayList<Object> fieldValueList = new ArrayList<>();
for (Field field : fields){
String name = field.getName();
Object value = ReflectUtils.invokeGet(object, name);
if (value!=null){
sb.append(name+",");
fieldValueList.add(value);
}
}
//將最后一個(gè),換成)
sb.setCharAt(sb.length()-1,')');
sb.append(" values(");
for (int i=0;i<fieldValueList.size();i++){
sb.append("?,");
}
sb.setCharAt(sb.length()-1,')');
executeDML(sb.toString(),fieldValueList.toArray());
其他方法
/**
* 刪除一個(gè)對(duì)象
* @date 2018/6/15 16:54
* @param object 要移除的對(duì)象
* @return void
*/
public void delete(Object object){
Class<?> aClass = object.getClass();
TableInfo tableInfo = TableContext.poClassTableMap.get(aClass);
//得到表的主鍵
ColumnInfo onlyPriKey = tableInfo.getOnlyPriKey();
String sql = "delete from "+tableInfo.getName()+" where "+onlyPriKey.getName()+"=?";
//反射調(diào)用get方法,得到屬性的值
Object o = ReflectUtils.invokeGet(object, onlyPriKey.getName());
executeDML(sql,new Object[]{o});
}
/**
* 刪除類 對(duì)應(yīng)的表中的數(shù)據(jù),刪除該id的對(duì)象
* @date 2018/6/15 16:55
* @param clazz 類對(duì)象
* @param id 主鍵
* @return void
*/
public void delete(Class clazz,Object id) {
// delete from logs where id=?
TableInfo tableInfo = TableContext.poClassTableMap.get(clazz);
ColumnInfo onlyPriKey = tableInfo.getOnlyPriKey();
String sql = "delete from "+tableInfo.getName()+" where "+onlyPriKey.getName()+"=?";
executeDML(sql.toString(),new Object[]{id});
}
/**
* 更新對(duì)象字段的信息
* @date 2018/6/15 16:57
* @param object 對(duì)象
* @param fieldNames 多個(gè)字段
* @return void
*/
public void update(Object object,String[] fieldNames){
//obj{"uanme","pwd"}-->update 表名 set uname=?,pwd=? where id=?
Class c = object.getClass();
List<Object> params = new ArrayList<Object>(); //存儲(chǔ)sql的參數(shù)對(duì)象
TableInfo tableInfo = TableContext.poClassTableMap.get(c);
ColumnInfo priKey = tableInfo.getOnlyPriKey(); //獲得唯一的主鍵
StringBuilder sql = new StringBuilder("update "+tableInfo.getName()+" set ");
for(String fname:fieldNames){
Object fvalue = ReflectUtils.invokeGet(object,fname);
params.add(fvalue);
sql.append(fname+"=?,");
}
sql.setCharAt(sql.length()-1, ' ');
sql.append(" where ");
sql.append(priKey.getName()+"=? ");
params.add(ReflectUtils.invokeGet(object,priKey.getName())); //主鍵的值
executeDML(sql.toString(), params.toArray());
}
/**
* 根據(jù)參數(shù),查詢指定的數(shù)據(jù),多行記錄,單行記錄可直接get(0)
* @date 2018/6/15 16:59
* @param sql sql語(yǔ)句
* @param clazz 類對(duì)象
* @param params sql語(yǔ)句參數(shù)
* @return java.util.List
*/
public List queryRows(String sql,Class clazz,Object[] params){
Connection connection = DBManager.getConnection();
PreparedStatement ps = null;
List<Object> rows = new ArrayList<Object>();
ResultSet resultSet = null;
try {
ps = connection.prepareStatement(sql);
JdbcUtils.handlerParams(ps,params);
resultSet = ps.executeQuery();
//得到返回結(jié)果又多少列
ResultSetMetaData metaData = resultSet.getMetaData();
while (resultSet.next()){
Object o = clazz.newInstance();
for (int i=0;i<metaData.getColumnCount();i++){
//得到每一列的名稱
String columnLabel = metaData.getColumnLabel(i + 1);
Object columnValue = resultSet.getObject(i + 1);
ReflectUtils.invokeSet(o, columnLabel, columnValue);
}
rows.add(o);
}
return rows;
} catch (Exception e) {
e.printStackTrace();
}finally {
DBManager.close(connection,ps);
}
return null;
}
/**
* 查詢某個(gè)字段的數(shù)據(jù)
* @date 2018/6/15 17:05
* @param sql sql語(yǔ)句
* @param params 參數(shù)
* @return java.lang.Object 封裝查詢到的數(shù)據(jù)
*/
public Object queryValue(String sql,Object[] params){
Connection connection = DBManager.getConnection();
PreparedStatement ps = null;
ResultSet resultSet = null;
Object o =null;
try {
ps = connection.prepareStatement(sql);
JdbcUtils.handlerParams(ps,params);
resultSet = ps.executeQuery();
while (resultSet.next()){
o = resultSet.getObject(1);
}
} catch (Exception e) {
e.printStackTrace();
return null;
}finally {
DBManager.close(connection,ps);
}
return o;
}
/**
* 執(zhí)行sql語(yǔ)句
* @date 2018/6/15 16:50
* @param sql sql語(yǔ)句
* @param params 參數(shù)
* @return int SQL影響的行數(shù)
*
*/
public int executeDML(String sql,Object[] params){
Connection connection = DBManager.getConnection();
int count = 0;
PreparedStatement ps = null;
try {
ps = connection.prepareStatement(sql);
JdbcUtils.handlerParams(ps,params);
System.out.println(ps);
count = ps.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}finally {
DBManager.close(connection,ps);
}
System.out.println("count:"+count);
return count;
}
以上,基礎(chǔ)的增刪改查就可以實(shí)現(xiàn)了
7.項(xiàng)目修改
1.工廠模式得到Query對(duì)象,
private static QueryFactory queryFactory = new QueryFactory();
private static Class c;
static {
if (DBManager.getConfiguration().getUseDB().equalsIgnoreCase("mysql")){
try {
c = Class.forName("jk.zmn.sorm.core.MySqlQuery");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
/*
構(gòu)造器私有化
*/
private QueryFactory(){
}
public static Query createQuery(){
try {
return (Query) c.newInstance();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
2.添加連接池功能
當(dāng)對(duì)數(shù)據(jù)庫(kù)操作很頻繁的時(shí)候,如果每次都新建鏈接,關(guān)閉鏈接,很耗資源,使用連接池保存鏈接,提高項(xiàng)目的效率
/**
* 連接池對(duì)象
*/
private List<Connection> pool;
/**
* 最大連接數(shù)
*/
private static final int POOL_MAX_SIZE = DBManager.getConfiguration().getPoolMaxSize();
/**
* 最小連接池
*/
private static final int POOL_MIN_SIZE = DBManager.getConfiguration().getPoolMinSize();
/**
* 初始化連接池,使池中的連接數(shù)達(dá)到最小值
*/
public void initPool() {
if(pool==null){
pool = new ArrayList<Connection>();
}
while(pool.size()<DBPool.POOL_MIN_SIZE){
pool.add(DBManager.getConnection());
System.out.println("初始化池,池中連接數(shù):"+pool.size());
}
}
/**
* 從連接池中取出一個(gè)連接
* @return
*/
public synchronized Connection getConnection() {
int last_index = pool.size()-1;
Connection conn = pool.get(last_index);
pool.remove(last_index);
return conn;
}
/**
* 將連接放回池中
* @param conn
*/
public synchronized void close(Connection conn){
if(pool.size()>=POOL_MAX_SIZE){
try {
if(conn!=null){
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}else {
pool.add(conn);
}
}
public DBPool() {
initPool();
}
3.測(cè)試
如此一來(lái),項(xiàng)目大致就結(jié)束了,直接打成jar包,由別的項(xiàng)目引入
新建項(xiàng)目,導(dǎo)入此jar包
添加



這里的count是影響數(shù)據(jù)庫(kù)的行數(shù)
查詢


演示到這里
源碼看這里:https://gitee.com/zhangqiye/SORM
QQ群:552113611