基本的JDBC以及CRUD/Transaction基本操作

  先上依赖:

        <!-- mysql start -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.38</version>
        </dependency>
        <!-- mysql end -->
        <!-- junit start -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <!-- junit end -->
        <!-- log start -->
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.7</version>
        </dependency>
        <!-- log end -->

基本的JDBCUtil(DBManager):

/**
 * JDBCUtil with mysql-connector-java-5.1.38.jar<br>
 *
 * @author Changjiang.Chen
 *
 */
public class JDBCUtil {

    private static final Log log = LogFactory.getLog(JDBCUtil.class);
    private static String URL;
    private static String USER;
    private static String PASS;
    private static String DRIVER;
    static {
        InputStream is = JDBCUtil.class.getClassLoader().getResourceAsStream("mysql.properties");
        Properties prop = new Properties();
        try {
            prop.load(is);
            URL = prop.getProperty("url");
            USER = prop.getProperty("user");
            PASS = prop.getProperty("password");
            DRIVER = prop.getProperty("driver");
            Class.forName(DRIVER);
        } catch (IOException e) {
            log.error("sth wrong with the property file loading pro", e);
        } catch (ClassNotFoundException e) {
            log.error("JDBCUtil:Class.forName(" + DRIVER + ") error", e);
        }
    }

    /**
     * 建立链接
     *
     * @return
     */
    public static Connection getConnection() {
        Connection conn = null;
        try {
            conn = DriverManager.getConnection(URL, USER, PASS);
        } catch (SQLException e) {
            log.error("JDBCUtil:getConnection() error", e);
        }
        return conn;
    }

    /**
     * 关闭资源
     *
     * @param conn
     * @param st
     * @param rs
     */
    public static void closeMysqlResouces(Connection conn, Statement st, ResultSet rs) {
        try {
            if (rs != null) {
                rs.close();
            }
        } catch (Exception e) {
            log.error("JDBCUtil:rs.close() error", e);
        } finally {
            try {
                if (st != null) {
                    st.close();
                }
            } catch (Exception e2) {
                log.error("JDBCUtil:st.close() error", e2);
            } finally {
                try {
                    if (conn != null) {
                        conn.close();
                    }
                } catch (Exception e3) {
                    log.error("JDBCUtil:conn.close() error", e3);
                }
            }
        }
    }

}

主要是static代码块里处理资源加载与驱动,另外是提供链接和关闭资源的方法。日志使用了Apache的commons-logging。

首先测试一下链接的建立:

public class TestJDBCUtil {
    @Test
    public void testGetConn() {
        Object obj = JDBCUtil.getConnection();
        Assert.assertNotNull(obj);
    }

}

测试CRUD与事务的过程中,会对数据库增删改,要保证这些方法成功执行并不对原先的数据造成影响就要定义不同测试方法的执行顺序,这里采用了@FixMethodOrder(MethodSorters.NAME_ASCENDING)(4.11之后)按照方法名的字母顺序进行升序执行,保证所有方法成功执行后,数据库的数据不会改动:

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Arrays;

import org.junit.Assert;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;

/**
 * @author Changjiang.Chen
 */
/**
 * 重新组合所有测试的执行顺序,按照字母表排序进行执行
 */
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestCRUD {
    private Connection conn;
    private Statement st;
    private ResultSet rs;
    private PreparedStatement pst;

    @Test
    public void testAInsert() {
        try {
            conn = JDBCUtil.getConnection();
            st = conn.createStatement();
            String sql = "INSERT INTO content(id,type,info,num,validtime,label) VALUES(7,‘测试‘,‘测试信息‘,0,10,‘chiq3_test‘)";
            int r = st.executeUpdate(sql);
            JDBCUtil.closeMysqlResouces(conn, st, null);
            Assert.assertEquals(1, r);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtil.closeMysqlResouces(conn, st, null);
        }
    }

    /**
     * 参数传入方式可能引起SQL注入
     *
     * @throws SQLException
     */
    @Test
    public void testCQuery1() throws SQLException {
        try {
            conn = JDBCUtil.getConnection();
            st = conn.createStatement();
            /**
             * param may be affected
             */
            String injectParam = "1";
            String sql = "select type from content where id = " + injectParam;
            rs = st.executeQuery(sql);
            String type = "";
            if (rs.next()) {
                type = rs.getString("type");
            }
            Assert.assertEquals("追剧推送", type);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtil.closeMysqlResouces(conn, st, rs);
        }
    }

    /**
     * preparedStatement对比Statement<br>
     * 如果可以保证sql语句不包含调用者传入的参数,可用后者,否则用前者<br>
     * 大部分情况下都倾向于使用前者,DBUtil,Hibernate都采用了pst
     *
     * @throws SQLException
     */
    @Test
    public void testCQuery2() throws SQLException {
        try {
            conn = JDBCUtil.getConnection();
            /**
             * param could not be affected
             */
            String injectParam = "1";
            String sql = "select type from content where id = ?";
            pst = conn.prepareStatement(sql);
            pst.setString(1, injectParam);
            rs = pst.executeQuery();
            String type = "";
            if (rs.next()) {
                type = rs.getString("type");
            }
            Assert.assertEquals("追剧推送", type);
        } catch (Exception e) {
            e.printStackTrace(); // TODO: handle exception
        } finally {
            JDBCUtil.closeMysqlResouces(conn, pst, rs);
        }
    }

    /**
     * pst应用场景<br>
     * 1.放置sql注入 <br>
     * 2.大数据处理:用IO流处理参数 <br>
     * 3.批处理
     *
     * @throws SQLException
     */
    @Test
    public void testCUpdate() throws SQLException {
        try {
            conn = JDBCUtil.getConnection();
            String injectParam = "7";
            String sql = "UPDATE content SET type = ‘TEST_PUSH‘ WHERE id = ?";
            pst = conn.prepareStatement(sql);
            pst.setString(1, injectParam);
            int r = pst.executeUpdate();
            Assert.assertEquals(1, r);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtil.closeMysqlResouces(conn, pst, rs);
        }
    }

    /**
     * 批量操作
     *
     * @throws SQLException
     */
    @Test
    public void testYBatchUpdate() throws SQLException {
        try {

            conn = JDBCUtil.getConnection();
            String sql = "INSERT INTO content(id,type,info,num,validtime,label) VALUES(?,?,?,?,?,?)";
            pst = conn.prepareStatement(sql);
            for (int i = 10; i < 30; i++) {
                pst.setInt(1, i);
                pst.setString(2, "测试推送");
                pst.setString(3, "测试信息");
                pst.setInt(4, i);
                pst.setInt(5, 10);
                pst.setString(6, "开启测试推送模式");
                pst.addBatch();
            }
            int[] r = pst.executeBatch();
            int[] expected = new int[20];
            for (int i = 0; i < expected.length; i++) {
                expected[i] = 1;
            }
            Assert.assertEquals(Arrays.toString(expected), Arrays.toString(r));
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtil.closeMysqlResouces(conn, pst, null);
        }
    }

    /**
     * Transaction
     */
    @Test
    public void testZTransaction() {
        conn = JDBCUtil.getConnection();
        try {
            conn.setAutoCommit(false);
            st = conn.createStatement();
            int r1 = st.executeUpdate("delete from content where id = 7");
            int r2 = st.executeUpdate("DELETE FROM content WHERE validtime = 10");
            conn.commit();
            Assert.assertEquals(Arrays.toString(new int[] { r1, r2 }), Arrays.toString(new int[] { 1, 20 }));
        } catch (SQLException e) {
            e.printStackTrace();
            try {
                conn.rollback();
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
        } finally {
            JDBCUtil.closeMysqlResouces(conn, st, null);
        }
    }

}
时间: 2024-10-29 05:55:48

基本的JDBC以及CRUD/Transaction基本操作的相关文章

jdbc mysql crud dao模型 sql注入漏洞 jdbc 操作大文件

day17总结 今日内容 l JDBC 1.1 上次课内容总结 SQL语句: 1.外键约束:foreign key * 维护多个表关系! * 用来保证数据完整性! 2.三种关系: * 一对多: * 一个客户可以对应多个订单,一个订单只属于一个客户! * 建表原则: * 在多的一方创建一个字段,作为外键指向一的一方的主键!!! * 多对多: * 一个学生可以选择多个课程,一个课程也可以被多个学生选择! * 建表原则: * 创建第三张表,第三张表中放入两个字段,作为外键分别指向多对多双方的主键! *

HTTP Status 500 - Could not open JDBC Connection for transaction; nested exception is java.lang.NoCl

HTTP Status 500 - Could not open JDBC Connection for transaction; nested exception is java.lang.NoClassDefFoundError: com/mchange/v2/sql/SqlUtils type Exception report message Could not open JDBC Connection for transaction; nested exception is java.l

Could not open JDBC Connection for transaction; nested exception is java.sql.SQLException: Connectio

严重: StandardWrapper.Throwableorg.springframework.transaction.CannotCreateTransactionException: Could not open JDBC Connection for transaction; nested exception is java.sql.SQLException: Connections could not be acquired from the underlying database!

Could not open JDBC Connection for transaction; nested exception is org.apache.commons.dbcp.SQLNestedException: Cannot create PoolableConnectionFactory (Could not create connection to database server.

报错信息:Could not open JDBC Connection for transaction; nested exception is org.apache.commons.dbcp.SQLNestedException: Cannot create PoolableConnectionFactory (Could not create connection to database server.) 问题来源mysql-connecter-java 版本过低 如果你mysql的版本是m

【JDBC】CRUD操作

JDBC的CRUD操作 向数据库中保存记录 修改数据库中的记录 删除数据库中的记录 查询数据库中的记录 保存代码的实现 package demo1; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; import org.junit.Test; public class JDBCDemo3 { @Test /** *

数据库操作,jdbc的CRUD

用Java代码操作数据库,可以用JDBC.首先要加载驱动,之后建立连接,再然后就可以对数据库进行操作. 1.建立连接.此处用的是MySQL数据库 1 public class DBUtil { 2 3 public static String URL = "jdbc:mysql://localhost:3306/JDBCDEmo"; 4 public static String USER = "root"; 5 public static String PASSWO

JavaWeb学习总结-10 JDBC的CRUD

一 常用JDBC API 1 搭建测试环境 MySQL数据库测试脚本 create database jdbcStudy character set utf8 ; use jdbcStudy; create table users( id int primary key, name varchar(40), password varchar(40), email varchar(60), birthday date )ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT

Java JDBC概要总结一(基本操作和SQL注入问题)

JDBC定义: JDBC(Java DataBase Connectivity,java数据库连接)是一种用于执行SQL语句的Java API.JDBC是Java访问数据库的标准规范,可以为不同的关系型数据库提供统一访问,它由一组用Java语言编写的接口和类组成. JDBC规范(掌握四个核心对象): DriverManager类:用于注册驱动(管理控制驱动程序) Connection: 表示与数据库创建的连接 Statement: 操作数据库sql语句的对象 ResultSet: 结果集或一张虚

java之连接数据库之JDBC访问数据库的基本操作

1.将数据库的JDBC驱动加载到classpath中,在基于JavaEE的web应用实际开发过程中通常要把目标数据库产品的JDBC驱动复制到WEB-INF/lib下. 2.加载JDBC驱动并将其注册到DriverManager中. Oracle数据库 Class.forName("oracle.jdbc.driver.oracleDriver"); SQL数据库 Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriv