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环境)

 

时间: 2024-10-05 20:32:27

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

java web实现增删改查后,应该学习哪些高级技术?

问题描述 java web实现增删改查后,应该学习哪些高级技术? 做了个小项目,实现了curd,想继续往缓存,并发,负载高级深入,请推荐一个详细的高级技术路线?最好有书 解决方案 javaweb深入浅出,不过这个方向研究,主要还是在公司里学的会更实用些 解决方案二: 多线程,Socket,I/O JSP.EL.JSTL,AJAX JavaScript,jQuery JSON,XML EJB(可忽略) 各种框架 ......太多了 解决方案三: 多线程,Socket,I/O JSP.EL.JSTL

简单用户登录和数据增删改查

问题描述 简单用户登录和数据增删改查 <%@page pageEncoding=""utf-8"" isELIgnored=""false""%><%@taglib uri=""http://java.sun.com/jsp/jstl/core"" prefix=""c""%><%@taglib uri="&

java 数组的增删改查,用数组的方法实现

问题描述 java 数组的增删改查,用数组的方法实现 对一维数组进行增删该查:int[] num=new int[10]要求:用方法实现1输入10个整数存入数组2删除指定位置上的数3修改指定位置上的数4查找某个数的位置(下标)5查找最大值6查找最小值7去掉一个最大值和一个最小值,求平均值. 跪求各位大神能给小弟一个立案...好人一生平安!! 解决方案 http://blog.csdn.net/myoral/article/details/7445675 解决方案二: java 对象数组(增删改查

C#操作Excel数据增删改查示例_实用技巧

C#操作Excel数据增删改查. 首先创建ExcelDB.xlsx文件,并添加两张工作表. 工作表1: UserInfo表,字段:UserId.UserName.Age.Address.CreateTime. 工作表2: Order表,字段:OrderNo.ProductName.Quantity.Money.SaleDate. 1.创建ExcelHelper.cs类,Excel文件处理类 复制代码 代码如下: using System; using System.Collections.Gen

C#在winform中实现数据增删改查等功能_C#教程

winform中利用ado.net实现对单表的增删改查的详细例子,具体如下: 1.前言: 运行环境:VS2013+SQL2008+Windows10 程序界面预览: 使用的主要控件:dataGridview和menuStrip等.  2.功能具体介绍: 1.首先,我们要先实现基本的数据操作,增删改查这几个操作. (1)先定义一个数据库操作的公共类: using System; using System.Collections.Generic; using System.Linq; using S

HDFS Java代码进行增删改查

提醒:如果要在idear或者eclipse等IDE下运行就必须在HDFS上给你所使用的目录分配权限给windows下的用户,为了方便起见建议给所有权限777 创建目录命令 hdfs dfs -mkdir myproject 分配权限命令 hdfs dfs -chmod 777 myproject HDFS增删改查工具类 package hdfs; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.Fi

Dapper逆天入门~强类型,动态类型,多映射,多返回值,增删改查+存储过程+事物案例演示

Dapper的牛逼就不扯蛋了,答应群友做个入门Demo的,现有园友需要,那么公开分享一下: 完整Demo:http://pan.baidu.com/s/1i3TcEzj 注 意 事 项:http://www.cnblogs.com/dunitian/p/5221058.html 平台之大势何人能挡? 带着你的Net飞奔吧! http://www.cnblogs.com/dunitian/p/4822808.html#skill 先安装一下Dapper(建议用nuget包来管理) 连接字符串: s

Yii 2.0框架数据增删改查的操作

新增操作: $model = newUser(); $model->username = 'username'; $model->age      = '20'; $model->insert(); 查询操作: User::find()->all();    此方法返回所有数据: User::findOne($id);   此方法返回 主键 id=1  的一条数据: User::find()->where(['name' => 'username'])->one(

java除了增删改查还能干什么?

问题描述 java除了写增删改查,还能干什么啊?自己写了多半年的增删改查,感觉java除了写增删改查也写不出什么了,现在又要找工作,感觉很迷惑.求解惑!! 解决方案 换个工作吧,增删改查也就是最基础的东西,编程最大的价值在于实现有价值的思想:)跟语言没有关系,用java比较多只是因为java学习和使用相对简单解决方案二:现在Java的需求这么火爆,说明它可以做很多事情,至于你只知道这点,说明你的见识还很短浅.送你一句话:路漫漫而修远,吾将上下而求索.解决方案三: 解决方案四:增删改查是数据库的操