池
- 池化机制是预先创建对象的方式。加载类时。
- 它改进了应用程序
performance [通过重新使用相同的对象对 Object-Data 执行任何操作] & memory [分配和取消分配许多对象会产生大量内存管理开销]。
- 不需要清理对象,因为我们使用的是同一个对象,从而减少了垃圾收集负载。
« 池化 [Object 池,String 常量池,Thread 池,连接池]
字符串常量池
- 字符串文字池仅维护每个不同字符串值的一份副本。必须是不可变的。
- 调用 intern 方法时,它使用 equals 方法检查池中具有相同内容的对象可用性。
« 如果字符串副本在池中可用,则返回引用。
« 否则,将 String 对象添加到池中并返回引用。
示例:用于验证池中Unique Object 的字符串。
public class StringPoolTest {
public static void main(String[] args) { // Integer.valueOf(), String.equals()
String eol = System.getProperty("line.separator"); //java7 System.lineSeparator();
String s1 = "Yash".intern();
System.out.format("Val:%s Hash:%s SYS:%s "+eol, s1, s1.hashCode(), System.identityHashCode(s1));
String s2 = "Yas"+"h".intern();
System.out.format("Val:%s Hash:%s SYS:%s "+eol, s2, s2.hashCode(), System.identityHashCode(s2));
String s3 = "Yas".intern()+"h".intern();
System.out.format("Val:%s Hash:%s SYS:%s "+eol, s3, s3.hashCode(), System.identityHashCode(s3));
String s4 = "Yas"+"h";
System.out.format("Val:%s Hash:%s SYS:%s "+eol, s4, s4.hashCode(), System.identityHashCode(s4));
}
}
使用 Type-4 的连接池 Driver 使用 3rd 方库[DBCP2, c3p0, Tomcat JDBC]
Type 4 - The Thin driver converts JDBC calls directly into the vendor-specific database protocol Ex[Oracle - Thick, MySQL - Quora].wiki
在连接池机制中,当类被加载时,它会得到physical JDBC connection 对象,并为用户提供一个封装的物理连接对象。 PoolableConnection 是实际连接的包装器。
-
getConnection() 从连接 objectpool 中选择一个免费的包装连接并将其返回。
-
close() 不是关闭它,而是将包装连接返回到池中。
示例:在 Java 7 中使用 ~ DBCP2 连接池[try-with-resources]
public class ConnectionPool {
static final BasicDataSource ds_dbcp2 = new BasicDataSource();
static final ComboPooledDataSource ds_c3p0 = new ComboPooledDataSource();
static final DataSource ds_JDBC = new DataSource();
static Properties prop = new Properties();
static {
try {
prop.load(ConnectionPool.class.getClassLoader().getResourceAsStream("connectionpool.properties"));
ds_dbcp2.setDriverClassName( prop.getProperty("DriverClass") );
ds_dbcp2.setUrl( prop.getProperty("URL") );
ds_dbcp2.setUsername( prop.getProperty("UserName") );
ds_dbcp2.setPassword( prop.getProperty("Password") );
ds_dbcp2.setInitialSize( 5 );
ds_c3p0.setDriverClass( prop.getProperty("DriverClass") );
ds_c3p0.setJdbcUrl( prop.getProperty("URL") );
ds_c3p0.setUser( prop.getProperty("UserName") );
ds_c3p0.setPassword( prop.getProperty("Password") );
ds_c3p0.setMinPoolSize(5);
ds_c3p0.setAcquireIncrement(5);
ds_c3p0.setMaxPoolSize(20);
PoolProperties pool = new PoolProperties();
pool.setUrl( prop.getProperty("URL") );
pool.setDriverClassName( prop.getProperty("DriverClass") );
pool.setUsername( prop.getProperty("UserName") );
pool.setPassword( prop.getProperty("Password") );
pool.setValidationQuery("SELECT 1");// SELECT 1(mysql) select 1 from dual(oracle)
pool.setInitialSize(5);
pool.setMaxActive(3);
ds_JDBC.setPoolProperties( pool );
} catch (IOException e) { e.printStackTrace();
} catch (PropertyVetoException e) { e.printStackTrace(); }
}
public static Connection getDBCP2Connection() throws SQLException {
return ds_dbcp2.getConnection();
}
public static Connection getc3p0Connection() throws SQLException {
return ds_c3p0.getConnection();
}
public static Connection getJDBCConnection() throws SQLException {
return ds_JDBC.getConnection();
}
}
public static boolean exists(String UserName, String Password ) throws SQLException {
boolean exist = false;
String SQL_EXIST = "SELECT * FROM users WHERE username=? AND password=?";
try ( Connection connection = ConnectionPool.getDBCP2Connection();
PreparedStatement pstmt = connection.prepareStatement(SQL_EXIST); ) {
pstmt.setString(1, UserName );
pstmt.setString(2, Password );
try (ResultSet resultSet = pstmt.executeQuery()) {
exist = resultSet.next(); // Note that you should not return a ResultSet here.
}
}
System.out.println("User : "+exist);
return exist;
}
jdbc:<DB>:<drivertype>:<HOST>:<TCP/IP PORT>:<dataBaseName>
jdbc:oracle:thin:@localhost:1521:myDBName
jdbc:mysql://localhost:3306/myDBName
connectionpool.properties
URL : jdbc:mysql://localhost:3306/myDBName
DriverClass : com.mysql.jdbc.Driver
UserName : root
Password :
Web 应用程序:为了避免在所有连接关闭时出现连接问题[MySQL "wait_timeout" 默认 8 小时],以便重新打开与底层数据库的连接。
您可以通过设置 testOnBorrow = true 和 validationQuery= "SELECT 1" 来测试每个连接,并且不要对 MySQL 服务器使用 autoReconnect,因为它已被弃用。 issue
===== ===== context.xml ===== =====
<?xml version="1.0" encoding="UTF-8"?>
<!-- The contents of this file will be loaded for a web application -->
<Context>
<Resource name="jdbc/MyAppDB" auth="Container"
factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
type="javax.sql.DataSource"
initialSize="5" minIdle="5" maxActive="15" maxIdle="10"
testWhileIdle="true"
timeBetweenEvictionRunsMillis="30000"
testOnBorrow="true"
validationQuery="SELECT 1"
validationInterval="30000"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/myDBName"
username="yash" password="777"
/>
</Context>
===== ===== web.xml ===== =====
<resource-ref>
<description>DB Connection</description>
<res-ref-name>jdbc/MyAppDB</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
===== ===== DBOperations ===== =====
servlet « init() {}
Normal call used by sevlet « static {}
static DataSource ds;
static {
try {
Context ctx=new InitialContext();
Context envContext = (Context)ctx.lookup("java:comp/env");
ds = (DataSource) envContext.lookup("jdbc/MyAppDB");
} catch (NamingException e) { e.printStackTrace(); }
}
另请参阅: