java学习:数据增删改查、存储过程调用及事务处理

java

为了方便,先定义二个常量:

package jmyang.utils;

public class ConstDefine {

/**

* WebLogic服务器地址

*/

public static final String WebLogicServerUrl = "t3://localhost:7001";

/**

* WebLogic JNDI上下文字符串

*/

public static final String WebLogicINDIContextFactory = "weblogic.jndi.WLInitialContextFactory";

}

 并把创建连接,关闭连接等基本方法 封装一下:

package jmyang.utils;

import javax.naming.Context;

import java.util.Hashtable;

import javax.naming.InitialContext;

import jmyang.utils.ConstDefine;

import javax.naming.NamingException;

import java.sql.Connection;

import javax.sql.DataSource;

import java.sql.SQLException;

import java.sql.Statement;

import java.sql.ResultSet;

/**

*

* <p>Title: JDBC工具类</p>

* <p>Description: 封装JDBC常用的基本操作</p>

* <p>Copyright: Copyright (c) 2012</p>

* <p>Company: yjmyzz.cnblogs.com</p>

* @author: yjmyzz@126.com

* @version 1.0

*/

public class JDBC {

private static Context ctx = null;

/**

* 获取weblogic上下文

* @return Context

*/

public static Context getContext() {

Hashtable ht = new Hashtable();

ht.put(Context.INITIAL_CONTEXT_FACTORY,

ConstDefine.WebLogicINDIContextFactory);

ht.put(Context.PROVIDER_URL, ConstDefine.WebLogicServerUrl);

try {

ctx = new InitialContext(ht);

} catch (NamingException e) {

e.printStackTrace();

return null;

}

return ctx;

}

/**

* 获取DataSource

* @param dsName String

* @return DataSource

*/

public static DataSource getDataSource(String dsName) {

if (ctx == null) {

ctx = getContext();

}

if (ctx == null || dsName == null) {

return null;

}

DataSource ds = null;

try {

ds = (javax.sql.DataSource) ctx.lookup(dsName);

} catch (NamingException e) {

e.printStackTrace();

return null;

}

return ds;

}

/**

* 获取连接对象

* @return Connection

*/

public static Connection getConnection(DataSource ds) {

if (ds == null) {

return null;

}

Connection conn = null;

try {

conn = ds.getConnection();

} catch (SQLException e) {

e.printStackTrace();

return null;

}

return conn;

}

/**

* 获取连接对象

* @param dsName String

* @param autoCommitTransaction boolean 是否自动提交事务

* @return Connection

*/

public static Connection getConnection(String dsName,

boolean autoCommitTransaction) {

if (dsName == null) {

return null;

}

DataSource ds = getDataSource(dsName);

if (ds == null) {

return null;

}

Connection conn = null;

try {

conn = ds.getConnection();

conn.setAutoCommit(autoCommitTransaction);

} catch (SQLException e) {

e.printStackTrace();

return null;

}

return conn;

}

/**

* 获取连接对象(自动提交事务)

* @param dsName String

* @return Connection

*/

public static Connection getConnection(String dsName) {

return getConnection(dsName, true);

}

/**

* 关闭连接

* @param conn Connection

* @param autoCommitTransaction boolean 是否自动提交事务

*/

public static void closeConnection(Connection conn,

boolean autoCommitTransaction) {

if (conn != null) {

if (autoCommitTransaction) {

//如果自动提交事务

try {

conn.commit();

} catch (SQLException e) {

e.printStackTrace();

try {

conn.rollback();

} catch (SQLException e2) {

e2.printStackTrace();

}

}

} else {

//否则回滚

try {

conn.rollback();

} catch (SQLException e2) {

e2.printStackTrace();

}

}

//关闭连接

try {

conn.close();

} catch (SQLException e) {

e.printStackTrace();

}

}

}

/**

* 关闭数据连接(并自动提交事务)

* @param conn Connection

*/

public static void closeConnection(Connection conn) {

closeConnection(conn, true);

}

/**

* 关闭查询

* @param statement Statement

*/

public static void closeStatement(Statement statement) {

if (statement != null) {

try {

statement.close();

} catch (SQLException e) {

e.printStackTrace();

}

}

}

/**

* 执行sql查询

* @param dsName string

* @param sql string

* @return ResultSet

*/

public static ResultSet executeQuery(String dsName, String sql) {

Connection conn = getConnection(dsName);

if (conn == null) {

System.out.println("数据库连接失败!");

return null;

}

ResultSet resultSet = null;

Statement cmd = null;

try {

cmd = conn.createStatement();

resultSet = cmd.executeQuery(sql);

} catch (SQLException e) {

e.printStackTrace();

} finally {

closeStatement(cmd);

closeConnection(conn);

}

return resultSet;

}

/**

* 执行sql更新/插入/删除

* @param dsName String

* @param sql String

* @return 影响的行数

*/

public static int executeUpdate(String dsName, String sql) {

int result = 0;

Connection conn = JDBC.getConnection(dsName);

Statement cmd = null;

try {

cmd = conn.createStatement();

result = cmd.executeUpdate(sql);

} catch (SQLException e) {

e.printStackTrace();

} finally {

JDBC.closeStatement(cmd);

JDBC.closeConnection(conn);

}

return result;

}

/**

* 执行sql语句(注:并不自动关闭连接,需要在开发人员调用完成后,手动关闭conn对象)

* @param conn Connection

* @param sql String

* @return int

*/

public static int executeUpdate(Connection conn, String sql) {

int result = 0;

Statement cmd = null;

try {

cmd = conn.createStatement();

result = cmd.executeUpdate(sql);

} catch (SQLException e) {

e.printStackTrace();

try {

conn.rollback();//如果失败,尝试回滚

} catch (SQLException e2) {

e2.printStackTrace();

}

} finally {

JDBC.closeStatement(cmd);

}

return result;

}

}

 下面的代码,演示了基础的增、删、改、查以及事务的使用

