资讯详情

java基础 - 2

JAVA编程语言和JDBC

正确编写,遵守规范Java程序可以在任何启用中重新编译Java在技术平台上运行。Java编程语言已经完全规定。根据定义,启用Java已知的核心库必须支持技术平台。java.sql包或javax.sql包或者JDBC就是这样一个库,它们可以视为ODBC可移植版本,本身就是一个重要的标准。JAVA编程语言和JDBC一起使用可以为编写数据库应用程序提供正确的可移植解决方案。注:虽然可移植的应用程序和标准数据库界面是重大结果,但不要忘记,历史和竞争有时是无聊的,各种数据库都没有完全标准化。这可能意味着必须根据特定数据库的性能或内部调整(甚至在同一平台上)找到"最低公分母"。无论采用标准SQL,ODBC,JDBC,或者其他解决方案于其他解决方案中。最后需要指出的是,JDBC驱动程序是JAVA类,它实现JDBC驱动程序接口可以是特殊的数据库转换程序(通常是SQL)请求。毫无疑问,驱动程序在这里起着重要的作用。大多数数据库供应商现在提供驱动程序来实现特定的系统JDBC API。这些通常是免费的。也可以获得第三方驱动程序,成本从免费到巨大。

JDBC编程的核心包是java.sql其结构如下图所示:

JDBC编程的步骤

第一:加载驱动程序

与特定数据库相连,JDBC必须加载相应的驱动程序。

try {

Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");

} catch (ClassNotFoundException e) {

e.printStackTrace();

}

// 加载Oracle的驱动程序

Class.forName("oracle.jdbc.driver.OracleDriver");

// 加载Microsoft SQL Server的驱动程序 Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver");

第二:要将"驱动程序"传递到DriverManager,然后获得"连接"。

DriverManager类的getConnection(String url,String user, String password)该方法用于与数据库建立连接。JDBC使用特殊驱动程序的驱动程序JDBC URL作为一种自我识别方法。

JDBC URL的格式为:jdbc : <子协议名> : <子名称>

子协议(sub-protocol)与JDBC驱动程序可以是相关的odbc,oracle,db2,mysql,microsoft等等,根据实际的JDBC驱动程序厂商而不同。数据库定位器(database locator)是与驱动程序有关的指示器,用于唯一指定应用程序要和哪个数据库进行交互。根据驱动程序的类型,该定位器可能包括主机名,端口和数据库系统名。

try{

String url="jdbc:odbc:myodbc";

Connection con=DriverManager.getConnection(url);

// 或者

Connection con=

DriverManager.getConnection(url,user,password);

}catch(SQLException e){

e.printStackTrace();

}

// 1.Microsoft SQL Server的URL

url="jdbc:Microsoft:sqlserver://192.168.0.1:1433;databasename=mydb";

127.0.0.1 也可以用字符串 "localhost"代替

// 2.Oracle 的URL

url="jdbc:oracle:thin:@192.168.0.1:1521:goudan";

第三:创建语句,Statement ,PreparedStatement,或CallableStatement,并将它们用于更新数据库或执行查询。

Statement 对象用于将 SQL 语句发送到数据库中。实际上有三种 Statement 对象,它们都作为在给定连接上执行 SQL语句的对象:Statement、PreparedStatement( 继承Statement )和 CallableStatement(继承PreparedStatement)。它们都专用于发送特定类型的 SQL 语句: Statement 对象用于执行不带参数的简单 SQL语句;PreparedStatement 对象用于执行带或不带 IN 参数的预编译 SQL 语句;CallableStatement对象用于执行对数据库已存储过程的调用。

第四:查询返回包含有已请求数据的ResultSet,该ResultSet是按类型检索的。

ResultSet包含符合SQL语句中条件的所有行,并且它通过一套get方法(这些get方法可以访问当前行中的不同列)提供了对这些行中数据的访问。

第五:DatabaseMetaData和ResultSetMetaData接口可以用来提供有关数据库或ResultSet的信息。

实例分析

例1:通过ODBC建立连接

? 配置WINDOWS下ODBC详细步骤参考 <<ODBC连接步骤.doc>>

? 代码如下:

import java.sql.*;

public class ODBCTest {

public static void main(String[] args) {

Connection con = null;

try {

// 加载ODBC驱动

(1)Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");

// 通过驱动管理器(DriverManager)获得连接

(2)con = DriverManager.getConnection("jdbc:odbc:myodbc",

"pubuse","123");

// 如果连接不成功,就会出现异常,不会执行下面这个语句

System.out.println("connect success!");

} catch (Exception e) {// 如果出现异常,会打印堆栈里异常的信息

e.printStackTrace();

} finally {// 用完后,关闭连接,释放资源

try {

if (con != null) // 防止出现内存泄露

con.close();

} catch (Exception e) {

e.printStackTrace();

}

}

}

}

例2:通过SQLSERVER 提供的驱动程序获得连接

? 下面通过SQLSERVER提供的三个驱动获得连接。三个jar文件的名字分别为:msbase.jar,mssqlserver.jar,msutil.jar 然后设置classpath环境变量指向这三个路径。假如这三个文件放在d:\mssqldriver 目录下,如下图所示:

? 然后在系统环境变量classpath里面设置这三个jar文件,这样的话就可以在任何的dos命令窗口里面使用。

也可以在一个dos窗口里面设置。这样的话是只在该窗口下有效。

? 部分代码如下:

………

try {

// 加载SQLSERVER的驱动程序Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver");

// 通过驱动来获得一个连接

con = DriverManager.getConnection(

"jdbc:microsoft:sqlserver://localhost:1433;"

+ "databasename=pubs", "sa", "");

System.out.println("connect success!");

} catch (Exception e) {

e.printStackTrace();

}

………

例3:通过ORACLE提供的驱动程序获得连接

? 下面介绍通过ORACLE提供的驱动程序获得连接。只有一个jar文件:classes12.jar 同上设置环境变量classpath 指向该jar文件。

部分代码如下

………

try {

// 加载ORACLE9i的驱动程序

Class.forName("oracle.jdbc.driver.OracleDriver");

// 获得连接 oracle数据库的端口号:1521 数据服务器的名字叫itjob

// 登陆的用户名为system,密码为:system (默认密码为manager)

con = DriverManager.getConnection(

"jdbc:oracle:thin:@127.0.0.1:1521:itjob",

"system","system");

System.out.println("con ok");

} catch (Exception e) {

e.printStackTrace();

}

………

例4:通过数据源获得连接

使用JDBC API的一个主要好处就是独立于数据库的编程,因为大部分JDBC应用程序都可以被轻易地转换到不同的数据库。然而,仍然有两个主要的内容与特定的数据库有关,即JDBC Driver类和JDBC URL。

随着JDBC API的升级,数据源技术的引入,可以提高数据库访问的灵活性。本质上,DataSource对象表示一个特殊的数据源。除了将数据库和专门的JDBC驱动程序信息封装到一个单独的,标准化的对象中之外,数据源可以作为Connection工厂,并为设置和获取DataSource对象进行成功操作所需要的特定属性提供方法。DataSource对象可能需要的一些标准属性包括:

? databaseName

? serverName

? portNumber

? username

? password

使用数据源的另一个好处就是和安全有关的敏感信息,如用户名,密码甚至数据库服务器只在一处编码,这可以由系统管理员完成。虽然和DataSource对象的交互可以用图形应用程序完成,但真正看到运行的示例是有指导性的。虽然DataSource对象的概念很简单,但为了在Java应用程序中使用,DataSource对象是使用Java名称和目录接口(JNDI)来引用的。

下面首先介绍下JNDI的相关概念。JNDI是个JAVA API,它包括名称和目录服务器的概念,道理和JDBC与数据库进行通讯的概念差不多。如:硬盘通过与磁道和扇区打交道工作,但用户只关心文件名和目录,文件系统管理名称服务,该服务将给定的文件名和硬盘上特定的位置相关联。另一个简单的示例就是Web,多数用户只关心Web站点的名称,如www.5itjob.com,并不关心底层的IP地址。然而,TCP/IP通讯是通过使用IP地址,而不是人类能看懂的名称进行的。两个表示法之间的转换是通过DNS(域名系统,Domain Name System)完成的。虽然JNDI用自己的方式提供了一个丰富和有用的API,我们的需求却简单得多。简短地说,我们需要知道怎样做四件事:

? 创建名称并将其绑定到一个Java对象

? 查询名称以检索Java对象

? 删除一个名称

? 重新绑定名称到一个新的Java对象

首先要先加载数据源的驱动程序。让环境变量classpath指向下面几个jar文件

2,代码如下:

import java.util.Hashtable;

import javax.naming.*;

import javax.naming.directory.*;

import java.sql.*;

import javax.sql.*;

import com.microsoft.jdbcx.sqlserver.SQLServerDataSource;

public class JNDIServer {

// First we define the relevant parameters for this datasource

private String serverName = "192.168.0.1";

private int portNumber = 1433;

private String login = "student";

private String password = "student";

private String databaseName = "mydb";

private String filePath = "jdbc/mydatasource";

public JNDIServer() {

Hashtable env = new Hashtable();

env.put(Context.INITIAL_CONTEXT_FACTORY,

"com.sun.jndi.fscontext.RefFSContextFactory");

try {

// 创建初始化上下文环境

Context ctx = new InitialContext(env);

// 如果filePath已经绑定过了,那么先解除绑定

ctx.unbind(filePath);

// 创建SQLServerDataSource

SQLServerDataSource ds = new SQLServerDataSource();

// 设置数据源的参数

ds.setServerName(serverName);

ds.setPortNumber(portNumber);

ds.setDatabaseName(databaseName);

ds.setUser(login);

ds.setPassword(password);

ds.setDescription("JDBC DataSource Connection");

// 绑定 JDBC 数据源

ctx.bind(filePath, ds);

ctx.close();

System.out.println("DataSource Created Success!");

} catch (Exception e) {

e.printStackTrace();

}

}

public static void main(String args[]) {

new JNDIServer();

}

}

运行成功后,会在控制台打印:DataSource Created Success!

同时在运行该类所在的磁盘根目录下生成".bindings"文件,如下图:

数据源创建好之后,下面开始使用数据源。

代码如下:

import java.util.Hashtable;

import javax.naming.*;

import java.sql.*;

import javax.sql.*;

public class UseJNDI {

public static void main(String args[]) {

Connection con = null;

try {

Hashtable env = new Hashtable();

env.put(Context.INITIAL_CONTEXT_FACTORY,

"com.sun.jndi.fscontext.RefFSContextFactory");

Context ctx = new InitialContext(env);

// 获得数据源对象

DataSource ds =

(DataSource) ctx.lookup("jdbc/mydatasource");

// 通过数据源对象获得一个连接

con = ds.getConnection();

// 如果连接不成功,就会出现异常,不会执行下面这个语句

System.out.println("connect success!");

} catch (Exception e) {

e.printStackTrace();

} finally {

try {

if (con != null)// 用完连接后,要关闭释放

con.close();

} catch (Exception e) {

e.printStackTrace();

}

}

}

}

下面是删除JNDI的引用的代码:

import java.util.Hashtable;

import javax.naming.*;

import java.sql.*;

import javax.sql.*;

public class DeleteJNDI {

public static void main(String[] args) {

Hashtable env = new Hashtable();

env.put(Context.INITIAL_CONTEXT_FACTORY,

"com.sun.jndi.fscontext.RefFSContextFactory");

try {

Context ctx = new InitialContext(env);

ctx.unbind("jdbc/pubs");

ctx.close();

System.out.println("delete succeed!");

} catch (Exception ex) {

System.err.println("ERROR: " + ex.getMessage());

}

}

}

例5:通过连接池获得连接

首先请根据我们在上面创建数据库连接的经验,来思考下列问题:

? 为什么需要连接池?

? 什么是PooledConnection?

? 初始化连接池

? 使用连接池

当使用DriverManager或者DataSource方法来获取数据库连接时,每个对新数据库连接的请求都会导致很大的开销。如果频繁地获取新的连接,将会影响性能问题。这在Web服务器端编程的时候尤为明显。请求一个新的Connection对象会带来大量的开销和很多潜在的错误。为了最小化开销,为什么在我们使用完数据库连接后不是重新使用它们,而是删除它们呢?JDBC设计者在创建接口ConnectionPoolDataSource时使用这种流行的设计模式,这允许您创建数据库连接池,其中的连接在关闭后可以重用,而不是删除。

PooledConnection是一个特殊类型的数据库连接,在关闭时不会被删除,不象常规的Connection对象(当常规的连接不再被使用时,垃圾收集器能删除它们)。相反,PooledConnection被缓存以备将来再次使用,从而可能带来大幅度的性能提升。使用数据库连接池几乎和使用DataSource对象一样。首先,不是创建一个实现DataSource接口的类的实例,而是创建了一个实现了ConnectionPoolDataSource接口的类的实例。可以像以前一样使用JNDI来绑定这个新的数据源到一个名称。要实际使用池化的数据源对象,调用ConnectionPooledDataSource(它接下来会建立数据库连接)上的getPooledConnection()得到一个PooledConnection对象。要创建将使用的Connection对象,调用PooledConnection对象(而不是以前的DriverManager或DataSource对象)上的getConnection().这种方法的一个额外的好处是,因为是自动处理,用ConnectionPool管理一定数量的数据库连接方便多了。如果你的客户机许可限制了能够同时连接到数据库的客户机的数目,这种自动化可能非常重要。

初始化连接池。下面的例子我们将使用SQLServer2000数据库和i-net软件的第三方驱动程序来创建PooledDataSource.所有与数据库相关的代码都包含在初始化或绑定过程中。

首先应该在classpath里面再指向名字为Merlia.jar的jar文件。

2,代码如下:

import com.inet.tds.PDataSource;

import java.util.Hashtable;

import javax.naming.*;

import com.microsoft.jdbcx.sqlserver.SQLServerDataSource;

public class JNDIofPooledDataSourceTest {

public static void main(String[] args) {

String serverName = "192.168.0.1";

String databaseName = "mydb";

String userName = "student";

String password = "student";

// 通过下面的名字可以获得一个池化的连接

String filePath = "jdbcPool/mydatasource";

int portNumber = 1433;

int poolSize = 10; // We want to create a pool with 10 connections.

Hashtable env = new Hashtable();

env.put(Context.INITIAL_CONTEXT_FACTORY,

"com.sun.jndi.fscontext.RefFSContextFactory");

try {

Context ctx = new InitialContext(env);

// 创建一个池化的数据源对象

PDataSource ds = new PDataSource();

ds.setServerName(serverName);

ds.setPortNumber(portNumber);

ds.setDatabaseName(databaseName);

ds.setUser(userName);

ds.setPassword(password);

ds.setDescription("i-Net PDataSource");

ds.setMaxPoolSize(poolSize);

// 绑定池化的数据源

ctx.bind(filePath, ds);

ctx.close();

System.out.println("PooledDataSource Created Success!");

} catch (Exception ex) {

System.err.println("ERROR: " + ex.getMessage());

}

}

}

一旦初始化了PooledDataSource,就能够在Java应用程序中使用它来创建数据库连接池。请看下面的例子:

import java.util.Hashtable;

import javax.naming.*;

import java.sql.*;

import javax.sql.*;

import java.io.*;

public class UseJNDIOfPooledDataSource {

public static void main(String[] args) {

Connection con = null;

try {

String filePath = "jdbcPool/mydatasource";

Hashtable env = new Hashtable();

env.put(Context.INITIAL_CONTEXT_FACTORY,

"com.sun.jndi.fscontext.RefFSContextFactory");

Context ctx = new InitialContext(env);

// 通过JNDI获得池化的数据源

ConnectionPoolDataSource ds =

(ConnectionPoolDataSource) ctx .lookup(filePath);

// 通过池化的数据源获得池化的连接

PooledConnection pcon = ds.getPooledConnection();

// 通过池化的连接获得连接

con = pcon.getConnection();

// 如果连接不成功,就会出现异常,不会执行下面这个语句

System.out.println("connect success!");

} catch (Exception e) {

e.printStackTrace();

} finally {

try {

if (con != null)// 用完连接后,要关闭释放

con.close();

} catch (Exception e) {

e.printStackTrace();

}

}

}

}

例6:总结数据库连接的各种方式

下面通过综合的例子来说明各种数据库的连接。

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.SQLException;

import java.util.Hashtable;

import javax.naming.Context;

import javax.naming.InitialContext;

import javax.sql.ConnectionPoolDataSource;

import javax.sql.DataSource;

import javax.sql.PooledConnection;

public class DBCon {

// 通过JDBC-ODBC桥获得连接

public static Connection getOdbcCon(String datasourcename, String name,String password)

throws ClassNotFoundException, SQLException {

String url = "jdbc:odbc:";

Connection con = null;

con = DriverManager.getConnection(url + datasourcename, name, password);

return con;

}

// 通过SQLSERVER的三个驱动,连接SQLSERVER2000数据库

public static Connection getSQLServerCon(String name, String password)

throws ClassNotFoundException, SQLException {

String url = "jdbc:microsoft:sqlserver://127.0.0.1:1433";

Connection con = null;

Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver");

con = DriverManager.getConnection(url, name, password);

return con;

}

// 通过ORACLE的驱动,连接ORACLE数据库

public static Connection getOracleCon(String name, String password)

throws ClassNotFoundException, SQLException {

Connection con = null;

Class.forName("oracle.jdbc.driver.OracleDriver");

// 获得连接 oracle数据库的端口号为:1521 数据服务器的名字叫goudan(作者外号)

String url = "jdbc:oracle:thin:@127.0.0.1:1521:goudan";

con = DriverManager.getConnection(url, name, password);

return con;

}

// 通过数据源获得连接

public static Connection getConnectionFromDataSource(String filePath)

throws javax.naming.NamingException, SQLException {

Connection con = null;

Hashtable env = new Hashtable();

env.put(Context.INITIAL_CONTEXT_FACTORY,

"com.sun.jndi.fscontext.RefFSContextFactory");

Context ctx = new InitialContext(env);

DataSource ds = (DataSource) ctx.lookup(filePath);

con = ds.getConnection();

return con;

}

// 通过连接池获得连接

public static Connection getConnectionFromPooledDataSource(String filePath)

throws javax.naming.NamingException, SQLException {

Connection con = null;

Hashtable env = new Hashtable();

env.put(Context.INITIAL_CONTEXT_FACTORY,

"com.sun.jndi.fscontext.RefFSContextFactory");

Context ctx = new InitialContext(env);

ConnectionPoolDataSource ds = (ConnectionPoolDataSource) ctx

.lookup(filePath);

PooledConnection pc = ds.getPooledConnection();

con = pc.getConnection();

return con;

}

}

内容总结

? JDBC(Java Database Connectivity)是Sun提供的一套数据库编程接口API,由Java语言编写的类、接口组成;通过这些类和接口JAVA可以方便的访问各种数据库中的数据。

? JDBC连接数据库的四种方式

? JDBC-ODBC桥,简单易用,只适用于WINDOW平台,适用于学习JDBC。

? 部分Java驱动程序(native-API partly-Java Driver),少用到。

? 网络驱动程序(net-protocol all-java driver(JDBC Proxy)),应用比较广。

? 纯Java驱动程序(native-protocal all-Java driver),它直接与数据库进行通讯,最好的一种连接。

? JDBC的编程步骤

? 加载驱动程序;

? 建立到数据库的连接对象Connection;

? 创建语句,Statement ,PreparedStatement,

或CallableStatement,并将它们用于更新数据库或执行查询;

? 查询返回包含有已请求数据的ResultSet;

? 通过SqlServer,Oracle的驱动程序连接数据库;

? JDBC数据源,连接池技术的实现原理及其优点

? 数据源技术的引入,可以提高数据库访问的灵活性

? 使用数据源,和安全有关的敏感信息,如用户名,密码甚至数据库服务器地址等信息只在一处编码。

? 使用连接池可以提高连接数据库的效率。

独立实践

1、 写一个SQLSERVER连接池的实现,访问pub数据库。

2、 写一个连接ORACLE数据库的实现,用scott用户登陆,操作emp表

3、 从控制台输入注册信息(用户名,密码,确认密码),写到数据库里面。

4、 从控制台输入用户名和密码,在数据库中并验证其有效性。(提示:需要编写的类有:User, Validation,DbUtil)。

5、 登陆成功后,从控制台输入一个表名,并从控制台打印该表里的数据。

第二十章:高级JDBC

学习目标

? 使用DDL,DML语言对数据库进行基本操作

? 预编译语句

? 使用事务

? 事务的级别控制

? 使用存储过程

? 操作元数据

? 可滚动的和可更新的结果集

? 批处理更新

? 字符大对象CLOB

? 二进制大对象BLOB

? RowSet 新特性

使用DDL,DML语言对数据库进行基本操作。

? 创建表并插入数据及修改数据:

import java.sql.Connection;

import java.sql.Statement;

public class CreateTable {

public static void main(String[] args) {

Connection con = null;

try {

// 通过连接池来获得一个连接

con = DBCon .getConnectionFromPooledDataSource("jdbcPool/mydatasource");

// 创建语句对象

Statement st = con.createStatement();

// 创建表的SQL语句

String sql = "create table student(id int,name char(30),age int)";

// 执行完SQL语句的结果

boolean b = st.execute(sql);

if (b) {

System.out.println("create success");

} else {

System.out.println("create fail");

}

// 插入数据到student表

sql = "insert into student values(1,'andy',47)"

+ "insert into student values(2,'jacky',53)"

+ "insert into student values(3,'周润发',51)"

+ "insert into student values(4,'谢贤',60)";

// 执行完SQL语句的结果

b = st.execute(sql);

if (b) {

System.out.println("insert success");

} else {

System.out.println("create fail");

}

// 更新表数据

sql = "update student set name='刘德华' where id=1";

int rows = st.executeUpdate(sql);

// 如果更新成功,rows肯定是大于1的值

if (rows > 0)

System.out.println("update success");

else

System.out.println("update fail");

} catch (Exception e) {

e.printStackTrace();

} finally {

try {

if (con != null)

con.close();

} catch (Exception e) {

e.printStackTrace();

}

}

}

}

查询数据库里的数据

Statement对象的executeQuery()方法一般用于执行一个select语句,它只返回一个结果集,要想把查询结果最后显示给用户,必须对ResultSet对象进行处理。ResultSet对象包括一个由查询语句返回的一个表,这个表中包含所有的查询结果。对ResultSet对象的处理必须逐行进行。ResultSet对象维持一个指向当前行的指针(类似于Iterator的用法)。最初,这个指针指向第一行之前。ResultSet的next()方法使这个指针移向下一行。因此,第一次使用next()方法将指针指向结果集的第一行,这是可以对第一行的数据进行处理。处理完毕后,使用next()方法,将指针移向下一行,继续处理第二行数据。next()方法的返回值是一个boolean值,若为true,则说明指针成功地移向下一行,可以对该行进行处理。若返回值是false,则说明没有下一行,即结果集已经处理完毕。按从左至右的顺序对各列进行处理可以获得较高的执行效率。ResultSet接口的getXXX()方法可以从某列中获得结果,XXX表示JDBC的数据类型。

请看下例:

import java.sql.Connection;

import java.sql.ResultSet;

import java.sql.ResultSetMetaData;

import java.sql.Statement;

public class ResultSetTest {

public static void main(String[] args) {

Connection con = null;

try {

con = DBCon

.getConnectionFromPooledDataSource("jdbcPool/mydatasource");

Statement st = con.createStatement();

String query = "select id,name from student";

// 获得一个结果集

ResultSet rs = st.executeQuery(query);

// 获得结果集的元数据(表及相关的信息)

ResultSetMetaData rsmt = rs.getMetaData();

// 得到结果集有几列

int num = rsmt.getColumnCount();

String[] columns = new String[num];

// 列的序号是从1开始的

for (int i = 0; i < num; i++)

columns[i] = rsmt.getColumnName(i + 1);

// 先输出列名

for (int i = 0; i < num; i++)

System.out.print(columns[i] + " ");

// 输出列名之后换行

System.out.println();

// 取出结果

while (rs.next()) {

// 输出每一行的值

for (int i = 1; i <= num; i++) {

String temp = rs.getString(i);

System.out.print(temp + " ");

}

System.out.println();

}

} catch (Exception e) {

e.printStackTrace();

} finally {

try {

// 用完后要关闭连接,释放资源

if (con != null)

con.close();

} catch (Exception e) {

e.printStackTrace();

}

}

}

}

输出结果为:(Eclipse环境)

预编译语句(PreparedStatement)

Statement对象在每次执行SQL语句时都将该语句传给数据库,在多次执行同一语句时,这样做效率较低。这时可以使用PreparedStatement对象.如果数据库支持预编译,它可以将SQL语句传给数据库作预编译,以后每次执行这个SQL语句时,速度就可以提高很多。如果数据库不支持预编译,则在语句执行时,才将其传给数据库。这对用户来说是透明的。PreparedStatement对象的SQL语句还可以接受参数。在语句中指出需要接受哪些参数,然后进行预编译。在每一次执行时,可以给SQL语句传输不同的参数,这样就大大提高了灵活性。PreparedStatement接口是Statement接口派生的子接口,因此它可以使用Statement接口中的方法。

代码

import java.sql.Connection;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.sql.ResultSetMetaData;

import java.sql.Statement;

public class PrepareStatementTest {

public static void main(String[] args) {

Connection con = null;

try {

con = DBCon

.getConnectionFromPooledDataSource("jdbcPool/mydatasource");

// 创建修改表的PrepareStatement SQL语句

String sql = "update student set name=? where id=?";

// 创建预编译语句对象

PreparedStatement st = con.prepareStatement(sql);

String[] names = new String[] { "梁朝伟", "贝壳汗母", "小罗", "霍元甲" };

for (int i = 0; i < names.length; i++) {

st.setString(1, names[i]);

st.setInt(2, i + 1);

st.executeUpdate();

}

st.close();

// 打印执行完SQL语句的结果

Statement stq = con.createStatement();

// 定义一个查询的SQL语句

String query = "select id,name from student";

// 获得一个结果集

ResultSet rs = stq.executeQuery(query);

// 获得结果集的元数据(表及的信息)

ResultSetMetaData rsmt = rs.getMetaData();

// 得到有几列,保存在num变量里

int num = rsmt.getColumnCount();

String[] columns = new String[num];

// 列的序号是从1开始的

for (int i = 0; i < num; i++)

columns[i] = rsmt.getColumnName(i + 1);

// 先输出列名

for (int i = 0; i < num; i++)

System.out.print(columns[i] + " ");

// 输出列名之后换行

System.out.println();

// 取出结果

while (rs.next()) {

// 输出每一行的值

for (int i = 1; i <= num; i++) {

String temp = rs.getString(i);

System.out.print(temp + " ");

}

System.out.println();

}

} catch (Exception e) {

e.printStackTrace();

} finally {

try {

if (con != null)

con.close();

} catch (Exception e) {

e.printStackTrace();

}

}

}

}

使用事务

下面介绍如何把一系列语句组织成一个事务?如果事务中所有命令都能正确执行,就可以提交这个事务;否则,如果事务中有一个命令出现错误,回滚这个事务,并返回到提交之前的状态,好像什么也没有发生。把命令组合成事务的主要原因是保证数据库的完整性。对于一个事务而言,要么事务中语句全部得到正确执行,事务就可被提交了,要么它中间出现错误。后一种情况,可以调用rollback()方法,数据库将自动放弃上一次提交事务以来的全部变化。一个数据库连接的缺省模式是autocommit模式,每个SQL命令一执行就会提交给数据库。一旦某个命令已提交,就不能把它回退。可以用Connection接口的getAutocommit()方法,检验数据库的目前自动提交模式设置。用命令con.setAutoCommit(false)方法关闭自动提交模式。用con.commit()命令提交事务。用con.rollback()回滚一个事务。

代码

import java.sql.Connection;

import java.sql.PreparedStatement;

import java.sql.SQLException;

import javax.naming.NamingException;

public class UseTran {

public static void main(String[] args) {

Connection con = null;// 方法里临时变量要手动初始化

PreparedStatement updateAge = null;

String updateString = "update student "

+ "set age = ? where name like ?";

String jndiname = "jdbcPool/mydatasource";

try {

con = DBCon.getConnectionFromPooledDataSource(jndiname);

updateAge = con.prepareStatement(updateString);

int[] age = { 45, 39, 25

标签: ds2保护继电器继电器jrs

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台