1. Connection
Connection是JDBC中代表数据库连接的接口。Connection对象通常友DriverManager和DataSource的getConnection()方法产生。其中DataSource主要有3种类型:标准DataSource、提供连接池的ConnectionPoolDataSource和实现分布式事务的XADataSource。
1.1 DriverManager
动态加载驱动,获得连接,示例如下:
package com.weportal.jdbc; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; public class ComputerAccess ... { public static void main(String[] args) ...{ Connection con = null; try ...{ //加载MySQL数据库驱动 Class.forName("org.gjt.mm.mysql.Driver"); //设置访问属性 Properties prop = new Properties(); prop.setProperty("user", "root"); prop.setProperty("password", "passwd"); //打开数据库连接并连接到指定的URL con = DriverManager.getConnection( "jdbc:mysql://localhost:3306/hibernate", prop); } catch (ClassNotFoundException e) ...{ e.printStackTrace(); } catch (SQLException e) ...{ e.printStackTrace(); } try ...{ //编辑SQL数据库语句 Statement sm = con.createStatement(); String query = "select cpu from computer;"; //执行SQL查询语句 ResultSet rs = sm.executeQuery(query); //从返回结果集中取出结果 while (rs.next()) ...{ String cpu = rs.getString("cpu"); System.out.println(cpu); } //关闭数据库连接 con.close(); } catch (SQLException e1) ...{ e1.printStackTrace(); } }}1.2 标准DataSource
由数据库驱动提供。下面例子中使用了MySQL数据库驱动软件提供的标准DataSource实现。
package com.weportal.jdbc; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import com.mysql.jdbc.jdbc2.optional.MysqlDataSource; public class BasicDataSourceTest ... { public static void main(String[] args) throws SQLException ...{ MysqlDataSource ds = new MysqlDataSource(); ds.setURL("jdbc:mysql://localhost:3306/hibernate"); ds.setUser("root"); ds.setPassword("passwd"); Connection con = ds.getConnection(); //编辑SQL数据库语句 Statement sm = con.createStatement(); String query = "select cpu from computer;"; //执行SQL查询语句 ResultSet rs = sm.executeQuery(query); //从返回结果集中取出结果 while (rs.next()) ...{ String cpu = rs.getString("cpu"); System.out.println(cpu); } //关闭数据库连接 con.close(); }}1.3 ConnectionPoolDataSource
由数据库驱动或者应用服务器提供。实际的数据库访问过程需要频繁的进行数据库的连接,为了提高效率,JDBC加入了连接池的机制:每次进行连接时,都会首先请求连接池中的连接,如果连接池中没有可用连接,则创建新的物理连接。连接池需要实现对可用连接的缓冲管理和响应处理。实例如下:
1.3.1 C3P0连接池
C3P0是一个开放源代码的JDBC连接池,它在lib目录中与Hibernate一起发布,包括了实现jdbc3和jdbc2扩展规范说明的Connection和Statement池的DataSources对象。实例如下:
package com.weportal.jdbc.c3p; import java.sql.Connection; import java.sql.ResultSet; import java.sql.Statement; import com.mchange.v2.c3p0.ComboPooledDataSource; public class C3P0Test ... { public static void main(String[] args) throws Exception ...{ //创建C3P0提供的连接池数据源 ComboPooledDataSource cpds = new ComboPooledDataSource(); //设置数据库驱动 cpds.setDriverClass("org.gjt.mm.mysql.Driver"); //设置JDBC的URL cpds.setJdbcUrl("jdbc:mysql://localhost:3306/hibernate"); //设置用户名 cpds.setUser("root"); //设置密码 cpds.setPassword("passwd"); //从连接池数据源获取数据库连接 Connection con = cpds.getConnection(); //编辑SQL数据库语句 Statement sm = con.createStatement(); String query = "select cpu from computer;"; //执行SQL查询语句 ResultSet rs = sm.executeQuery(query); //从返回结果集中取出结果 while (rs.next()) ...{ String cpu = rs.getString("cpu"); System.out.println(cpu); } //关闭数据库连接 con.close(); }}1.3.2 PooledDataSource与JNDI
利用连接池实现的DataSource是一个系统中需要反复调用的资源,通常被注册到JNDI,以便于被其他应用程序使用。示例如下,注意这个例子使用的JNDI服务来自Apache的name包naming-common.jar,运行时要将其导入项目。
package com.weportal.jdbc.c3p;import java.sql.Connection;import java.sql.ResultSet;import java.sql.Statement;import java.util.Hashtable;import javax.naming.Context;import javax.naming.InitialContext;import javax.sql.DataSource;import com.mchange.v2.c3p0.ComboPooledDataSource; public class C3P0JNDITest ... { public static void main(String[] args) throws Exception ...{ Hashtable table = new Hashtable(); //设置JNDI的工厂类 table.put(Context.INITIAL_CONTEXT_FACTORY, "org.apache.naming.java.javaURLContextFactory"); //初始化JNDI上下文 InitialContext ctx = new InitialContext(table); //创建C3P0提供的连接池数据源 ComboPooledDataSource cpds = new ComboPooledDataSource(); //设置数据库驱动 cpds.setDriverClass("org.gjt.mm.mysql.Driver"); //设置JDBC的URL cpds.setJdbcUrl("jdbc:mysql://localhost:3306/hibernate"); //设置用户名 cpds.setUser("root"); //设置密码 cpds.setPassword("passwd"); //设置连接池的初始大小 cpds.setInitialPoolSize(10); //把数据源绑定到JNDI,名称是"hibernateDS" ctx.bind("hibernateDS", cpds); //从JNDI查找数据源 DataSource ds = (DataSource) ctx.lookup("hibernateDS"); //从连接池数据源获取数据库连接 Connection con = ds.getConnection(); //编辑SQL数据库语句 Statement sm = con.createStatement(); String query = "select cpu from computer;"; //执行SQL查询语句 ResultSet rs = sm.executeQuery(query); //从返回结果集中取出结果 while (rs.next()) ...{ String cpu = rs.getString("cpu"); System.out.println(cpu); } //关闭数据库连接 con.close(); }}1.4 XADataSource
由应用服务器提供。
1.4.1 Tomcat中的数据源
在server.xml中Context配置resource即可。示例程序如下:
package com.weportal.jdbc; import java.io.IOException; import java.io.PrintWriter; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.sql.DataSource; public class DataSourceServlet extends HttpServlet ... { private DataSource ds; /**//* (non-Javadoc) * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException ...{ PrintWriter out = response.getWriter(); try ...{ Connection con = ds.getConnection(); //编辑SQL数据库语句 Statement sm = con.createStatement(); String query = "select cpu from computer;"; //执行SQL查询语句 ResultSet rs = sm.executeQuery(query); //从返回结果集中取出结果 while (rs.next()) ...{ String cpu = rs.getString("cpu"); out.println(cpu); } //关闭数据库连接 con.close(); } catch (SQLException e) ...{ e.printStackTrace(); } } /**//* (non-Javadoc) * @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException ...{ super.doGet(request, response); } /**//* (non-Javadoc) * @see javax.servlet.Servlet#init(javax.servlet.ServletConfig) */ public void init(ServletConfig config) throws ServletException ...{ super.init(config); try ...{ InitialContext ctx = new InitialContext(); ds = (DataSource) ctx.lookup("java:comp/env/jdbc/hibernate"); } catch (NamingException e) ...{ e.printStackTrace(); } }}2. Statement
JDBC通过Statement完成执行SQL的过程,JDBC中包含3种Statement:Statement、PreparedStatement、CallableStatement,它们之间是依次继承的关系,其中PreparedStatement是实现Hibernate的基础。
2.1 Statement
用于执行静态的SQL语句。
Statement的主要方法 方法名对应SQL操作返回结果executeUpdateinsert、update、delete受影响的行数executeQuery-单一ResultSetexecute-多个ResultSet
2.1.1 executeUpdate() demo
package com.weportal.jdbc.statement; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; public class ExcuteUpdateTest ... { public static void main(String[] args) ...{ Connection con = null; try ...{ //加载MySQL数据库驱动 Class.forName("org.gjt.mm.mysql.Driver"); //设置访问属性 Properties prop = new Properties(); prop.setProperty("user", "root"); prop.setProperty("password", "passwd"); //打开数据库连接并连接到指定的URL con = DriverManager.getConnection( "jdbc:mysql://localhost:3306/hibernate", prop); } catch (ClassNotFoundException e) ...{ e.printStackTrace(); } catch (SQLException e) ...{ e.printStackTrace(); } try ...{ //编辑SQL数据库语句 Statement sm = con.createStatement(); String query = "insert into computer(id,cpu,display) values(NULL,'Intel 奔腾 P4 2.4B GHz','LG 563LS');"; //执行SQL查询语句 int result = sm.executeUpdate(query); System.out.println(result); //关闭数据库连接 con.close(); } catch (SQLException e1) ...{ e1.printStackTrace(); } }}2.1.2 execute() demo
package com.weportal.jdbc.statement; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; public class ExcuteTest ... { public static void main(String[] args) ...{ Connection con = null; try ...{ //加载MySQL数据库驱动 Class.forName("org.gjt.mm.mysql.Driver"); //设置访问属性 Properties prop = new Properties(); prop.setProperty("user", "root"); prop.setProperty("password", "passwd"); //打开数据库连接并连接到指定的URL con = DriverManager.getConnection( "jdbc:mysql://localhost:3306/hibernate", prop); //DatabaseMetaData dmd = con.getMetaData(); //System.out.println(dmd.getSchemaTerm()); //System.out.println(dmd.getCatalogTerm()); } catch (ClassNotFoundException e) ...{ e.printStackTrace(); } catch (SQLException e) ...{ e.printStackTrace(); } try ...{ //编辑SQL数据库语句 Statement sm = con.createStatement(); //String query = "insert into computer(id,cpu,display) values(NULL,'Intel 奔腾 P4 2.4B GHz','LG 563LS');"; String query = "select * from computer;"; //执行SQL查询语句 boolean result = sm.execute(query); if (!result) ...{ System.out.println(sm.getUpdateCount()); } else ...{ ResultSet rs = sm.getResultSet(); while (rs.next()) ...{ String id = rs.getString("id"); System.out.println(id); } } //关闭数据库连接 con.close(); } catch (SQLException e1) ...{ e1.printStackTrace(); } }}2.1.3 executeQuery() demo
package com.weportal.jdbc.statement; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; public class ExcuteQueryTest ... { public static void main(String[] args) ...{ Connection con = null; try ...{ //加载MySQL数据库驱动 Class.forName("org.gjt.mm.mysql.Driver"); //设置访问属性 Properties prop = new Properties(); prop.setProperty("user", "root"); prop.setProperty("password", "passwd"); //打开数据库连接并连接到指定的URL con = DriverManager.getConnection( "jdbc:mysql://localhost:3306/hibernate", prop); } catch (ClassNotFoundException e) ...{ e.printStackTrace(); } catch (SQLException e) ...{ e.printStackTrace(); } try ...{ //编辑SQL数据库语句 Statement sm = con.createStatement(); String query = "select * from computer;"; //执行SQL查询语句 ResultSet rs = sm.executeQuery(query); while (rs.next()) ...{ String id = rs.getString("id"); System.out.println(id); } //关闭数据库连接 con.close(); } catch (SQLException e1) ...{ e1.printStackTrace(); } }}2.2 PreparedStatement
PreparedStatement对SQL执行预编译过程,执行速度较快;IN参数以占位符“?”的方式添加。示例如下:
package com.weportal.jdbc.preparedstatement; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Properties; public class PreparedStatementQuery ... { public static void main(String[] args) ...{ Connection con = null; try ...{ //加载MySQL数据库驱动 Class.forName("org.gjt.mm.mysql.Driver"); //设置访问属性 Properties prop = new Properties(); prop.setProperty("user", "root"); prop.setProperty("password", "passwd"); //打开数据库连接并连接到指定的URL con = DriverManager.getConnection( "jdbc:mysql://localhost:3306/hibernate", prop); } catch (ClassNotFoundException e) ...{ e.printStackTrace(); } catch (SQLException e) ...{ e.printStackTrace(); } try ...{ String query = "select * from computer where id = ?;"; //编辑SQL数据库语句 PreparedStatement ps = con.prepareStatement(query); ps.setLong(1, 2); //执行SQL查询语句 ResultSet rs = ps.executeQuery(); while (rs.next()) ...{ String cpu = rs.getString("cpu"); System.out.println(cpu); } //关闭数据库连接 con.close(); } catch (SQLException e1) ...{ e1.printStackTrace(); } }}2.3 CallableStatement
提供了调用数据库存储过程的方法。调用存储过程需要使用转义语法来完成,转义语法可以包括结果参数,也可以不包括结果参数。
2.3.1 创建存储过程
create procedure select_computer() begin select id from hibernate.computer; end2.3.2 demo
package com.weportal.jdbc.callablestatement; import java.sql.CallableStatement; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; public class CallableStatementQuery ... { public static void main(String[] args) ...{ Connection con = null; try ...{ //加载MySQL数据库驱动 Class.forName("org.gjt.mm.mysql.Driver"); //设置访问属性 Properties prop = new Properties(); prop.setProperty("user", "root"); prop.setProperty("password", "passwd"); //打开数据库连接并连接到指定的URL con = DriverManager.getConnection( "jdbc:mysql://localhost/hibernate", prop); } catch (ClassNotFoundException e) ...{ e.printStackTrace(); } catch (SQLException e) ...{ e.printStackTrace(); } try ...{ String produce = "CREATE PROCEDURE SELECT_COMPUTER() BEGIN SELECT id FROM hibernate.Computer; END"; Statement stm = con.createStatement(); stm.executeUpdate(produce); //String query = "select * from computer where id = ?;"; //编辑SQL数据库语句 CallableStatement cs = con.prepareCall("{call SELECT_COMPUTER()}"); //cs.setLong(1,1); //执行SQL查询语句 ResultSet rs = cs.executeQuery(); while (rs.next()) ...{ String id = rs.getString("id"); System.out.println(id); } //关闭数据库连接 con.close(); } catch (SQLException e1) ...{ e1.printStackTrace(); } }}3. 事务
使用Savepoint可以记录当前的状态并标记为一个Savepoint,以后的操作可以退回到这个SavePoint。示例如下:
package com.weportal.jdbc.savepoint; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Savepoint; import java.sql.Statement; import java.util.Properties; public class SavepointTest ... { public static void main(String[] args) ...{ Connection con = null; try ...{ //加载MySQL数据库驱动 Class.forName("org.gjt.mm.mysql.Driver"); //设置访问属性 Properties prop = new Properties(); prop.setProperty("user", "root"); prop.setProperty("password", "passwd"); //打开数据库连接并连接到指定的URL con = DriverManager.getConnection( "jdbc:mysql://localhost:3306/hibernate", prop); con.setAutoCommit(false); } catch (ClassNotFoundException e) ...{ e.printStackTrace(); } catch (SQLException e) ...{ e.printStackTrace(); } String query01 = "insert into computer(id,cpu,display) values(NULL,'Intel 奔腾 P4 2.3B GHz','LG 563LS');"; String query02 = "insert into computer(id,cpu,display) values(NULL,'Intel 奔腾 P4 2.4B GHz','LG 563LS');"; try ...{ Statement stm = con.createStatement(); stm.executeUpdate(query01); Savepoint point01 = con.setSavepoint("a"); stm.executeUpdate(query02); //第二次的插入操作被取消了 con.rollback(point01); con.commit(); con.close(); } catch (SQLException e2) ...{ e2.printStackTrace(); } }}3. ResultSet
ResultSet的可更新和可滚动属性是相互独立的。
4. Blob和Clob
在JDBC中,Blob和Clob用来存储大数据对象。Blob用来存储二进值大对象,Clob用于存储字符型大对象。
4.1 创建表
create table `hibernate`.`bigimage`( `name` varchar ( 30 ), `value` longblob, `id` bigint default '' not null , primary key (`id`) ); create unique index ` PRIMARY ` on `hibernate`.`bigimage`(`id`);4.2 demo
package com.weportal.jdbc.blob; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.Properties; public class FileToBlob ... { public static void main(String[] args) ...{ Connection con = null; try ...{ //加载MySQL数据库驱动 Class.forName("org.gjt.mm.mysql.Driver"); //设置访问属性 Properties prop = new Properties(); prop.setProperty("user", "root"); prop.setProperty("password", "passwd"); //打开数据库连接并连接到指定的URL con = DriverManager.getConnection( "jdbc:mysql://localhost:3306/hibernate", prop); } catch (ClassNotFoundException e) ...{ e.printStackTrace(); } catch (SQLException e) ...{ e.printStackTrace(); } try ...{ String query = "insert into bigImage(id,name,value) values(?,?,?);"; //编辑SQL数据库语句 PreparedStatement ps = con.prepareStatement(query); ps.setLong(1, 4); ps.setString(2, "photo001"); File imageFile = new File("test.bmp"); FileInputStream is = new FileInputStream(imageFile); ps.setBinaryStream(3, is, (int) imageFile.length()); //执行SQL查询语句 ps.executeUpdate(); //关闭数据库连接 con.close(); } catch (SQLException e1) ...{ e1.printStackTrace(); } catch (FileNotFoundException e2) ...{ e2.printStackTrace(); } }}参考《精通Hibernate》刘洋 著