JdbcUtil JDBC工具类

hydyy 2010-01-20 09:55:40

import java.sql.*;
/**
* @JDBC工具类
* 功能:
* 1 获得Connection
* 2 String转Integer
* 3 select table
* 4 读取任意结果集
* 5 关连接
*/
public class JdbcUtil {
/**
*
* @加载类
*/
static {
try {
String driverClassName = "oracle.jdbc.driver.OracleDriver";
Class.forName(driverClassName);
}catch(Exception e) {
e.printStackTrace();
}
}
/**
* @获得Connection
*/
public static Connection getConnection() {
Connection con = null;
try {
String url = "jdbc:oracle:thin:@192.168.0.20:1521:tarena";
// 协议+主机地址+资源名称
String userName = "openlab";
String pwd = "open123";
con = DriverManager.getConnection(url, userName, pwd);
} catch (Exception e) {
e.printStackTrace();
}
return con;
}
/**
* @String转Integer
*/
public static Integer toInt(String num) {
Integer i = null;
try {
i = Integer.parseInt(num);
} catch (Exception e) {
System.out.println(e.getMessage());
}
return i;
}
/**
* @select table
*/
public static void selectTable(String tableName){
Connection con = null;
PreparedStatement ps = null;
ResultSet rs = null;
try{
con = JdbcUtil.getConnection();
String sql = "select * from "+tableName;
ps = con.prepareStatement(sql);
rs = ps.executeQuery();

ResultSetMetaData meta = rs.getMetaData();
int cols = meta.getColumnCount();
StringBuffer sb = new StringBuffer();
while(rs.next()){
for (int i = 1; i <= cols; i++) {
sb.append(meta.getColumnName(i)+" = ");
sb.append(rs.getString(i)+" ");
}
sb.append("\n");
}
System.out.println(sb.toString());
}catch(Exception e){
System.out.println(e.getMessage());
}finally{
JdbcUtil.close(rs, ps, con);
}

}
/**
* 读取任意结果集
* @param rs
*/
public static void printRs(ResultSet rs) {
try{
ResultSetMetaData meta = rs.getMetaData();
int cols = meta.getColumnCount();
StringBuffer sb = new StringBuffer();
int n = 0;
while(rs.next()){
for (int i = 1; i <= cols; i++) {
sb.append(meta.getColumnName(i)+" = ");
sb.append(rs.getString(i)+" ");
}
sb.append("\n");
n++;
}
System.out.println(sb.toString());
System.out.println("找到-"+n+"条记录");
}catch(Exception e){
System.out.println(e.getMessage());
}
}
/**
* @关连接
*/
public static void close(ResultSet rs, Statement stmt, Connection con) {
/**
* 要按照顺序关 rs-->stmt-->con
*/
try {
if (rs != null)
rs.close();
} catch (Exception e) {
e.printStackTrace();
}
try {
if (stmt != null)
stmt.close();// 对象还在,不过不能用了,对象是垃圾回收器去回收的!
} catch (Exception e) {
e.printStackTrace();
}
try {
if (con != null)
con.close();
} catch (Exception e) {
e.printStackTrace();
}
}

}

自己写的JDBC工具类 望高手改进
并且说一下,本人新手!各位高手看看还有什么功能应该实现的,说说。



不忘记宣传下自己的群:java讨论群 66901044 学习群,欢迎来指导学习!
...全文
1590 14 打赏 收藏 举报
写回复
14 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
dinghun8leech 2010-01-25
  • 打赏
  • 举报
回复
这是我1年前的小菜水平,见笑了,也欢迎前辈提出意见。
楼主给分 >...<
小贝壳666 2010-01-25
  • 打赏
  • 举报
回复
我只提两点简单
第一,配置信息如URL USER PASSWORD等应该放到properties文件或XML文件中
第二,连接池技术
dinghun8leech 2010-01-25
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 hydyy 的回复:]

3.静态变量+静态方法,当多个线程同时调用这个组件的不同方法时,他们使用的很可能是同一个连接,或是没用完就被别的线程关闭,这个设计缺陷直接导致楼主定义的这个组件是个不能用的东西。

那应该怎么去设计呢,希望大侠给出建议!万分感激!!!

4.没有看到有关数据库事务的api定义。

事务我一知半解,而且我也不知道这个程序中我应该在哪里去写事务,帮帮忙吧,谢谢了各位大侠!

5.每个原子方法都开关连接,而实际情况往往一段逻辑要执行好几次数据库操作,或是用事务封装好几个原子操作,解决方法是将连接的开关管理和事务管理从这些方法中抽离。

原子方法的具体定义是什么啊?不懂哎,我真够菜的

[/Quote]
回3
将这个组件设计成每个调用处都要新建实例的方法,而不是提供一大堆静态方法。每新建一个实例,组件中就新建一个数据库连接,每使用这个实例调用一次实例方法,就用这个连接生成一个statement、preparedstatement或resultset,另外再提供一个释放连接资源的实例方法。这样只要在每个调用处实例化这个组件,就等于得到一条连接和使用这一连接的方法,且一个连接可操作多次后才释放。不同的调用处只要实例化各自的组件,即可保证线程安全,因为他们用的根本不是一条连接,即不是同一个dbutil组件。
回4
事务层不应该与dbutil层胶着在一起,可以提供管理功能,比如开启、提交和回滚,也就是事务管理和数据库连接有关,与数据库操作的方法无关。
回5
打个比方,帐户A向帐户B汇款,其中肯定会有这两步:第一步,扣除帐户A账上的对应金额,第二步,在帐户B上加上对应金额。那么整个汇款过程就是一个事务,上述第一步和第二步即为这个事务的原子操作,事务是封装了一系列原子操作,保证其全部成功要么全部失效,所以上面的例子中两步只要有一步错,汇款都会失败,操作都会被回滚,如果不用事务,那么会出什么问题就不得而知了。


我水平不高,只能说给个例子,当中肯定还有各种各样的设计上的不合理,楼主可以谨慎参考下。

