1.Java程序连接数据库的四种方法
1 JDBC-ODBC桥和ODBC驱动程序--在这种方式下,这是一个本地解决方案,因为ODBC驱动程序和桥代码必须出现在用户的每台机器中。从根本上说这是一个临时解决方案。
2 本机代码和Java驱动程序--它用另一个本地解决方案(该平台上的Java可调用的本机代码)取代 ODBC 和 JDBC-ODBC 桥。
3 JDBC网络的纯Java驱动程序--由Java驱动程序翻译的JDBC形成传送给服务器的独立协议。然后,服务器可连接任何数量的数据库。这种方法使您可能从客户机Applet中调用服务器,并将结果返回到您的Applet。在这种情况下,中间件软件提供商可提供服务器。
4 本机协议Java驱动程序-- Java驱动程序直接转换为该数据库的协议并进行调用。这种方法也可以通过网络使用,而且可以在Web浏览器的Applet中显示结果。在这种情况下,每个数据库厂商将提供驱动程序。
2.使用连接池和语句池 提高 Oracle 驱动的 JDBC 程序的性能
使用诸如连接池和语句池等池技术可以显著提高数据库密集型应用程序的性能,因为这样可以实现对象重用,而无需花费时间和资源重新创建对象。
如果应用程序与数据库频繁交互并且经常使用相同的参数重新建立连接,那么重用表示应用程序使 用的物理数据库连接的数据库连接对象可显著提高性能。反之,如果应用程序与其基础数据库很少连接,您不会因使用连接池获益。实际上,如果池的设置(例如,允许的最大或最小连接数限制)针对特定应用程序进行了优化,许多数据库密集型应用程序都可以因使用连接池获益。
与连接池一样,语句池也是用于提高应用程序性能的技术。通过在应用程序运行期间多次执行语句池,可以进一步提高性能。然而,我们应该意识到语句池并不是解决性能问题的灵丹妙药。如果对每条语句进行缓存而不辨别其在程序中执行的次数,则不可能获得任何性能改进。实际上,由于将语句放入缓存并保存在缓存中将产生开销,因此对在程序执行期间仅执行一次的语句进行缓存将降低性能。
3.准备好驱动和连接池
准备数据库驱动:
由于安装的数据库是oracle10g个人版,这里下载的是oracle10g瘦版JDBC(相当于前面Java数据库连接方式的第四种)地址是:
http://www.oracle.com/technology/software/tech/java/sqlj_jdbc/htdocs/jdbc_10201.html
准备数据库连接池
DBCP是apache的数据库连接池项目,其依赖于commons-pool 下载地址是:
http://commons.apache.org/dbcp/download_dbcp.cgi
http://commons.apache.org/pool/downloads.html
4.初始化连接代码
Java代码
importorg.apache.commons.dbcp.BasicDataSource;
importjava.sql.SQLException;
importjava.sql.Connection;
/**
* 使用DBCP 1.4 做数据库连接池 DBCP1.4支持JDK1.6
*/
publicclassDbcpextendsDBConnection
{
privateBasicDataSource dataSource =null;
// 初始化数据连接
publicvoidinitDataSource()
{
if(dataSource !=null)
{
try
{
dataSource.close();
}
catch(Exception e)
{
e.printStackTrace();
}
dataSource =null;
}
try
{
dataSource =newBasicDataSource();
dataSource.setDriverClassName("oracle.jdbc.driver.OracleDriver");
dataSource.setUrl("jdbc:oracle:thin:@127.0.0.1:1521:XE");
dataSource.setUsername("name");
dataSource.setPassword("password");
dataSource.setMaxActive(20);
dataSource.setMaxIdle(10);
}
catch(Exception e)
{
e.printStackTrace();
}
}
// 从连接池中获得数据库连接
publicConnection getConnection()throwsSQLException
{
if(dataSource !=null)
{
returndataSource.getConnection();
}
else
{
thrownewSQLException("数据源不存在");
}
}
}
import org.apache.commons.dbcp.BasicDataSource;
import java.sql.SQLException;
import java.sql.Connection;
/**
* 使用DBCP 1.4 做数据库连接池 DBCP1.4支持JDK1.6
*/
public class Dbcp extends DBConnection
{
private BasicDataSource dataSource = null;
// 初始化数据连接
public void initDataSource()
{
if (dataSource != null)
{
try
{
dataSource.close();
}
catch (Exception e)
{
e.printStackTrace();
}
dataSource = null;
}
try
{
dataSource = new BasicDataSource();
dataSource.setDriverClassName("oracle.jdbc.driver.OracleDriver");
dataSource.setUrl("jdbc:oracle:thin:@127.0.0.1:1521:XE");
dataSource.setUsername("name");
dataSource.setPassword("password");
dataSource.setMaxActive(20);
dataSource.setMaxIdle(10);
}
catch (Exception e)
{
e.printStackTrace();
}
}
// 从连接池中获得数据库连接
public Connection getConnection() throws SQLException
{
if (dataSource != null)
{
return dataSource.getConnection();
}
else
{
throw new SQLException("数据源不存在");
}
}
}
5.测试代码
Java代码
/**
* Java调用Oracle的存储过程
*/
staticvoidcallableSatement()
{
Connection con =null;
CallableStatement callStmt =null;
try
{
con = DBService.getInstance().getConnection();
System.out.println("创建连接成功");
// 调用Oralce的存储过程luketest(?)
callStmt = con.prepareCall("BEGIN luketest(?); END;");
callStmt.setInt(1,682);
System.out.println("调用Oralce的存储过程");
callStmt.execute();/* 如果这里阻塞说明上面的store procedure正被独占访问/或者事务没有提交 */
System.out.println("存储过程执行成功");
}
catch(SQLException e)
{
e.printStackTrace();
}
finally
{
try
{
if(callStmt !=null)
callStmt.close();
if(con !=null)
con.close();
}
catch(SQLException ex)
{
ex.printStackTrace();
}
}
}
/**
* 执行预编译SQL语句
*/
staticvoidpreparedStatement()
{
// 表示预编译的 SQL 语句的对象。
// SQL 语句被预编译并且存储在 PreparedStatement 对象中。然后可以使用此对象高效地多次执行该语句。
Connection conn =null;
PreparedStatement prepStmt =null;
ResultSet set =null;
try
{
conn = DBService.getInstance().getConnection();
prepStmt = conn.prepareStatement("select * from account_info where account_id=5000007");
set = prepStmt.executeQuery();
while(set.next())
{
System.out.print(" "+ set.getInt("account_id"));
System.out.print(" "+ set.getString("account_name"));
System.out.println(" "+ set.getString("account_password"));
}
}
catch(SQLException e)
{
e.printStackTrace();
}
finally
{
try
{
if(set !=null)
set.close();
if(prepStmt !=null)
prepStmt.close();
if(conn !=null)
conn.close();
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
/**
* 执行SQL
*/
staticvoidstatement()
{
// 执行大量的查询语句
for(inti =0; i <100; i++)
{
Connection conn =null;
Statement stmt =null;
ResultSet set =null;
try
{
conn = DBService.getInstance().getConnection();
stmt = conn.createStatement();
set = stmt.executeQuery("select * from account_info where account_id=5000007");
while(set.next())
{
System.out.print(i +" "+ set.getInt("account_id"));
System.out.print(" "+ set.getString("account_name"));
System.out.println(" "+ set.getString("account_password"));
}
}
catch(SQLException e)
{
e.printStackTrace();
}
finally
{
try
{
if(set !=null)
set.close();
if(stmt !=null)
stmt.close();
if(conn !=null)
conn.close();
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
}
/**
* Java调用Oracle的存储过程
*/
static void callableSatement()
{
Connection con = null;
CallableStatement callStmt = null;
try
{
con = DBService.getInstance().getConnection();
System.out.println("创建连接成功");
// 调用Oralce的存储过程luketest(?)
callStmt = con.prepareCall("BEGIN luketest(?); END;");
callStmt.setInt(1, 682);
System.out.println("调用Oralce的存储过程");
callStmt.execute(); /* 如果这里阻塞说明上面的store procedure正被独占访问/或者事务没有提交 */
System.out.println("存储过程执行成功");
}
catch (SQLException e)
{
e.printStackTrace();
}
finally
{
try
{
if (callStmt != null)
callStmt.close();
if (con != null)
con.close();
}
catch (SQLException ex)
{
ex.printStackTrace();
}
}
}
/**
* 执行预编译SQL语句
*/
static void preparedStatement()
{
// 表示预编译的 SQL 语句的对象。
// SQL 语句被预编译并且存储在 PreparedStatement 对象中。然后可以使用此对象高效地多次执行该语句。
Connection conn = null;
PreparedStatement prepStmt = null;
ResultSet set = null;
try
{
conn = DBService.getInstance().getConnection();
prepStmt = conn.prepareStatement("select * from account_info where account_id=5000007");
set = prepStmt.executeQuery();
while (set.next())
{
System.out.print(" " + set.getInt("account_id"));
System.out.print(" " + set.getString("account_name"));
System.out.println(" " + set.getString("account_password"));
}
}
catch (SQLException e)
{
e.printStackTrace();
}
finally
{
try
{
if (set != null)
set.close();
if (prepStmt != null)
prepStmt.close();
if (conn != null)
conn.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
/**
* 执行SQL
*/
static void statement()
{
// 执行大量的查询语句
for (int i = 0; i < 100; i++)
{
Connection conn = null;
Statement stmt = null;
ResultSet set = null;
try
{
conn = DBService.getInstance().getConnection();
stmt = conn.createStatement();
set = stmt.executeQuery("select * from account_info where account_id=5000007");
while (set.next())
{
System.out.print(i + " " + set.getInt("account_id"));
System.out.print(" " + set.getString("account_name"));
System.out.println(" " + set.getString("account_password"));
}
}
catch (SQLException e)
{
e.printStackTrace();
}
finally
{
try
{
if (set != null)
set.close();
if (stmt != null)
stmt.close();
if (conn != null)
conn.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
}
6.分析效率
Java中对于执行SQL语句接口设计如下:
java.sql.Statement
java.sql.PreparedStatement extends Statement
java.sql.CallableStatement extends PreparedStatement
为了进一步了解用法,下面直接复制了JDK的文档,JDK文档描述如下:
public interface Statement
用于执行静态 SQL 语句并返回它所生成结果的对象。
在默认情况下,同一时间每个 Statement 对象在只能打开一个 ResultSet 对象。因此,如果读取一个 ResultSet 对象与读取另一个交叉,则这两个对象必须是由不同的 Statement 对象生成的。如果存在某个语句的打开的当前 ResultSet 对象,则 Statement 接口中的所有执行方法都会隐式关闭它。
优势:在执行单独的一条简单的SQL效率最高。
public interface PreparedStatement extends Statement
表示预编译的 SQL 语句的对象。
SQL 语句被预编译并且存储在 PreparedStatement 对象中。然后可以使用此对象高效地多次执行该语句。
在以下设置参数的示例中,con 表示一个活动连接:
PreparedStatement pstmt = con.prepareStatement("update employees set salary=? where id =? ");
pstmt.setBigDecimal(1, 153833.00)
pstmt.setInt(2, 110592)
pstmt.executeUpdate();
优势:可以显著提高执行多条语句相同而参数不同的SQL的效率。
在多次执行同样SQL语句而参数不同的情况下,可以使用setXXX()方法来动态的改变参数,而不用像Statement那样每次都要生成新的SQL语句。
public interface CallableStatement extends PreparedStatement
用于执行 SQL 存储过程的接口。JDBC API 提供了一个存储过程 SQL 转义语法,该语法允许对所有 RDBMS 使用标准方式调用存储过程。
优势:适合于对不同数据表的频繁访问并且逻辑操作复杂的情况。java只需要简单的调用一下数据库中定义好的存储过程并传递相应参数,剩下的操作都有数据库自己去执行这样减少Java与数据库之间的交互次数。
参考网址
www.ibm.com/developerworks/cn/java
www.oracle.com/cn/
JDK6.0中文文档