package jmyang.jndi;

import jmyang.utils.*;

import javax.sql.*;

import java.sql.*;

public class JDBCTest {

static final String WeblogicDataSoueceName = "oracleXE";

/**

* 查询示例

*/

public static void QueryDemo() {

ResultSet resultSet = JDBC.executeQuery(WeblogicDataSoueceName,

"Select * from EMP");

try {

while (resultSet.next()) {

System.out.println("EMPNO=" + resultSet.getString("EMPNO") + ",ENAME=" + resultSet.getString("ENAME"));

}

} catch (SQLException e) {

e.printStackTrace();

}

}

/**

* 新增记录示例

*/

public static void InsertDemo() {

if (JDBC.executeUpdate(WeblogicDataSoueceName,

"INSERT INTO DEPT VALUES('50','市场部','上海')") > 0) {

System.out.println("insert 记录成功!");

} else {

System.out.println("insert 记录失败!");

}

}

/**

* 删除示例

*/

public static void DeleteDemo() {

if (JDBC.executeUpdate(WeblogicDataSoueceName,

"Delete From Dept Where DeptNo='50'") > 0) {

System.out.println("delete 记录成功!");

} else {

System.out.println("delete 记录失败!");

}

}

/**

* 更新示例

*/

public static void UpdateDemo() {

if (JDBC.executeUpdate(WeblogicDataSoueceName,

"Update Dept Set LOC='中国上海' Where DeptNo='50'") >

0) {

System.out.println("update 记录成功!");

} else {

System.out.println("update 记录失败!");

}

}

/**

* 简单事务示例

*/

public static void transactionDemo() {

Connection conn = JDBC.getConnection(WeblogicDataSoueceName, false);//设置不自动提交事务

try {

JDBC.executeUpdate(conn, "INSERT INTO DEPT VALUES('50','市场部','上海')");

JDBC.executeUpdate(conn, "INSERT INTO DEPT VALUES('60','技术部')"); //这里故意少写一个字段的值,insert时失败,导致事务回滚

} catch (Exception e) {

e.printStackTrace();

} finally {

JDBC.closeConnection(conn);

}

}

}

