JDBC C3P0数据库连接池

简介:

  • JDBC(Java DataBase Connectivity)就是Java数据库连接,实际上就是用Java语言来操作数据库。原来我们操作数据库是在控制台使用SQL语句来操作数据库,JDBC是用Java语言向数据库发送SQL语句。
  • JDBC是接口,而JDBC驱动才是接口的实现,没有驱动无法完成数据库连接!每个数据库厂商都有自己的驱动,用来连接自己公司的数据库。
  • JDBC中的核心类有:DriverManager、Connection、Statement,和ResultSet!
       //加载驱动
        Class.forName("com.mysql.jdbc.Driver")
       //获取连接
        Connection con = DriverManager.getConnection(“jdbc:mysql://localhost:3306/mydb1”,”root”,”123”);
       //得到声明
         Statement stmt = con.createStatement();
       //sql语句
         String sql = “insert into user value(’zhangSan’, ’123’)”;
       //执行更新sql
        int m = stmt.executeUpdate(sql);(这里的m指的是影响的行数)
       //执行查询sql
        ResulSet rs=stmt.executeQuery(sql);
                       rs.next();
                       rs.getString(下标);(下标是从1开始,而不是从零)
  • 关闭流(倒关)
    rs.close();
    stmt.close();
    con.close();
  • void beforeFirst():把光标放到第一行的前面,这也是光标默认的位置;
    void afterLast():把光标放到最后一行的后面;
    boolean first():把光标放到第一行的位置上,返回值表示调控光标是否成功;
    boolean last():把光标放到最后一行的位置上;
    boolean isBeforeFirst():当前光标位置是否在第一行前面;
    boolean isAfterLast():当前光标位置是否在最后一行的后面;
    boolean isFirst():当前光标位置是否在第一行上;
    boolean isLast():当前光标位置是否在最后一行上;
    boolean previous():把光标向上挪一行;
    boolean next():把光标向下挪一行;
    boolean relative(int row):相对位移,当row为正数时,表示向下移动row行,为负数时表示向上移动row行;
    boolean absolute(int row):绝对位移,把光标移动到指定的行上;
    int getRow():返回当前光标所有行。
  • con.createStatement():生成的结果集:不滚动、不敏感、不可更新!
    con.createStatement(int,int):
    第一个参数:
    ResultSet.TYPE_FORWARD_ONLY:不滚动结果集;
    ResultSet.TYPE_SCROLL_INSENSITIVE:滚动结果集,但结果集数据不会再跟随数据库而变化;
    ResultSet.TYPE_SCROLL_SENSITIVE:滚动结果集,但结果集数据不会再跟随数据库而变化;
    第二个参数:
    CONCUR_READ_ONLY:结果集是只读的,不能通过修改结果集而反向影响数据库;
    CONCUR_UPDATABLE:结果集是可更新的,对结果集的更新可以反向影响数据库。
  • Statement createStatement(int resultSetType, int resultSetConcurrency)
  • PreparedStatement(它是Statement接口的子接口)
    作用:防SQL攻击;提高代码的可读性、可维护性、提高效率
    String sql = “select * from tab_student where s_number=?”;
    PreparedStatement pstmt = con.prepareStatement(sql);
    pstmt.setString(1, “S_1001”);
    ResultSet rs = pstmt.executeQuery();
    rs.close();
    pstmt.clearParameters();//每次执行需要清空的
    pstmt.setString(1, “S_1002”);
    rs = pstmt.executeQuery();
  • JdbcUtils工具类
public class JdbcUtils {
	private static final String dbconfig = "dbconfig.properties";
	
	static {
		try {
			InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream(dbconfig);
			private static Properties prop = new Properties();
			prop.load(in);
			Class.forName(prop.getProperty("driverClassName"));
		} catch(IOException e) {
			throw new RuntimeException(e);
		}
	}

	public static Connection getConnection() {
		try {
			return DriverManager.getConnection(prop.getProperty("url"),
					prop.getProperty("username"), prop.getProperty("password"));
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
}
  • 经过class.forName()得到Class之后,调用newInstance()的到对象

时间类型

  • java.sql包下给出三个与数据库相关的日期时间类型,分别是:
    Date:表示日期,只有年月日,没有时分秒。会丢失时间;
    Time:表示时间,只有时分秒,没有年月日。会丢失日期;
    Timestamp:表示时间戳,有年月日时分秒,以及毫秒。
  • 数据库类型与java中类型的对应关系:
    DATE -> java.sql.Date
    TIME -> java.sql.Time
    TIMESTAMP -> java.sql.Timestamp
  • 时间类型的转换:
    java.util.Date 转换为 java.sql.Date、Time、Timestamp
    把util的Date转换成毫秒值
    使用毫秒值创建sql的Date、Time、Timestamp
java.util.Date date = new java.util.Date();
long l = date.getTime();
java.sql.Date sqlDate = new java.sql.Date(l);

海量数据

  • 标准SQL中提供了如下类型来保存大数据类型:
    类型 长度
    tinyblob (256B)
    blob (64K)
    mediumblob(16M)
    longblob (4G)
    tinyclob (256B)
    clob (64K)
    mediumclob (16M)
    longclob(4G)
  • mysql中使用如下四种类型来处理文本大数据:
    类型 长度
    tinytext (256B)
    text (64K)
    mediumtext (16M)
    longtext (4G)

装入

con = JdbcUtils.getConnection();
			String sql = "insert into tab_bin(filename,data) values(?, ?)";
			pstmt = con.prepareStatement(sql);
			pstmt.setString(1, "a.jpg");
			InputStream in = new FileInputStream("f:\\a.jpg");[得到一个输入流对象]
			pstmt.setBinaryStream(2, in);[为第二个参数赋值为流对象]
			pstmt.executeUpdate();

取出:

con = JdbcUtils.getConnection();
			String sql = "select filename,data from tab_bin where id=?";
			pstmt = con.prepareStatement(sql);
			pstmt.setInt(1, 1);
			rs = pstmt.executeQuery();
			rs.next();
			
			String filename = rs.getString("filename");
			OutputStream out = new FileOutputStream("F:\\" + filename)[使用文件名来创建输出流对象。];
			
			InputStream in = rs.getBinaryStream("data")[读取输入流对象];
			IOUtils.copy(in, out)[把in中的数据写入到out中。];
			out.close();

批处理

  • 批处理只针对更新(增、删、改)语句
  • 可以多次调用Statement类的addBatch(String sql)方法,把需要执行的所有SQL语句添加到一个“批”中,然后调用Statement类的executeBatch()方法来执行当前“批”中的语句。
  • void addBatch(String sql):添加
  • int[] executeBatch():执行所有
  • void clearBatch():清除
  • 当执行了“批”之后,“批”中的SQL语句就会被清空!

PreparedStatement批处理

PreparedStatement的批处理有所不同,因为每个PreparedStatement对象都绑定一条SQL模板。所以向PreparedStatement中添加的不是SQL语句,而是给“?”赋值。

	con = JdbcUtils.getConnection();
			String sql = "insert into stu values(?,?,?,?)";
			pstmt = con.prepareStatement(sql);
			for(int i = 0; i < 10; i++) {
				pstmt.setString(1, "S_10" + i);
				pstmt.setString(2, "stu" + i);
				pstmt.setInt(3, 20 + i);
				pstmt.setString(4, i % 2 == 0 ? "male" : "female");
				pstmt.addBatch()[PreparedStatement的addBatch()方法没有参数!];
			}
			pstmt.executeBatch[执行批]();

数据库连接池

  • 实现:必须实现 javax.sql.DataSource接口
  • 概念:
    用池来管理Connection,这可以重复使用Connection。有了池,所以我们就不用自己来创建Connection,而是通过池来获取Connection对象。当使用完Connection后,调用Connection的close()方法也不会真的关闭Connection,而是把Connection“归还”给池。

DBCP

  • DBCP是Apache提供的一款开源免费的数据库连接池
	public void fun1() throws SQLException {
		BasicDataSource ds = new BasicDataSource();
		ds.setUsername("root");
		ds.setPassword("123");
		ds.setUrl("jdbc:mysql://localhost:3306/mydb1");
		ds.setDriverClassName("com.mysql.jdbc.Driver");
		
		ds.setMaxActive(20);
		ds.setMaxIdle(10);
		ds.setInitialSize(10);
		ds.setMinIdle(2);
		ds.setMaxWait(1000);
		
		Connection con = ds.getConnection();
		System.out.println(con.getClass().getName());
		con.close();
	}

C3P0(性能优于DBCP)

  • C3P0也是开源免费的连接池!
  • C3P0中池类是:ComboPooledDataSource。
 public void fun1() throws PropertyVetoException, SQLException {
		ComboPooledDataSource ds = new ComboPooledDataSource();
		ds.setJdbcUrl("jdbc:mysql://localhost:3306/mydb1");
		ds.setUser("root");
		ds.setPassword("123");
		ds.setDriverClass("com.mysql.jdbc.Driver");
		
		ds.setAcquireIncrement(5);
		ds.setInitialPoolSize(20);
		ds.setMinPoolSize(2);
		ds.setMaxPoolSize(50);
		
		Connection con = ds.getConnection();
		System.out.println(con);
		con.close();
	}
  • 配置文件要求:
    文件名称:必须叫c3p0-config.xml
    文件位置:必须在src下
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
     <--            默认配置              -->
	<default-config>
		<property name="jdbcUrl">jdbc:mysql://localhost:3306/mydb1</property>
		<property name="driverClass">com.mysql.jdbc.Driver</property>
		<property name="user">root</property>
		<property name="password">123</property>
		<property name="acquireIncrement">3</property>
		<property name="initialPoolSize">10</property>
		<property name="minPoolSize">2</property>
		<property name="maxPoolSize">10</property>
	</default-config>
	<--           指定数据库(oracle)配置          -->
<named-config name="oracle-config">
		<property name="jdbcUrl">jdbc:mysql://localhost:3306/mydb1</property>
		<property name="driverClass">com.mysql.jdbc.Driver</property>
		<property name="user">root</property>
		<property name="password">123</property>
		<property name="acquireIncrement">3</property>
		<property name="initialPoolSize">10</property>
		<property name="minPoolSize">2</property>
		<property name="maxPoolSize">10</property>
	</named-config>
</c3p0-config>
  • c3p0的配置文件中可以配置多个连接信息,可以给每个配置起个名字,这样可以方便的通过配置名称来切换配置信息。

ThreadLocal

  • ThreadLocal类只有三个方法:
    void set(T value):保存值;
    T get():获取值;
    void remove():移除值。
  • ThreadLocal的内部是Map
    ThreadLocal内部其实是个Map来保存数据。它使用了当前线程做为键。
class MyThreadLocal<T> {
	private Map<Thread,T> map = new HashMap<Thread,T>();
	public void set(T value) {
		map.put(Thread.currentThread(), value);
	}
	
	public void remove() {
		map.remove(Thread.currentThread());
	}
	
	public T get() {
		return map.get(Thread.currentThread());
	}
}

DBUtils

  • DBUtils简介
    DBUtils是Apache Commons组件中的一员,开源免费!
    DBUtils是对JDBC的简单封装!
    DBUtils的Jar包:dbutils.jar
  • DBUtils主要类
    update():执行insert、update、delete!
    query():执行select语句!
    batch():执行批处理!
  • QueryRunner之更新
  • 创建QueryRunner
  • update()方法
int update(Connection con, String sql, Object… params)
	public void fun1() throws SQLException {
		QueryRunner qr = new QueryRunner();
		String sql = "insert into user values(?,?,?)";
		qr.update(JdbcUtils.getConnection(), sql, "u1", "zhangSan", "123");
	}
  • 还有另一种方式来使用QueryRunner
  • 创建QueryRunner
    构造器:QueryRunner(DataSource)
  • update()方法
    int update(String sql, Object… params)
    这种方式在创建QueryRunner时传递了连接池对象,那么在调用update()方法时就不用再传递Connection了。
public void fun2() throws SQLException {
		QueryRunner qr = new QueryRunner(JdbcUtils.getDataSource());
		String sql = "insert into user values(?,?,?)";
		qr.update(sql, "u1", "zhangSan", "123");
	}

BaseServlet

  • BaseServlet的作用
    是让一个Servlet可以处理多种不同的请求。不同的请求调用Servlet的不同方法。我们写好了BaseServlet后,让其他Servlet继承BaseServlet,例如CustomerServlet继承BaseServlet,然后在CustomerServlet中提供add()、update()、delete()等方法,每个方法对应不同的请求。
  • BaseServlet代码
public class BaseServlet extends HttpServlet {
	
	protected void service(HttpServletRequest req, HttpServletResponse res)
			throws ServletException, IOException {
		req.setCharacterEncoding("UTF-8");
		res.setContentType("text/html;charset=utf-8");

		// 例如:http://localhost:8080/demo1/xxx?m=add
		String methodName = req.getParameter("method");
		
		// 当没用指定要调用的方法时,那么默认请求的是execute()方法。
		if(methodName == null || methodName.isEmpty()) {
			methodName = "execute";
		}
		Class c = this.getClass();
		//得到Class
		try {
			// 通过方法名称获取方法的反射对象
			Method m = c.getMethod(methodName, HttpServletRequest.class,
					HttpServletResponse.class);
			String result = (String) m.invoke(this, req, res);
			if(result != null && !result.isEmpty()) {
				req.getRequestDispatcher(result).forward(req, res);
			}
		} catch (Exception e) {
			throw new ServletException(e);
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值