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

来源:互联网 发布:中国的参政党知乎 编辑:程序博客网 时间:2024/06/06 00:31

前言:

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 {@Testpublic 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 {@Testpublic 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()方法只是为了看效果。@Overridepublic 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 {@Testpublic 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框架,学到了就再来补充。




1 0
原创粉丝点击