package com.xxx.dbImpl;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.DriverManager;
import com.xxx.common.Print;
import com.xxx.db.DB;
import com.xxx.db.DBException;
/**
* 数据库底层操作类:提供执行sql语句的服务
* @author:dinghun8leech
* @date:081216
* @version:1.0
*/
public class DbUtil extends DB {
/** con 数据连接 */
private Connection con;
/** stmt 执行静态sql语句 */
private Statement stmt;
/** 加载数据库驱动 */
static {
try {
Class.forName(driverName);
} catch (Exception e) {
Print.ln("数据库驱动类未找到。");
Print.er(e);
}
}
/**
* +1参数构造方法,建立此类实例对象的同时也获得已建立的数据库链接
* @param Object 描述当前会话所使用的语言的字符串对象
* @throws DBException 当创建数据库连接失败时抛出此异常
*/
public DbUtil(Object obj) throws DBException {
try {
if (obj == null || (obj.toString()).equals(CHINESE)) {
con = DriverManager.getConnection(Chinese_dbUrl,dbUser,dbPwd);
} else if ((obj.toString()).equals(ENGLISH)) {
con = DriverManager.getConnection(English_dbUrl,dbUser,dbPwd);
} else if ((obj.toString()).equals(MCDONALD)) {
con = DriverManager.getConnection(MCDONALD_dbUrl,dbUser,dbPwd);
} else {
con = DriverManager.getConnection(Chinese_dbUrl,dbUser,dbPwd);
}
} catch (SQLException e) {
Print.er(e);
throw new DBException("数据库连接建立失败。");
}
}
/**
* 执行非查询类的完整SQL语句
* @param String 需要执行的静态sql语句
* @throws DBException 当数据库操作出现异常或资源不能正常释放时抛出此异常
*/
public void execute(String sql) throws DBException {
Print.sql(sql);
try {
stmt = con.createStatement();
stmt.execute(sql);
} catch (SQLException e) {
Print.er(e);
throw new DBException("数据库操作失败:"+sql);
} finally {
try {
if (stmt != null) {
stmt.close();
}
} catch (SQLException e) {
Print.er(e);
throw new DBException("Statement资源释放出错。");
}
}
}
/**
* 执行查询类的完整SQL语句
* 需在调用端释放Statement与ResultSet资源
* @param String 需要执行的静态sql语句
* @return ResultSet ResultSet类型的结果集
* @throws DBException 当数据库操作出现异常时抛出此异常
*/
public ResultSet executeQuary(String sql) throws DBException {
Print.sql(sql);
try {
stmt = con.createStatement();
return stmt.executeQuery(sql);
} catch (SQLException e) {
Print.er(e);
throw new DBException("数据库操作失败:"+sql);
}
}
/**
* 执行添加类的完整SQL语句,并返回自动生成的主键值
* @param String 需要执行的完整SQL语句
* @return int 添加数据后自动生成的int类型的主键值,非添加类SQL语句则返回0
* @throws DBException 当数据库操作出现异常或释放资源失败时抛出此异常
*/
public int executeGetKey(String sql) throws DBException {
Print.sql(sql);
ResultSet rs = null;
try {
stmt = con.createStatement();
stmt.execute(sql);
rs = stmt.getGeneratedKeys();
int key = 0;
if (rs.next()) {
key = rs.getInt(1);
}
return key;
} catch (SQLException e) {
Print.er(e);
throw new DBException("数据库操作失败:"+sql);
} finally {
boolean isthrow = false;
try {
if (rs != null) {
rs.close();
}
} catch (SQLException e) {
Print.er(e);
isthrow = true;
}
try {
if (rs != null) {
rs.close();
}
} catch (SQLException e) {
Print.er(e);
isthrow = true;
}
if (isthrow) {
throw new DBException("资源释放出错。");
}
}
}
/**
* 开始数据库操作事务
* 设置当前数据库操作类包含的数据库连接对象为手动提交
* @throws DBException 当当前连接已关闭,或数据库访问错误时抛出此异常
*/
public void beginTranscation() throws DBException {
try {
con.setAutoCommit(false);
} catch (SQLException e) {
Print.er(e);
throw new DBException("当前连接已关闭,或数据库访问错误。");
}
}
/**
* 提交数据库操作事务,执行对数据库的操作
* 将调用beginTranscation()方法后的所有操作进行提交
* @throws DBException 当当前连接已关闭、数据库访问错误或自动提交未被关闭时抛出此异常
*/
public void commit() throws DBException {
try {
con.commit();
} catch (SQLException e) {
Print.er(e);
throw new DBException("当前连接已关闭、数据库访问错误或自动提交未被关闭。");
}
}
/**
* 回滚数据库操作事务,执行数据库的操作
* 取消所有未提交的数据库操作
* @throws DBException 当当前连接已关闭、数据库访问错误或自动提交未被关闭时抛出此异常
*/
public void rollback() throws DBException {
try {
con.rollback();
} catch (SQLException e) {
Print.er(e);
throw new DBException("当前连接已关闭、数据库访问错误或自动提交未被关闭。");
}
}
/**
* 释放此数据库底层操作类对象的连接资源
* @throws DBException 当释放资源出现异常时抛出此异常
*/
public void close() throws DBException {
if (con != null) {
try {
con.close();
} catch (SQLException e) {
Print.er(e);
throw new DBException("数据库连接资源释放出错。");
}
}
}
}
dinghun8leech 2010-01-25
  • 打赏
  • 举报
回复
先帮楼主顶下,中午下班再来回答
hydyy 2010-01-23
  • 打赏
  • 举报
回复
1.sql异常通常没法处理,且要做记录也不是在这一层,建议转为runtimeexception向上抛,而现在楼主将其就地截获和打印信息,调用层就几乎无法知晓操作的结果而作出准确的处理。

把所有的异常信息都抛给调用层吗?好吧,我瞅瞅,

2.jdbc的工具类怎么混进了String转Integer 的方法?职责不单一哦。

呵呵,这个可以改,可以改!主要是写一些东西的时候经常用到这个方法就提取出来了,

3.静态变量+静态方法,当多个线程同时调用这个组件的不同方法时,他们使用的很可能是同一个连接,或是没用完就被别的线程关闭,这个设计缺陷直接导致楼主定义的这个组件是个不能用的东西。

那应该怎么去设计呢,希望大侠给出建议!万分感激!!!

4.没有看到有关数据库事务的api定义。

事务我一知半解,而且我也不知道这个程序中我应该在哪里去写事务,帮帮忙吧,谢谢了各位大侠!

5.每个原子方法都开关连接,而实际情况往往一段逻辑要执行好几次数据库操作,或是用事务封装好几个原子操作,解决方法是将连接的开关管理和事务管理从这些方法中抽离。

原子方法的具体定义是什么啊?不懂哎,我真够菜的
hydyy 2010-01-23
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 dinghun8leech 的回复:]
1.sql异常通常没法处理,且要做记录也不是在这一层,建议转为runtimeexception向上抛,而现在楼主将其就地截获和打印信息,调用层就几乎无法知晓操作的结果而作出准确的处理。
2.jdbc的工具类怎么混进了String转Integer 的方法?职责不单一哦。
3.静态变量+静态方法,当多个线程同时调用这个组件的不同方法时,他们使用的很可能是同一个连接,或是没用完就被别的线程关闭,这个设计缺陷直接导致楼主定义的这个组件是个不能用的东西。
4.没有看到有关数据库事务的api定义。
5.每个原子方法都开关连接,而实际情况往往一段逻辑要执行好几次数据库操作,或是用事务封装好几个原子操作,解决方法是将连接的开关管理和事务管理从这些方法中抽离。


[/Quote]

我要达到这个层次该怎么做哦?
hydyy 2010-01-23
  • 打赏
  • 举报
回复
我还是菜鸟哎,谢谢大家的提议,我改改看看,谢谢了!
dinghun8leech 2010-01-21
  • 打赏
  • 举报
回复
好像我提的离楼主想到达到的程度有点远了
dinghun8leech 2010-01-21
  • 打赏
  • 举报
回复
1.sql异常通常没法处理,且要做记录也不是在这一层,建议转为runtimeexception向上抛,而现在楼主将其就地截获和打印信息,调用层就几乎无法知晓操作的结果而作出准确的处理。
2.jdbc的工具类怎么混进了String转Integer 的方法?职责不单一哦。
3.静态变量+静态方法,当多个线程同时调用这个组件的不同方法时,他们使用的很可能是同一个连接,或是没用完就被别的线程关闭,这个设计缺陷直接导致楼主定义的这个组件是个不能用的东西。
4.没有看到有关数据库事务的api定义。
5.每个原子方法都开关连接,而实际情况往往一段逻辑要执行好几次数据库操作,或是用事务封装好几个原子操作,解决方法是将连接的开关管理和事务管理从这些方法中抽离。

不善^ 2010-01-21
  • 打赏
  • 举报
回复
很好了 不用改了
墨水鱼 2010-01-21
  • 打赏
  • 举报
回复
JDBC的工具类,一般我用现成的:apache commons DbUtils,对JDBC做了很好的封装,用起来很方便,而且有人维护
crazylaa 2010-01-21
  • 打赏
  • 举报
回复
路过。
工具类,driverName、url、username、password等等最好从一个配置文件读。省得每次改代码。。
yang677888 2010-01-21
  • 打赏
  • 举报
回复
up
日日新 2010-01-21
  • 打赏
  • 举报
回复
感觉些的查询都没有返回类型,对程序有用吗?
发帖
Java

4.9w+

社区成员

Java相关技术讨论
javaspring bootspring cloud 技术论坛(原bbs)
社区管理员
  • Java相关社区
  • 小虚竹
  • 谙忆
加入社区
帖子事件
创建了帖子
2010-01-20 09:55
社区公告
暂无公告