先上依赖:
<dependency> <groupId>mysqlgroupId> <artifactId>mysql-connector-javaartifactId> <version>5.1.38version> dependency> <dependency> <groupId>junitgroupId> <artifactId>junitartifactId> <version>4.12version> <scope>testscope> dependency> <dependency> <groupId>commons-logginggroupId> <artifactId>commons-loggingartifactId> <version>1.2version> dependency> <dependency> <groupId>org.slf4jgroupId> <artifactId>slf4j-log4j12artifactId> <version>1.7.7version> dependency>
基本的JDBCUtil(DBManager):
/** * JDBCUtil with mysql-connector-java-5.1.38.jar
* * @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之后)按照方法名的字母顺序进行升序执行,保证所有方法成功执行后,数据库的数据不会改动:
package com.changjiang.practise.demo.jdbc; 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.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.FixMethodOrder; import org.junit.Test; import org.junit.runners.MethodSorters; /** * @author Changjiang.Chen */ /** * 重新组合所有测试的执行顺序,按照字母表排序进行执行 */ @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestCRUD { private static Connection conn; private static Statement st; private static ResultSet rs; private static PreparedStatement pst; @BeforeClass public static void getConn() { conn = JDBCUtil.getConnection(); } @AfterClass public static void close() { JDBCUtil.closeMysqlResouces(conn, st, null); } @Test public void testAInsert() { try { 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); Assert.assertEquals(1, r); } catch (Exception e) { e.printStackTrace(); } } /** * 参数传入方式可能引起SQL注入 * * @throws SQLException */ @Test public void testCQuery1() { 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(); } } /** * preparedStatement对比Statement
* 如果可以保证sql语句不包含调用者传入的参数,可用后者,否则用前者
* 大部分情况下都倾向于使用前者,DBUtil,Hibernate都采用了pst * * @throws SQLException */ @Test public void testCQuery2() { 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(); } } /** * pst应用场景
* 1.放置sql注入
* 2.大数据处理:用IO流处理参数
* 3.批处理 * * @throws SQLException */ @Test public void testCUpdate() { 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(); } } /** * 批量操作 * * @throws SQLException */ @Test public void testYBatchUpdate() { 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(); } } /** * 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(); } } } }