===============================
数据库连接池
连接池的原理如上,可以写一个简单的代码来说明,这部分代码不完整,随便看看就好
public class MyDataSource implements DataSource
{
private List<Connection>list1=new ArrayList<Connection>();
public MyDataSource()
{
//一开始就获取10个连接
for(int i=0;i<10;i++)
{
Connection conn1=JDBCUtil.getConnection();
list1.add(conn1);
}
}
@Override
public Connection getConnection() throws SQLException
{
//如果连接池满了,自动扩容
if (list1.size()==0)
{
for(int i=0;i<5;i++)
{
Connection conn1=JDBCUtil.getConnection();
list1.add(conn1);
}
}
//拿走一个对象
//remove会把第一个删除并且返回,且后面所有元素会向前移
Connection coon1=list1.remove(0);
//利用装饰者模式对原本的对象进行包装,我们传出去的是我们自己的对象
//我们的对象只实现了3个方法,getConnection,close,prepareStatement(伪实现)
//所以这个包装出去的对象,调用不了除这3个之外的其他方法
Connection connection1=new MyConnection(coon1, list1);
return connection1;
}
public Connection getConnection(String username, String password) throws SQLException
{
return null;
}
//归返对象
public void addBack(Connection con)
{
list1.add(con);
}
@Override
public PrintWriter getLogWriter() throws SQLException
{
// TODO 自动生成的方法存根
return null;
}
@Override
public void setLogWriter(PrintWriter out) throws SQLException
{
}
@Override
public void setLoginTimeout(int seconds) throws SQLException
{
// TODO 自动生成的方法存根
}
@Override
public int getLoginTimeout() throws SQLException
{
// TODO 自动生成的方法存根
return 0;
}
@Override
public Logger getParentLogger() throws SQLFeatureNotSupportedException
{
// TODO 自动生成的方法存根
return null;
}
@Override
public <T> T unwrap(Class<T> iface) throws SQLException
{
// TODO 自动生成的方法存根
return null;
}
@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException
{
// TODO 自动生成的方法存根
return false;
}
}
DBCP连接池
由Apache开发,tomcat就是他们开发的,导入dbcp的jar包,dbcp的jar有2个,还有一个是pool.jar
public class DBCPDemo
{
public static void main(String[] args)
{
test2();
}
//使用配置文件的方法获取参数连接数据库
public static void test2()
{
Connection conn1=null;
PreparedStatement ps1=null;
try
{
//加载配置文件,配置文件放到src下面,这样发布到tomcat后就是在classes文件夹里
Properties properties1=new Properties();
InputStream iStream1=DBCPDemo.class.getClassLoader().getResourceAsStream("dbcpconfig.properties");
//加载配置文件
properties1.load(iStream1);
//通过配置文件获取连接池对象
//createDataSource是一个静态的对象,在BasicDataSourceFactory(资源工厂)里
DataSource dataSource1=BasicDataSourceFactory.createDataSource(properties1);
//获取连接对象
conn1=dataSource1.getConnection();
//执行语句
String sql="insert into bank values(null,?,?)";
ps1=conn1.prepareStatement(sql);
ps1.setString(1, "test");
ps1.setInt(2, 10000);
ps1.executeUpdate();
} catch (Exception e)
{
e.printStackTrace();
}finally {
//释放资源
JDBCUtil.release(null, ps1, conn1);
}
}
//使用普通set方法设置连接数据库的参数
public static void test1()
{
//创建连接池对象
BasicDataSource dataSource1=new BasicDataSource();
Connection conn1=null;
PreparedStatement ps1=null;
try
{
//设置连接数据库的参数
dataSource1.setDriverClassName("com.mysql.jdbc.Driver");
dataSource1.setUrl("jdbc:mysql://localhost/test");
dataSource1.setUsername("root");
dataSource1.setPassword("123");
//获取连接对象
conn1=dataSource1.getConnection();
//执行语句
String sql="insert into bank values(null,?,?)";
ps1=conn1.prepareStatement(sql);
ps1.setString(1, "test");
ps1.setInt(2, 10000);
ps1.executeUpdate();
} catch (SQLException e)
{
e.printStackTrace();
}finally {
//释放资源
JDBCUtil.release(null, ps1, conn1);
}
}
}
c3p0连接池(一般都用这个)
c3p0配置文件,这个直接从c3p0的文档复制过来的,名字要固定,就叫c3p0-config.xml 且放到src目录下
c3p0可以方便的切换数据库
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<!-- default-config 默认的配置, -->
<default-config>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost/test</property>
<property name="user">root</property>
<property name="password">123</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>
</default-config>
<!-- 下面这是配置另外一个数据库的-->
<named-config name="oracle">
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost/test</property>
<property name="user">root</property>
<property name="password">123</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>
c3p0的使用
public class C3P0Demo
{
public static void main(String[] args)
{
test2();
}
//使用xml配置文件的方法获取参数连接数据库
public static void test2()
{
Connection conn1=null;
PreparedStatement ps1=null;
try
{
//创建连接池对象并且自动加载配置文件,可以指定数据库,不指定就是用默认的
// ComboPooledDataSource dataSource1=new ComboPooledDataSource("oracle");
ComboPooledDataSource dataSource1=new ComboPooledDataSource();
//获取连接对象
conn1=dataSource1.getConnection();
//执行语句
String sql="insert into bank values(null,?,?)";
ps1=conn1.prepareStatement(sql);
ps1.setString(1, "test");
ps1.setInt(2, 10000);
ps1.executeUpdate();
} catch (Exception e)
{
e.printStackTrace();
}finally {
//释放资源
JDBCUtil.release(null, ps1, conn1);
}
}
//使用普通set方法设置连接数据库的参数
public static void test1()
{
Connection conn1=null;
PreparedStatement ps1=null;
try
{
//创建连接池对象
ComboPooledDataSource dataSource1=new ComboPooledDataSource();
//设置连接数据库的参数
dataSource1.setDriverClass("com.mysql.jdbc.Driver");
dataSource1.setJdbcUrl("jdbc:mysql://localhost/test");
dataSource1.setUser("root");
dataSource1.setPassword("123");
//获取连接对象
conn1=dataSource1.getConnection();
//执行语句
String sql="insert into bank values(null,?,?)";
ps1=conn1.prepareStatement(sql);
ps1.setString(1, "test");
ps1.setInt(2, 10000);
ps1.executeUpdate();
} catch (Exception e)
{
e.printStackTrace();
}finally {
//释放资源
JDBCUtil.release(null, ps1, conn1);
}
}
}
DBUtils
可以更加方便的操作sql语句,连接数据库的部分还需要我们自己来
我们甚至可以改造之前的JDBCUtils
public class JDBCUtil
{
static ComboPooledDataSource dataSource1 = null;
static
{
// 因为我们是使用配置文件xml的,所以直接创建里面会自动加载xml
dataSource1 = new ComboPooledDataSource();
}
public static DataSource getDataSource()
{
return dataSource1;
}
public static Connection getConnection()
{
try
{
// 直接返回Connection
return dataSource1.getConnection();
} catch (SQLException e)
{
e.printStackTrace();
}
return null;
}
public static void release(ResultSet rs, Statement state1, Connection conn1)
{
closeRs(rs);
closeState(state1);
closeConn(conn1);
}
private static void closeRs(ResultSet rs)
{
try
{
// 需要先判断是不是等于空,如果等于空,去释放就触发异常了
// 最后的时候还需要把rs置空
if (rs != null)
{
rs.close();
}
} catch (SQLException e)
{
e.printStackTrace();
} finally
{
rs = null;
}
}
private static void closeState(Statement state1)
{
try
{
if (state1 != null)
{
state1.close();
}
} catch (SQLException e)
{
e.printStackTrace();
} finally
{
state1 = null;
}
}
private static void closeConn(Connection conn1)
{
try
{
if (conn1 != null)
{
conn1.close();
}
} catch (SQLException e)
{
e.printStackTrace();
} finally
{
conn1 = null;
}
}
}
使用DBUtils
public class DBUtilsDemo
{
public static void main(String[] args)
{
testSelect2();
}
//测试查询,用的反射机制,常用
public static void testSelect2()
{
try
{
// 创建连接池对象并且自动加载配置文件,这里我们使用的是C3P0
ComboPooledDataSource dataSource1 = new ComboPooledDataSource();
//创建查询对象,我们传入dataSource,里面应该会自动调用getConnection
QueryRunner queryRunner1 = new QueryRunner(dataSource1);
String sql = "select * from bank where id=?";
//第2个参数传入类的描述符,然后函数内部会自动去调用get,set方法,如果我们去掉了get set方法就获取不到数值
Account account1=queryRunner1.query(sql, new BeanHandler<Account>(Account.class),1);
account1.toString();
System.out.println("==========下面是查询多个===================");
sql = "select * from bank";
List<Account> list1= queryRunner1.query(sql, new BeanListHandler<Account>(Account.class));
for (Account account : list1)
{
account.toString();
}
} catch (Exception e)
{
e.printStackTrace();
}
}
//测试查询,用匿名内部类
public static void testSelect()
{
try
{
// 创建连接池对象并且自动加载配置文件,这里我们使用的是C3P0
ComboPooledDataSource dataSource1 = new ComboPooledDataSource();
// DBUtils只是帮我们简化CRUB代码,还是需要传递连接对象的
// 里面应该会自动调用getConnection
QueryRunner queryRunner1 = new QueryRunner(dataSource1);
String sql = "select * from bank where id=?";
//采用匿名内部类
queryRunner1.query(sql, new ResultSetHandler<Account>()
{
//ResultSetHandler接口的方法,需要我们实现
public Account handle(ResultSet rs) throws SQLException
{
Account account2 = new Account();
//用while可以实现多条查询
while (rs.next())
{
int id = rs.getInt("id");
String name = rs.getString("name");
int money = rs.getInt("money");
account2.setId(id);
account2.setName(name);
account2.setMoney(money);
//输出结果
System.out.println(account2.toString());
}
return account2;
}
}, 1);
} catch (Exception e)
{
e.printStackTrace();
}
}
//测试增加,删除,更新
public static void testUpdate()
{
try
{
//创建连接池对象并且自动加载配置文件,这里我们使用的是C3P0
ComboPooledDataSource dataSource1=new ComboPooledDataSource();
//DBUtils只是帮我们简化CRUB代码,还是需要传递连接对象的
//里面应该会自动调用getConnection
QueryRunner queryRunner1=new QueryRunner(dataSource1);
//update可以实现增加,删除,更新
String sql="insert into bank values(null,'test1',123)";
queryRunner1.update(sql);
} catch (Exception e)
{
e.printStackTrace();
}finally {
}
}
}
//如果使用了聚合函数,那么就用ScalarHandler
String sql="select count(*) from stu where sname=?";
Long num=(Long)runner.query(sql,new ScalarHandler(),name);