从上面的代码可以看出:对于日常的数据库操作,用Statement对象的executeQuery(),executeUpate()以及Connection.setAutoCommit()基本上就满足增、删、改、查需求,以及事务的调用

下面来看看存储过程的调用:

先在oracle中创建一个示例存储过程

create or replace procedure up_getENameByNo(empno in varchar2,

eName out varchar2) is

begin

select t.ename

into eName

from emp t

where empno = empno

and rownum = 1;

end up_getENameByNo;

 很简单,根据empno获取emp表中的ename字段值,下面是java的调用代码:

    /**

* 存储过程调用示例

*/

public static void procedureDemo(){

Connection conn = JDBC.getConnection(WeblogicDataSoueceName);

try{

CallableStatement statement= conn.prepareCall("{call up_getENameByNo(?,?)}");

statement.setString(1,"7839");//设置第一个参数值为7839

statement.registerOutParameter(2,Types.VARCHAR);//注册第二个参数为返回参数

statement.execute();

System.out.println(statement.getString(2));//显示返回参数

}

catch(SQLException e){

e.printStackTrace();

}

finally{

JDBC.closeConnection(conn);

}

}

 这里我们又用到了一个新对象:CallableStatement,存储过程的调用就是通过它来完成的。

最后再来看看SQL注入及参数化问题,众所周知,用SQL拼接的方式处理查询参数,默认情况下有安全问题,下面的代码演示了这一点:

    public static void queryDemo() {

String deptNo = "'30' or 1=1";

ResultSet resultSet = JDBC.executeQuery(WeblogicDataSoueceName,

"Select * from EMP where deptno=" + deptNo + " order by ename desc");

String empNo, eName;

try {

while (resultSet.next()) {

empNo = resultSet.getString("EMPNO");

eName = resultSet.getString("eName");

deptNo = resultSet.getString("DeptNo");

System.out.println("EMPNO=" + empNo + " , ENAME=" + eName + " , DEPTNO=" + deptNo);

}

} catch (SQLException e) {

e.printStackTrace();

}

}

 代码本意是要查出DeptNo=30的记录,但是最终却查出了所有记录!(特别是该查询参数值是从前端界面上客户输入时,这个问题显得很严重了)。当然java也有相应的策略:那就是尽量使用PreparedStatement,以参数化的方式处理,下面是示例代码:

/**

* 查询示例(使用PreparedStatement)

*/

public static void queryDemoP() {

Connection conn = null;

PreparedStatement statement = null;

String empNo, eName,deptNo;

try {

conn = JDBC.getConnection(WeblogicDataSoueceName);

statement = conn.prepareStatement(

"select * from emp where deptno=? order by ename desc");//注意这里的?号

statement.setString(1, "'30' or 1=1");//设置第一个参数的值

ResultSet resultSet = statement.executeQuery();

while (resultSet.next()) {

empNo = resultSet.getString("EMPNO");

eName = resultSet.getString("eName");

deptNo = resultSet.getString("DeptNo");

System.out.println("EMPNO=" + empNo + " , ENAME=" + eName + " , DEPTNO=" + deptNo);

}

} catch (SQLException e) {

e.printStackTrace();

} finally {

JDBC.closeStatement(statement);

JDBC.closeConnection(conn);

}

}

运行时会报错:

java.sql.SQLException: ORA-01722: 无效数字

显然,statement.setString(1, "'30' or 1=1");的注入并未成功,所以推荐大家尽量使用PreparedStatement,而且从效率上讲PreparedStatement 也高于Statement (很多网上的文章,包括介绍jdbc的书籍是这么讲的,但是我实际测试的结果,貌似性能相差不大-jdk1.5+jbuilder2006+oracle 11g express + winxp环境)

以上是 java学习:数据增删改查、存储过程调用及事务处理 的全部内容, 来源链接: utcz.com/z/390991.html

回到顶部