javaweb学习(3):JDBC进阶之路

前言:

JDBC学习起来并不难,但是随着学习的深入,涉及到的知识越来越多,见到的框架也越来越多。

于是乎,很有必要对学过的知识做个总结。以下代码都是在eclipse中完成的。


第一章:单连接操作

起初学习jdbc,一上来我们接触到的jdbc就是jdk的标准“单连接”操作,

首先下载jdbc的java包:点击下载jar包

一个完整的标准操作代码应如下所示:

package com.jimmy.jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public class Demo1 {
	public static void main(String[] args) throws Exception {
		Connection conn = null;
		PreparedStatement ps = null;
		ResultSet rts = null;
		try {
			Class.forName("com.mysql.jdbc.Driver");
			conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/emp", "root", "123456");
			ps = conn.prepareStatement("select * from emp");
			rts = ps.executeQuery();
			while(rts.next()){
				System.out.println(rts.getObject(2));
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {	
			if (rts != null) {				
				try {
					rts.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
				rts = null;
			}
			if (ps != null) {				
				try {
					ps.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
				ps = null;
			}
			if (conn != null) {
				try {
					conn.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
				conn = null;
			}
		}
	}
}

这样操作的弊端显而易见,主要有两方面的缺陷:

1,重复的大量代码在执行相同的操作,如:取得连接,关闭资源等。

2,每次只取得一个连接,然后再关闭,效率极其低下。

针对以上方面的缺点,我们来一一攻破。


第二章:自己写一个封装类

自己写一个类,将获得连接和关闭资源的重复代码封装一下:

1,首先我们在src目录下写一个配置文件:mysqlInfo.properties,将一些配置信息写进去:

 driverClass = com.mysql.jdbc.Driver
 url = jdbc:mysql://localhost:3306/user
 username = root
 password = 123456


2,MyJDBCUtils.java类用于读取配置文件,并封装代码:

package com.jimmy.MyDBUtils;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ResourceBundle;

public class MyJDBCUtils {
	//数据库连接用到的字段我们从配置文件中读取
	private static String driverClass;
	private static String url;
	private static String username;
	private static String password;
	//下面的静态代码块就是读取配置文件中的数据
	static{
		ResourceBundle rb = ResourceBundle.getBundle("mysqlInfo");
		driverClass = rb.getString("driverClass");
		url = rb.getString("url");
		username = rb.getString("username");
		password = rb.getString("password");
	}
	//取得连接函数
	public static Connection getConnection() throws Exception {
		Class.forName(driverClass);
		Connection conn = DriverManager.getConnection(url,username, password);
		return conn;
	}
	//关闭资源函数
	public static void closeRes(ResultSet rst, Statement stmt, Connection conn){
		if (rst != null) {				
			try {
				rst.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
			rst = null;
		}
		if (stmt != null) {				
			try {
				stmt.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
			stmt = null;
		}
		if (conn != null) {
			try {
				conn.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
			conn = null;
		}
	}
}

这样一来,我们再写第一章中的代码时,会是如下这个样子:

package com.jimmy.MyDBUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

import org.junit.Test;

public class MyJDBCUtilsTest {
	@Test
	public void testSelect() throws Exception{
		Connection conn = null;
		PreparedStatement ps = null;
		
		conn = MyJDBCUtils.getConnection();  //获得连接
		ps = conn.prepareStatement("select * from emp");
		ResultSet rts = ps.executeQuery();
		while (rts.next()) {
			System.out.println(rts.getString(2));
		}
		MyJDBCUtils.closeRes(rts, ps, conn);  //关闭资源
	}
}

这样一来,获得连接和关闭资源的代码被大大的简化了,关键是我们写的封装代码类可以重复使用。

当然,我们只是简单的封装,后面会有第三方jar包完成更简化的封装。


第三章:连接池(也叫数据源)解决单连接问题

我们可以自己写一个类,实现连接池,思路如下:

首先创建10个连接对象conn,然后将这10个conn放到一个List中,每次使用时,从List中取出一个,用完后放回List。较麻烦,就不实现了。

三方库大多都是基于以上思想实现了连接池,那么我们就来介绍一个第三方jar包:C3P0包(点击下载jar包

下载解压后,将lib包里的c3p0-0.9.1.2.jar添加到BuildPath中去。

1,首先在src路径下新建一个配置文件:“c3p0-config.xml”,名称固定。

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
  <default-config>
	<property name="driverClass">com.mysql.jdbc.Driver</property>
	<property name="jdbcUrl">jdbc:mysql://localhost:3306/user</property>
	<property name="user">root</property>
	<property name="password">123456</property>
    	<property name="initialPoolSize">10</property>
    	<property name="maxIdleTime">30</property>
    	<property name="maxPoolSize">100</property>
    	<property name="minPoolSize">10</property>
  </default-config>
</c3p0-config>


2,新建一个类:C3P0Utils.java,其封装了C3P0提供的一些方法。

package com.jimmy.C3P0;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import javax.sql.DataSource;

import com.mchange.v2.c3p0.ComboPooledDataSource;


public class C3P0Utils {
	//得到一个数据源(连接池)对象
	private static DataSource ds = new ComboPooledDataSource();
	//对外提供返回数据源的方法
	public static DataSource getDs() { return ds;}
	
	//封装了数据源从池中获取拿到连接的方法
	public static Connection getConnection() {
		try {
			return ds.getConnection();
		} catch (SQLException e) {
			throw new RuntimeException("服务器异常");
		}
	}
	
	//关闭资源方法
	public static void closeRes(Connection conn, Statement stmt, ResultSet rts) {
		if(rts!=null){
			try {
				rts.close();    //关闭对象
			} catch (Exception e) {
				e.printStackTrace();
			}
			rts = null;
		}
		if(stmt!=null){
			try {
				stmt.close();    //关闭对象
			} catch (Exception e) {
				e.printStackTrace();
			}
			stmt = null;
		}
		if(conn!=null){
			try {
				conn.close();   //那么,这里的close()方法不再是关闭连接,而是将conn放回了池中。
			} catch (Exception e) {
				e.printStackTrace();
			}
			conn = null;
		}
	}
}

那么,我们来写一个测试类:

package com.jimmy.C3P0;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

import org.junit.Test;

public class C3P0test {
	@Test
	public void test() {
		Connection conn = null;
		PreparedStatement ps = null;
		
		try {
			conn = C3P0Utils.getConnection();
			ps = conn.prepareStatement("INSERT INTO account(username,money) VALUES(?,?)");
			ps.setString(1, "jimmy");
			ps.setDouble(2, 521);
			ps.executeUpdate();
		} catch (SQLException e) {
			e.printStackTrace();
		} finally{
			C3P0Utils.closeRes(conn, ps, null);
		}
	}
}

那么,测试代码看来与第二章中我们自己写的代码很像,不过代码背后真实千差万别。


第四章:DBUtils.jar包

这个包是由apache提供的,是对jdbc的进一步封装(执行sql语句将只有2行代码),并且支持线程池(也叫数据源)。一起来看看吧。

首先下载jar包(点击下载),添加commons-dbutils-1.4.jar到Build Path中。


1,开发中,往往要将数据库中的每条数据封装到一个java对象中去,或者将从网页输入中得到的数据也封装到java对象中去。

所以在使用DBUtils之前,要创建一个实体类,该实体类的成员变量要跟数据库表的列名一样。

比如:DB中有个User表,字段名和类型如下;

id int,
username varchar(20),
password varchar(20),
email varchar(20),
birthday varchar(20)

那么我们就要创建一个java类:

package com.jimmy.DBUtils;

import java.io.Serializable;

public class User implements Serializable{
	//成员变量名应该与DB中表的列名一模一样
	private int id;
	private String username;
	private String password;
	private String email;
	private String birthday;
	
	//自动生成成员变量的set和get方法
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	public String getBirthday() {
		return birthday;
	}
	public void setBirthday(String birthday) {
		this.birthday = birthday;
	}
	
	//toString()方法只是为了看效果。
	@Override
	public String toString() {
		return "User [id=" + id + ", username=" + username + ", password="
				+ password + ", email=" + email + ", birthday=" + birthday
				+ "]";
	}
}

2,本案例要用到连接池,我们用上一章中C3P0Utils.java类提供的返回连接池方法:getDs()方法。

然后我们就可以很轻松地取出数据了。

package com.jimmy.DBUtils;

import java.util.List;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.junit.Test;

import com.jimmy.C3P0.C3P0Utils;

public class DBUtilsCRUDDemo1 {

	
	@Test
	public void testSelect2() throws Exception{
		//1,创建QueryRunner对象,并得到c3p0提供的连接池。
		QueryRunner qr = new QueryRunner(C3P0Utils.getDs());
		//2,当query方法执行了select语句后,将结果集以参数的形式传递给第2个参数,第2个参数将结果封装到User对象中,最后将各个对象放进List中.
		List<User> list = qr.query("select * from user where id=?", new BeanListHandler<User>(User.class),1);
		
		for (User user : list) {
			System.out.println(user);
		}
	}
}
这样就取出了id为1的那行数据。

这样可以看出,操作数据库就只有2行代码了。不仅简化了重复代码,而且使用到了连接池技术。解决了一开始我们提出的2个弊端。


往后还会学习到各种各样的jdbc框架,学到了就再来补充。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值