由於數據庫鏈接對象的建立比較消耗性能,因此能夠在應用程序啓動時就在內存中開闢一片空間(集合)存放多個數據庫鏈接對象,後面須要鏈接時直接從該空間中取而不用新建立;使用完畢後歸還鏈接(將鏈接從新放回空間),確保鏈接對象能重複使用。java
package com.zze.test; public interface IWaiter { void service(); }
package com.zze.test; public class Waiter implements IWaiter{ public void service(){ System.out.println("正在服務"); } }
package com.zze.test; public class WaiterWrapper implements IWaiter { public WaiterWrapper(Waiter waiter) { this.waiter = waiter; } private Waiter waiter; @Override public void service() { System.out.println("服務以前"); waiter.service(); System.out.println("服務以後"); } }
@Test public void wrapperTest() { IWaiter waiter = new WaiterWrapper(new Waiter()); waiter.service(); /* 服務以前 正在服務 服務以後 */ }
一般一個鏈接使用完畢後咱們要調用它的 close 方法關閉它,而這裏咱們是要讓它歸還到鏈接池,這裏咱們能夠經過裝飾者模式修改它的 close 方法實現:mysql
package com.zze.util; import java.sql.*; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.concurrent.Executor; public class ConnectionWrap implements Connection { private Connection connection = null; private List<Connection> connectionList; /** * 構造函數 * @param connection 要裝飾的鏈接 * @param connectionList 鏈接池儲存鏈接的集合 */ public ConnectionWrap(Connection connection, List<Connection> connectionList) { super(); this.connection = connection; this.connectionList = connectionList; } @Override public void close() throws SQLException { connectionList.add(connection); } @Override public Statement createStatement() throws SQLException { return connection.createStatement(); } @Override public PreparedStatement prepareStatement(String sql) throws SQLException { return connection.prepareStatement(sql); } @Override public CallableStatement prepareCall(String sql) throws SQLException { return connection.prepareCall(sql); } @Override public String nativeSQL(String sql) throws SQLException { return connection.nativeSQL(sql); } @Override public void setAutoCommit(boolean autoCommit) throws SQLException { connection.setAutoCommit(autoCommit); } @Override public boolean getAutoCommit() throws SQLException { return connection.getAutoCommit(); } @Override public void commit() throws SQLException { connection.commit(); } @Override public void rollback() throws SQLException { connection.rollback(); } @Override public boolean isClosed() throws SQLException { return connection.isClosed(); } @Override public DatabaseMetaData getMetaData() throws SQLException { return connection.getMetaData(); } @Override public void setReadOnly(boolean readOnly) throws SQLException { connection.setReadOnly(readOnly); } @Override public boolean isReadOnly() throws SQLException { return connection.isReadOnly(); } @Override public void setCatalog(String catalog) throws SQLException { connection.setCatalog(catalog); } @Override public String getCatalog() throws SQLException { return connection.getCatalog(); } @Override public void setTransactionIsolation(int level) throws SQLException { connection.setTransactionIsolation(level); } @Override public int getTransactionIsolation() throws SQLException { return connection.getTransactionIsolation(); } @Override public SQLWarning getWarnings() throws SQLException { return connection.getWarnings(); } @Override public void clearWarnings() throws SQLException { connection.clearWarnings(); } @Override public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException { return connection.createStatement(resultSetType, resultSetConcurrency); } @Override public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { return connection.prepareStatement(sql, resultSetType, resultSetConcurrency); } @Override public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { return connection.prepareCall(sql,resultSetType,resultSetConcurrency); } @Override public Map<String, Class<?>> getTypeMap() throws SQLException { return connection.getTypeMap(); } @Override public void setTypeMap(Map<String, Class<?>> map) throws SQLException { connection.setTypeMap(map); } @Override public void setHoldability(int holdability) throws SQLException { connection.setHoldability(holdability); } @Override public int getHoldability() throws SQLException { return connection.getHoldability(); } @Override public Savepoint setSavepoint() throws SQLException { return connection.setSavepoint(); } @Override public Savepoint setSavepoint(String name) throws SQLException { return connection.setSavepoint(name); } @Override public void rollback(Savepoint savepoint) throws SQLException { connection.rollback(); } @Override public void releaseSavepoint(Savepoint savepoint) throws SQLException { connection.releaseSavepoint(savepoint); } @Override public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { return connection.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability); } @Override public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { return connection.prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability); } @Override public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { return connection.prepareCall(sql,resultSetType,resultSetConcurrency,resultSetHoldability); } @Override public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException { return connection.prepareStatement(sql, autoGeneratedKeys); } @Override public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException { return connection.prepareStatement(sql, columnIndexes); } @Override public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException { return connection.prepareStatement(sql, columnNames); } @Override public Clob createClob() throws SQLException { return connection.createClob(); } @Override public Blob createBlob() throws SQLException { return connection.createBlob(); } @Override public NClob createNClob() throws SQLException { return connection.createNClob(); } @Override public SQLXML createSQLXML() throws SQLException { return connection.createSQLXML(); } @Override public boolean isValid(int timeout) throws SQLException { return connection.isValid(timeout); } @Override public void setClientInfo(String name, String value) throws SQLClientInfoException { connection.setClientInfo(name,value); } @Override public void setClientInfo(Properties properties) throws SQLClientInfoException { connection.setClientInfo(properties); } @Override public String getClientInfo(String name) throws SQLException { return connection.getClientInfo(name); } @Override public Properties getClientInfo() throws SQLException { return connection.getClientInfo(); } @Override public Array createArrayOf(String typeName, Object[] elements) throws SQLException { return connection.createArrayOf(typeName,elements); } @Override public Struct createStruct(String typeName, Object[] attributes) throws SQLException { return connection.createStruct(typeName,attributes); } @Override public void setSchema(String schema) throws SQLException { connection.setSchema(schema); } @Override public String getSchema() throws SQLException { return connection.getSchema(); } @Override public void abort(Executor executor) throws SQLException { connection.abort(executor); } @Override public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException { connection.setNetworkTimeout(executor,milliseconds); } @Override public int getNetworkTimeout() throws SQLException { return connection.getNetworkTimeout(); } @Override public <T> T unwrap(Class<T> iface) throws SQLException { return connection.unwrap(iface); } @Override public boolean isWrapperFor(Class<?> iface) throws SQLException { return connection.isWrapperFor(iface); } }
對於鏈接池,java 已經給咱們提供了接口 javax.sql.DataSource ,咱們要作的就是實現它:sql
package com.zze.util; import javax.sql.DataSource; import java.io.PrintWriter; import java.sql.Connection; import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; import java.util.ArrayList; import java.util.List; import java.util.logging.Logger; public class MyDataSource implements DataSource { // 定義一個集合用來存放鏈接 private List<Connection> connections = new ArrayList<>(); public MyDataSource() { // 初始化 10 個鏈接 for (int i = 0; i < 10; i++) { connections.add(JDBCUtil.getConnection()); } } /** * 獲取鏈接 * * @return 從鏈接池取出的鏈接 */ @Override public Connection getConnection() throws SQLException { // 取鏈接但集合沒有鏈接時,新添加 5 個鏈接 if (connections.size() == 0) { for (int i = 0; i < 5; i++) { connections.add(JDBCUtil.getConnection()); } } Connection connection = connections.remove(0); // 返回咱們定義的鏈接包裝類 ConnectionWrap connectionWrap = new ConnectionWrap(connection, connections); return connectionWrap; } @Override public Connection getConnection(String username, String password) throws SQLException { return null; } @Override public <T> T unwrap(Class<T> iface) throws SQLException { return null; } @Override public boolean isWrapperFor(Class<?> iface) throws SQLException { return false; } @Override public PrintWriter getLogWriter() throws SQLException { return null; } @Override public void setLogWriter(PrintWriter out) throws SQLException { } @Override public void setLoginTimeout(int seconds) throws SQLException { } @Override public int getLoginTimeout() throws SQLException { return 0; } @Override public Logger getParentLogger() throws SQLFeatureNotSupportedException { return null; } }
此時就能夠經過咱們本身編寫的鏈接池獲取鏈接了:數據庫
@Test public void getConnTest() { try { MyDataSource dataSource = new MyDataSource(); Connection connection = dataSource.getConnection(); System.out.println(connection); // com.zze.util.ConnectionWrap@6c629d6e } catch (SQLException e) { e.printStackTrace(); } }
點擊下載完整示例apache
DBCP (DataBase Connection Pool) 是 java 數據庫鏈接池的一種,由 Apache 開發,經過它可讓程序自動管理數據庫鏈接的釋放和斷開。緩存
依賴 jar 包下載多線程
# 鏈接設置 driverClassName=com.mysql.cj.jdbc.Driver url=jdbc:mysql://localhost:3306/test username=root password=root # 初始化鏈接 initialSize=10 # 最大鏈接數量 maxActive=50 # 最大空閒鏈接 maxIdle=20 # 最小空閒鏈接 minIdle=5 # 超時等待時間以毫秒爲單位 6000毫秒/1000等於60秒 maxWait=60000 # JDBC驅動創建鏈接時附帶的鏈接屬性屬性的格式必須爲這樣:[屬性名=property;] # 注意:"user" 與 "password" 兩個屬性會被明確地傳遞,所以這裏不須要包含他們。 connectionProperties=useUnicode=true;characterEncoding=gbk;serverTimezone=GMT # 指定由鏈接池所建立的鏈接的自動提交(auto-commit)狀態。 defaultAutoCommit=true # driver default 指定由鏈接池所建立的鏈接的事務級別(TransactionIsolation)。 # 可用值爲下列之一:(詳情可見javadoc。)NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE defaultTransactionIsolation=READ_UNCOMMITTED
package com.zze.test; import org.apache.commons.dbcp.BasicDataSource; import org.apache.commons.dbcp.BasicDataSourceFactory; import org.junit.Test; import javax.sql.DataSource; import java.io.FileInputStream; import java.sql.Connection; import java.sql.SQLException; import java.util.Properties; public class DemoTest { /** * 經過代碼配置建立鏈接池 */ @Test public void dbcpTest1() { try { // 構建數據源對象 BasicDataSource dataSource = new BasicDataSource(); // 數據庫驅動 dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver"); // 用戶名 dataSource.setUsername("root"); // 密碼 dataSource.setPassword("root"); // 數據庫連接 dataSource.setUrl("jdbc:mysql://localhost:3306/test?serverTimezone=GMT"); // 獲得鏈接對象 Connection connection = dataSource.getConnection(); System.out.println(connection.getClass()); // class org.apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper } catch (SQLException e) { e.printStackTrace(); } } /** * 經過配置文件建立鏈接池 */ @Test public void dbcpTest2() { try { Properties properties = new Properties(); properties.load(new FileInputStream("src//dbcpconfig.properties")); DataSource dataSource = BasicDataSourceFactory.createDataSource(properties); Connection connection = dataSource.getConnection(); System.out.println(connection.getClass()); } catch (Exception e) { e.printStackTrace(); } } }
C3P0 也是一個開源的 JDBC 鏈接池,它實現了數據源和 JNDI 綁定,支持 JDBC3 規範和 JDBC2 的標準擴展。目前使用它的開源項目有 Hibernate、Sping 等。app
<?xml version="1.0" encoding="UTF-8"?> <c3p0-config> <!--默認配置--> <default-config> <property name="initialPoolSize">10</property> <property name="maxIdleTime">30</property> <property name="maxPoolSize">100</property> <property name="minPoolSize">10</property> <property name="maxStatements">200</property> </default-config> <!--配置 mysql 鏈接池--> <named-config name="mysql"> <property name="driverClass">com.mysql.jdbc.Driver</property> <property name="jdbcUrl">jdbc:mysql://localhost:3306/test?useUnicode=true&serverTimezone=GMT&characterEncoding=utf-8</property> <property name="user">root</property> <property name="password">root</property> <property name="initialPoolSize">10</property> <property name="maxIdleTime">30</property> <property name="maxPoolSize">100</property> <property name="minPoolSize">10</property> <property name="maxStatements">200</property> </named-config> </c3p0-config>
<!--acquireIncrement:連接用完了自動增量3個。 --> <property name="acquireIncrement">3</property> <!--acquireRetryAttempts:連接失敗後從新試30次。--> <property name="acquireRetryAttempts">30</property> <!--acquireRetryDelay;兩次鏈接中間隔1000毫秒。 --> <property name="acquireRetryDelay">1000</property> <!--autoCommitOnClose:鏈接關閉時默認將全部未提交的操做回滾。 --> <property name="autoCommitOnClose">false</property> <!--automaticTestTable:c3p0測試表,沒什麼用。--> <property name="automaticTestTable">Test</property> <!--breakAfterAcquireFailure:出錯時不把正在提交的數據拋棄。--> <property name="breakAfterAcquireFailure">false</property> <!--checkoutTimeout:100毫秒後若是sql數據沒有執行完將會報錯,若是設置成0,那麼將會無限的等待。 --> <property name="checkoutTimeout">100</property> <!--connectionTesterClassName:經過實現ConnectionTester或QueryConnectionTester的類來測試鏈接。類名需制定全路徑。Default: com.mchange.v2.c3p0.impl.DefaultConnectionTester--> <property name="connectionTesterClassName"></property> <!--factoryClassLocation:指定c3p0 libraries的路徑,若是(一般都是這樣)在本地便可得到那麼無需設置,默認null便可。--> <property name="factoryClassLocation">null</property> <!--forceIgnoreUnresolvedTransactions:做者強烈建議不使用的一個屬性。--> <property name="forceIgnoreUnresolvedTransactions">false</property> <!--idleConnectionTestPeriod:每60秒檢查全部鏈接池中的空閒鏈接。--> <property name="idleConnectionTestPeriod">60</property> <!--initialPoolSize:初始化時獲取三個鏈接,取值應在minPoolSize與maxPoolSize之間。 --> <property name="initialPoolSize">3</property> <!--maxIdleTime:最大空閒時間,60秒內未使用則鏈接被丟棄。若爲0則永不丟棄。--> <property name="maxIdleTime">60</property> <!--maxPoolSize:鏈接池中保留的最大鏈接數。 --> <property name="maxPoolSize">15</property> <!--maxStatements:最大連接數。--> <property name="maxStatements">100</property> <!--maxStatementsPerConnection:定義了鏈接池內單個鏈接所擁有的最大緩存statements數。Default: 0 --> <property name="maxStatementsPerConnection"></property> <!--numHelperThreads:異步操做,提高性能經過多線程實現多個操做同時被執行。Default: 3--> <property name="numHelperThreads">3</property> <!--overrideDefaultUser:當用戶調用getConnection()時使root用戶成爲去獲取鏈接的用戶。主要用於鏈接池鏈接非c3p0的數據源時。Default: null--> <property name="overrideDefaultUser">root</property> <!--overrideDefaultPassword:與overrideDefaultUser參數對應使用的一個參數。Default: null--> <property name="overrideDefaultPassword">password</property> <!--password:密碼。Default: null--> <property name="password"></property> <!--preferredTestQuery:定義全部鏈接測試都執行的測試語句。在使用鏈接測試的狀況下這個一顯著提升測試速度。注意: 測試的表必須在初始數據源的時候就存在。Default: null--> <property name="preferredTestQuery">select id from test where id=1</property> <!--propertyCycle:用戶修改系統配置參數執行前最多等待300秒。Default: 300 --> <property name="propertyCycle">300</property> <!--testConnectionOnCheckout:因性能消耗大請只在須要的時候使用它。Default: false --> <property name="testConnectionOnCheckout">false</property> <!--testConnectionOnCheckin:若是設爲true那麼在取得鏈接的同時將校驗鏈接的有效性。Default: false --> <property name="testConnectionOnCheckin">true</property> <!--user:用戶名。Default: null--> <property name="user">root</property> <!--usesTraditionalReflectiveProxies:動態反射代理。Default: false--> <property name="usesTraditionalReflectiveProxies">false</property>
package com.zze.test; import com.mchange.v2.c3p0.ComboPooledDataSource; import org.junit.Test; import javax.sql.DataSource; import java.sql.Connection; public class DemoTest { /** * 代碼配置建立鏈接池 */ @Test public void c3p0Test1() { try { ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource(); comboPooledDataSource.setDriverClass("com.mysql.cj.jdbc.Driver"); comboPooledDataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test?serverTimezone=GMT"); comboPooledDataSource.setUser("root"); comboPooledDataSource.setPassword("root"); Connection connection = comboPooledDataSource.getConnection(); System.out.println(connection); // com.mchange.v2.c3p0.impl.NewProxyConnection@7a0ac6e3 } catch (Exception e) { e.printStackTrace(); } } /** * 配置文件建立鏈接池 */ @Test public void c3p0Test2() { try { //參數對應使用哪一個config,若是不寫,表示使用默認的config,即default-config裏的配置,不然使用參數指定的named-config裏的配置。 DataSource ds = new ComboPooledDataSource("mysql"); Connection connection = ds.getConnection(); System.out.println(connection); // com.mchange.v2.c3p0.impl.NewProxyConnection@3796751b } catch (Exception e) { e.printStackTrace(); } } }
package com.zze.util; import com.mchange.v2.c3p0.ComboPooledDataSource; import javax.sql.DataSource; import java.sql.Connection; import java.sql.SQLException; public class JDBCUtil { private static final ComboPooledDataSource DATA_SOURCE = new ComboPooledDataSource("mysql"); private static final ThreadLocal<Connection> t = new ThreadLocal<>(); public static Connection getConnection() { Connection conn = null; try { conn = t.get(); if (conn == null) { conn = DATA_SOURCE.getConnection(); t.set(conn); } } catch (Exception e) { e.printStackTrace(); } return conn; } public static void beginTransaction() throws SQLException { Connection conn = getConnection(); conn.setAutoCommit(false); } public static void commitTransaction() throws SQLException { Connection conn = getConnection(); conn.commit(); } public static DataSource getDataSource() { return DATA_SOURCE; } }
要使用 dbutils 須要提供一個鏈接池,這裏我使用 c3p0 。ide
package com.zze.bean; public class User { public User() { } public User(Integer id, String username, String password) { this.id = id; this.username = username; this.password = password; } private Integer id; private String password; private String username; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } @Override public String toString() { return String.format("id=%d,username=%s", this.id, this.username); } }
package com.zze.test; import com.mchange.v2.c3p0.ComboPooledDataSource; import com.zze.bean.User; import org.apache.commons.dbutils.QueryRunner; import org.apache.commons.dbutils.ResultSetHandler; import org.junit.Test; import javax.sql.DataSource; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; public class DemoTest { /** * 查詢全部 */ @Test public void listAllTest() { try { DataSource ds = new ComboPooledDataSource("mysql"); QueryRunner qr = new QueryRunner(ds); List<User> userList = qr.query("select * from user", new ResultSetHandler<List<User>>() { @Override public List<User> handle(ResultSet resultSet) throws SQLException { List<User> users = new ArrayList<>(); while (resultSet.next()) { int id = resultSet.getInt("id"); String username = resultSet.getString("username"); String password = resultSet.getString("password"); users.add(new User(id, username, password)); } return users; } }); System.out.println(userList); // [id=1,username=張三, id=2,username=李四] } catch (Exception e) { e.printStackTrace(); } } /** * 根據 Id 查詢 */ @Test public void getByIdTest() { try { Integer id = 1; DataSource ds = new ComboPooledDataSource("mysql"); QueryRunner qr = new QueryRunner(ds); User user = qr.query("select * from user where id=?", new ResultSetHandler<User>() { @Override public User handle(ResultSet resultSet) throws SQLException { if (resultSet.next()) { int id = resultSet.getInt("id"); String username = resultSet.getString("username"); String password = resultSet.getString("password"); return new User(id, username, password); } return null; } }, id); System.out.println(user); // id=1,username=張三 } catch (Exception e) { e.printStackTrace(); } } /** * 新增 */ @Test public void testAdd() { Integer id = 1; DataSource ds = new ComboPooledDataSource("mysql"); QueryRunner qr = new QueryRunner(ds); try { int count = qr.update("insert into user (username,password) values(?,?)", "王五", "1226"); System.out.println(count > 0 ? "success" : "failed"); } catch (SQLException e) { e.printStackTrace(); } } /** * 更新 */ @Test public void testUpdate() { DataSource ds = new ComboPooledDataSource("mysql"); QueryRunner qr = new QueryRunner(ds); try { int count = qr.update("update user set username=? where id=?", "趙六", 3); System.out.println(count > 0 ? "success" : "failed"); } catch (SQLException e) { e.printStackTrace(); } } /** * 刪除 */ @Test public void testDelete() { DataSource ds = new ComboPooledDataSource("mysql"); QueryRunner qr = new QueryRunner(ds); try { int count = qr.update("delete from user where id=?", 3); System.out.println(count > 0 ? "success" : "failed"); } catch (SQLException e) { e.printStackTrace(); } } }
package com.zze.util; import java.sql.ResultSet; public interface ResultHandler<T> { T handle(ResultSet resultSet); }
package com.zze.util; import javax.sql.DataSource; import javax.xml.crypto.Data; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; public class MyQueryRunner { public MyQueryRunner(DataSource dataSource){ this.dataSource = dataSource; } private DataSource dataSource; public int update(String sql, Object... args) { try { Connection conn = dataSource.getConnection(); PreparedStatement preparedStatement = conn.prepareStatement(sql); int parameterCount = preparedStatement.getParameterMetaData().getParameterCount(); for (int i = 0; i < parameterCount; i++) { preparedStatement.setObject(i + 1, args[i]); } return preparedStatement.executeUpdate(); } catch (Exception e) { e.printStackTrace(); } return 0; } public <T> T query(String sql, ResultHandler<T> handler, Object... args) { try { Connection conn = dataSource.getConnection(); PreparedStatement preparedStatement = conn.prepareStatement(sql); int parameterCount = preparedStatement.getParameterMetaData().getParameterCount(); for (int i = 0; i < parameterCount; i++) { preparedStatement.setObject(i + 1, args[i]); } ResultSet resultSet = preparedStatement.executeQuery(); T result = handler.handle(resultSet); return result; } catch (Exception e) { e.printStackTrace(); } return null; } }
package com.zze.test; import com.mchange.v2.c3p0.ComboPooledDataSource; import com.zze.bean.User; import com.zze.util.MyQueryRunner; import com.zze.util.ResultHandler; import org.junit.Test; import javax.sql.DataSource; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; /** * 自定義的 DBUtils 測試 */ public class MyDBUtilsTest { /** * 查詢全部 */ @Test public void listAllTest() { DataSource ds = new ComboPooledDataSource("mysql"); MyQueryRunner myQueryRunner = new MyQueryRunner(ds); List<User> userList = myQueryRunner.query("select * from user", new ResultHandler<List<User>>() { @Override public List<User> handle(ResultSet resultSet) { try { List<User> users = new ArrayList<>(); while (resultSet.next()) { int id = resultSet.getInt("id"); String username = resultSet.getString("username"); String password = resultSet.getString("password"); users.add(new User(id, username, password)); } return users; } catch (Exception e) { e.printStackTrace(); } return null; } }); System.out.println(userList); } @Test public void getByIdTest() { DataSource ds = new ComboPooledDataSource("mysql"); MyQueryRunner myQueryRunner = new MyQueryRunner(ds); int id = 1; User user = myQueryRunner.query("select * from user where id=?", new ResultHandler<User>() { @Override public User handle(ResultSet resultSet) { try { if (resultSet.next()) { int id = resultSet.getInt("id"); String username = resultSet.getString("username"); String password = resultSet.getString("password"); return new User(id, username, password); } } catch (SQLException e) { e.printStackTrace(); } return null; } }, id); System.out.println(user); } /** * 新增 */ @Test public void testAdd() { Integer id = 1; DataSource ds = new ComboPooledDataSource("mysql"); MyQueryRunner qr = new MyQueryRunner(ds); try { int count = qr.update("insert into user (username,password) values(?,?)", "王五", "1226"); System.out.println(count > 0 ? "success" : "failed"); } catch (Exception e) { e.printStackTrace(); } } /** * 更新 */ @Test public void testUpdate() { DataSource ds = new ComboPooledDataSource("mysql"); MyQueryRunner qr = new MyQueryRunner(ds); try { int count = qr.update("update user set username=? where id=?", "趙六", 7); System.out.println(count > 0 ? "success" : "failed"); } catch (Exception e) { e.printStackTrace(); } } /** * 刪除 */ @Test public void testDelete() { DataSource ds = new ComboPooledDataSource("mysql"); MyQueryRunner qr = new MyQueryRunner(ds); try { int count = qr.update("delete from user where id=?", 6); System.out.println(count > 0 ? "success" : "failed"); } catch (Exception e) { e.printStackTrace(); } } }
@Test public void beanHandlerTest() { try { Integer id = 1; DataSource ds = new ComboPooledDataSource("mysql"); QueryRunner qr = new QueryRunner(ds); User user = qr.query("select * from user where id=?", new BeanHandler<>(User.class), id); System.out.println(user); } catch (Exception e) { e.printStackTrace(); } } @Test public void beanListHandlerTest() { try { DataSource ds = new ComboPooledDataSource("mysql"); QueryRunner qr = new QueryRunner(ds); List<User> userList = qr.query("select * from user", new BeanListHandler<>(User.class)); System.out.println(userList); } catch (Exception e) { e.printStackTrace(); } } @Test public void mapHandlerTest() { try { DataSource ds = new ComboPooledDataSource("mysql"); QueryRunner qr = new QueryRunner(ds); Map<String, Object> user = qr.query("select * from user where id=?", new MapHandler(), 2); System.out.println(user); // {password=1226, id=2, username=李四} } catch (Exception e) { e.printStackTrace(); } } @Test public void mapListHandlerTest() { try { DataSource ds = new ComboPooledDataSource("mysql"); QueryRunner qr = new QueryRunner(ds); List<Map<String, Object>> users = qr.query("select * from user", new MapListHandler()); System.out.println(users); // [{password=1226, id=1, username=張三}, {password=1226, id=2, username=李四}] } catch (Exception e) { e.printStackTrace(); } }
這個練習算是對以前知識的總結,一個包含 CRUD、模糊查詢、分頁功能的簡易版學生管理系統,點擊下載。