您的位置:首页 > 数据库

数据库基础操作和配置的整合集成-新手适用

2020-01-15 10:20 218 查看

数据库基础操作和配置的简单集成

背景

其他子公司的接口需求,因为只需要抛数据,所以打算写一个可以复用的WebService,这是其中的数据库部分操作的集成。

先贴出代码

package Xzzx.Liminghua.Util;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

/**
* @author 李明华
* 数据库连接公用方法集成
*/
public class DateBase {

private String driverClassName; // 数据库驱动字符串
private String url; // 连接URL字符串
private String username; // 数据库用户名
private String password; // 用户密码

/**
* 读取jdbc.properties配置文件
* 初始化连接参数
* 当需要连接数据库时使用相应的jdbc连接
* @param jdbcname jdbc.properties配置文件的文件名  例如:crmjdbc.properties
*/
public void init(String jdbcname) {
Properties params = new Properties();
//文件路径
String configFile = jdbcname;
//加载配置文件到输入流
InputStream is    = DateBase.class.getClassLoader().getResourceAsStream(configFile);

try {
//读取配置信息
//pro.load(类名.class.getResourceAsStream("/jdbc.properties"));
params.load(is);
} catch (IOException e) {
e.printStackTrace();
}

//获取连接参数
driverClassName = params.getProperty("driverClassName");
url = params.getProperty("url");
username = params.getProperty("username");
password = params.getProperty("password");
}
/**
* 获取数据库连接方法
* @return Connection对象
*/
public Connection getConnection(){
Connection con = null;
try {
Class.forName(driverClassName);
con = DriverManager.getConnection(url, username, password);
//System.out.print(username);//测试多数据库同时连接
//System.out.println("数据库连接成功");
} catch (Exception e) {
//System.out.println("数据库连接失败");
e.printStackTrace();
}
return con;
}

/**关闭数据库所有连接公用方法
* @param con 数据库连接
* @param stmt 数据库执行操作对象
* @param rs 数据库结果集
*/
public void closeAll(Connection con, Statement stmt, ResultSet rs){
// 若结果集对象不为空,则关闭
if (rs != null) {
try {
rs.close();
} catch (Exception e) {
e.printStackTrace();
}
}

// 若Statement对象不为空,则关闭
if (stmt != null) {
try {
stmt.close();
} catch (Exception e) {
e.printStackTrace();
}
}

// 若数据库连接对象不为空,则关闭
if (con != null) {
try {
con.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}

/**
* 执行增删改操作的公共方法
* @param preparedSql 预备好的SQL语句
* @param param SQL语句中的占位参数
* @return influnceNum SQL影响行数
*/
public int exceuteUpdate(String preparedSql, Object[] param) {
PreparedStatement pstmt = null;
int influnceNum = 0;
Connection con = getConnection();
try {
pstmt = con.prepareStatement(preparedSql);
if (param != null) {
for (int i = 0; i < param.length; i++) {
pstmt.setObject(i + 1, param[i]); // 为预编译SQL语句设置参数
}//end of for
}
influnceNum = pstmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
closeAll(con, pstmt, null);
}
return influnceNum;
}
/**
* 单个对象的公共查询方法
* @param sql   准备好的带占位符的SQL
* @param paras ArrayList存放查询条件
* @param cls	查询对象数据类型
* @return 返回在参数cls指定的数据类型的查询对象
*/
public <T> T findBySingleObject(String sql,ArrayList<Object> paras,Class<T> cls) {
Connection con =getConnection();
PreparedStatement pstmt = null;
ResultSet rs=null;
T singleObject = null;
int index = 1;

try {
pstmt = con.prepareStatement(sql);
if(paras != null && paras.size()>0) {
pstmt.clearParameters();
//清理上次留下的参数
for(int i = 0;i<paras.size();i++) {
pstmt.setObject(index++,paras.get(i));
}//end of for
//给SQL中的占位符赋值
}
rs = pstmt.executeQuery();
//执行查询操作
ResultSetMetaData rsmd = rs.getMetaData();
//利用ResultSet的getMetaData的方法可以获得ResultSetMeta对象
int columnCount = rsmd.getColumnCount();
//返回所有字段的数目
while(rs.next()) {
singleObject = cls.newInstance();
//通过反射实例化查询对象
for(int i = 0;i<columnCount;i++) {
String columnName = rsmd.getColumnName(i+1);
//根据行数位置得到查询对象的名称
Object columnValue = rs.getObject(columnName);
//通过名称得到查询对象
Field field = cls.getDeclaredField(columnName);
//得到文件类中查询对象的指定字段,将rs中得到的对象类型赋予filed(或者理解为根据实体类的字段名获取字段类型)
field.setAccessible(true);
//设置允许在反射时访问私有变量
field.set(singleObject, columnValue);
//将rs中得到的查询对象的对象类型和对象值赋予singleObject(返回值)
}//end of for
}//end of while
} catch (Exception e) {
e.printStackTrace();
} finally {
closeAll(con,pstmt,rs);
}
return singleObject;
}

/**
* 多个对象的公共查询方法
* @param sql 预备好的SQL语句
* @param paras 存放条件参数的List结构
* @param cls 查询对象的实体类型
* @return 返回存放查询对象的List结构
*/
public <T> List<T> queryListExecute(String sql,ArrayList<Object> paras,Class<T> cls){
Connection con = getConnection();
PreparedStatement pstmt = null;
ResultSet rs = null;
T singleObject = null;
int index = 1;
List <T> list = new ArrayList<T>();
try {
pstmt = con.prepareStatement(sql);
if(paras !=null && paras.size()>0) {
pstmt.clearParameters();
for(int i = 0;i<paras.size();i++) {
pstmt.setObject(index++, paras.get(i));
}//end of for
}
rs = pstmt.executeQuery();
ResultSetMetaData rsmd = rs.getMetaData();
int columnCount = rsmd.getColumnCount();
while(rs.next()) {
singleObject = cls.newInstance();
for(int i = 0;i<columnCount;i++) {
String columnName = rsmd.getColumnName(i+1);
Object columdValue = rs.getObject(columnName);
Field field = cls.getDeclaredField(columnName);
field.setAccessible(true);
field.set(singleObject, columdValue);
}//end of for
list.add(singleObject);
//将查询出的多个对象逐个放入list中。
}//end of while
} catch (Exception e) {
e.printStackTrace();
} finally {
closeAll(con, pstmt, rs);
}
return list;
}

}

1.和数据库建立连接

因为数据库建立连接的属性便于抽象,所以我把各个数据库的连接配置放在jdbc.properties文件当中,读取相应的jdbc.properties文件并将其赋值给抽象出来的操作对象,通过init()方法建立Connection:

1.在src目录下创建你需要的jdbc.properties文件

2. 类似如下格式配置连接信息
3. 下面这个初始化方法会将这些信息赋给DateBase对象。

/**
* 读取jdbc.properties配置文件
* 初始化连接参数
* 当需要连接数据库时使用相应的jdbc连接
* @param jdbcname jdbc.properties配置文件的文件名  例如:crmjdbc.properties
*/
public void init(String jdbcname) {
Properties params = new Properties();
//文件路径
String configFile = jdbcname;
//加载配置文件到输入流
InputStream is    = DateBase.class.getClassLoader().getResourceAsStream(configFile);

try {
//读取配置信息
//pro.load(类名.class.getResourceAsStream("/jdbc.properties"));
params.load(is);
} catch (IOException e) {
e.printStackTrace();
}

//获取连接参数
driverClassName = params.getProperty("driverClassName");
url = params.getProperty("url");
username = params.getProperty("username");
password = params.getProperty("password");
}

4.然后根据你需要的数据库参数建立相应的数据库连接

在这里插入代/**
* 获取数据库连接方法
* @return Connection对象
*/
public Connection getConnection(){
Connection con = null;
try {
Class.forName(driverClassName);
con = DriverManager.getConnection(url, username, password);
System.out.print(username);
System.out.println("数据库连接成功");
} catch (Exception e) {
System.out.println("数据库连接失败");
e.printStackTrace();
}
return con;
}
  1. 测试类
package Test;

import java.util.ArrayList;

import Xzzx.Liminghua.Util.DateBase;

public class DateBaseTest {

public static void main(String[] args) {
DateBase dateBase  = new DateBase();
DateBase dateBase2 = new DateBase();
dateBase.init("crmjdbc.properties");
dateBase2.init("testmysqljdbc.properties");
dateBase.getConnection();
dateBase2.getConnection();
}
}
  1. 运行结果如图
    我测试了一个sqlserver数据库和一个mysql数据库,建立了2个连接,sqlserver数据库的用户名为sa,mysql数据库的用户名为root。通过init()方法中的控制台打印可以看到都成功了。

  2. 关闭数据库连接的方法过于简单,不做赘述。

2.增删改方法的集成

/**
* 执行增删改操作的公共方法
* @param preparedSql 预备好的SQL语句
* @param param SQL语句中的占位参数
* @return influnceNum SQL影响行数
*/
public int exceuteUpdate(String preparedSql, Object[] param) {
PreparedStatement pstmt = null;
int influnceNum = 0;
Connection con = getConnection();
try {
pstmt = con.prepareStatement(preparedSql);
if (param != null) {
for (int i = 0; i < param.length; i++) {
pstmt.setObject(i + 1, param[i]); // 为预编译SQL语句设置参数
}//end of for
}
influnceNum = pstmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
closeAll(con, pstmt, null);
}
return influnceNum;
}

3.查询方法的集成

/**
* 单个对象的公共查询方法
* @param sql   准备好的带占位符的SQL
* @param paras ArrayList存放查询条件
* @param cls	查询对象数据类型
* @return 返回在参数cls指定的数据类型的查询对象
*/
public <T> T findBySingleObject(String sql,ArrayList<Object> paras,Class<T> cls) {
Connection con =getConnection();
PreparedStatement pstmt = null;
ResultSet rs=null;
T singleObject = null;
int index = 1;

try {
pstmt = con.prepareStatement(sql);
if(paras != null && paras.size()>0) {
pstmt.clearParameters();
//清理上次留下的参数
for(int i = 0;i<paras.size();i++) {
pstmt.setObject(index++,paras.get(i));
}//end of for
//给SQL中的占位符赋值
}
rs = pstmt.executeQuery();
//执行查询操作
ResultSetMetaData rsmd = rs.getMetaData();
//利用ResultSet的getMetaData的方法可以获得ResultSetMeta对象
int columnCount = rsmd.getColumnCount();
//返回所有字段的数目
while(rs.next()) {
singleObject = cls.newInstance();
//通过反射实例化查询对象
for(int i = 0;i<columnCount;i++) {
String columnName = rsmd.getColumnName(i+1);
//根据行数位置得到查询对象的名称
Object columnValue = rs.getObject(columnName);
//通过名称得到查询对象
Field field = cls.getDeclaredField(columnName);
//得到文件类中查询对象的指定字段,将rs中得到的对象类型赋予filed(或者理解为根据实体类的字段名获取字段类型)
field.setAccessible(true);
//设置允许在反射时访问私有变量
field.set(singleObject, columnValue);
//将rs中得到的查询对象的对象类型和对象值赋予singleObject(返回值)
}//end of for
}//end of while
} catch (Exception e) {
e.printStackTrace();
} finally {
closeAll(con,pstmt,rs);
}
return singleObject;
}

/**
* 多个对象的公共查询方法
* @param sql 预备好的SQL语句
* @param paras 存放条件参数的List结构
* @param cls 查询对象的实体类型
* @return 返回存放查询对象的List结构
*/
public <T> List<T> queryListExecute(String sql,ArrayList<Object> paras,Class<T> cls){
Connection con = getConnection();
PreparedStatement pstmt = null;
ResultSet rs = null;
T singleObject = null;
int index = 1;
List <T> list = new ArrayList<T>();
try {
pstmt = con.prepareStatement(sql);
if(paras !=null && paras.size()>0) {
pstmt.clearParameters();
for(int i = 0;i<paras.size();i++) {
pstmt.setObject(index++, paras.get(i));
}//end of for
}
rs = pstmt.executeQuery();
ResultSetMetaData rsmd = rs.getMetaData();
int columnCount = rsmd.getColumnCount();
while(rs.next()) {
singleObject = cls.newInstance();
for(int i = 0;i<columnCount;i++) {
String columnName = rsmd.getColumnName(i+1);
Object columdValue = rs.getObject(columnName);
Field field = cls.getDeclaredField(columnName);
field.setAccessible(true);
field.set(singleObject, columdValue);
}//end of for
list.add(singleObject);
//将查询出的多个对象逐个放入list中。
}//end of while
} catch (Exception e) {
e.printStackTrace();
} finally {
closeAll(con, pstmt, rs);
}
return list;
}

查询方法的测试


结果截图

写的挺折腾的,其实就是ResultSetMetaData这个类描述了ResultSet的数据结构,所以我们根据这个数据结构利用反射机制再在ResultSet中找到查询对象自身的类型和值。不知道这样写对不对…Whatever,It works.

写在后面

总是在参考别人的,想了一下其实不管技术程度的高低好坏,能相互分享并乐于相互分享帮助不正是我们这个职业群体的优点之一吗。以后还是要多总结。

  • 点赞
  • 收藏
  • 分享
  • 文章举报
还是Eclipse好用 发布了4 篇原创文章 · 获赞 2 · 访问量 375 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: