java JDBC

java JDBC

概述

java DataBase Connectivity可以让 Java 连接数据库,Java语言操作数据库。

本质

官方(sun)公司定义的一套操作所有关系型数据库的规则,即接口。各个数据库厂商去实现这套接口,提供数据库驱动jar包。我们可以使用这套接口(JDBC)编程,真正执行代码是驱动jar包中的实现类

  • 使用的驱动不同,即可连接不同的数据库。
  • 使用同一套操作来操作不同的数据库
  • 如果每一个数据库java都制订一套连接方式,那么当不同的数据库更新的时候,java也需要更新自己的代码,而使用jdbc,使用同一套代码来操作,使用不同的驱动程序(驱动程序由数据库厂商提供)来连接,这使得可以连接不同的数据库。

使用

  • 导入对应数据库的驱动类
  • 加载驱动 DriverManager
  • 获取连接 Connection
  • 执行SQL语句 Statement
  • 获取返回 ResultSet
  • 关闭连接

使用介绍

DriverManager

public class DriverManager extends Object

  • 概述

用于管理一组JDBC驱动程序的基本服务。

注意: JDBC 2.0 API中新增的DataSource接口提供了另一种连接到数据源的方法。 使用DataSource对象是连接到数据源的首选方法。

作为其初始化的一部分, DriverManager类将尝试加载在“jdbc.drivers”系统属性中引用的驱动程序类。 这允许用户自定义应用程序使用的JDBC驱动程序。 例如在〜/ .hotjava / properties文件中,您可以指定: ( jdbc.drivers=foo.bah.Driver:wombat.sql.Driver:bad.taste.ourDriver )

DriverManager方法getConnectiongetDrivers已得到增强,以支持Java Standard Edition [Service Provider](…/…/…/technotes/guides/jar/jar.html#Service Provider)机制。 JDBC 4.0驱动程序必须包含文件META-INF/services/java.sql.Driver 。 该文件包含java.sql.Driver的JDBC驱动程序实现的java.sql.Driver 。 例如,要加载my.sql.Driver类, META-INF/services/java.sql.Driver文件将包含条目: my.sql.Driver

应用程序不再需要使用Class.forName()显式加载JDBC驱动程序。 目前使用加载JDBC驱动程序的现有程序Class.forName()将继续无需修改工作。

当调用方法getConnection时, DriverManager将尝试从初始化中加载的驱动程序中找到合适的驱动程序,并使用与当前小程序或应用程序相同的类加载器显式加载驱动程序。

  • 常用方法

static void deregisterDriver(Driver driver)DriverManager的注册驱动程序列表中删除指定的驱动程序。

static Connection getConnection(String url) 尝试建立与给定数据库URL的连接。

static Connection getConnection(String url, Properties info) 尝试建立与给定数据库URL的连接。

static Connection getConnection(String url, String user, String password) 尝试建立与给定数据库URL的连接。

static Driver getDriver(String url) 尝试查找了解给定URL的驱动程序。

static Enumeration getDrivers() 使用当前调用者可以访问的所有当前加载的JDBC驱动程序检索枚举。 static int getLoginTimeout() 获取尝试登录数据库时驱动程序可以等待的最长时间(秒)。

static PrintWriter getLogWriter() 检索日志记录器。

static void println(String message) 打印到当前JDBC日志流的消息。

static void registerDriver(Driver driver) 注册与给定的驱动程序 DriverManager

static void registerDriver(Driver driver, DriverAction da) 注册与给定的驱动程序 DriverManager

static void setLoginTimeout(int seconds) 设置驱动程序在识别驱动程序后尝试连接到数据库时等待的最长时间(秒)。

static void setLogWriter(PrintWriter out) 设置 DriverManager和所有驱动程序使用的记录/跟踪 PrintWriter对象。

public interface Driver

每个驱动程序类必须实现的接口。

Java SQL框架允许多个数据库驱动程序。

每个驱动程序都应该提供一个实现Driver接口的类。

DriverManager将尝试加载尽可能多的驱动程序,然后对于任何给定的连接请求,它会依次要求每个驱动程序尝试连接到目标URL。

 //加载驱动
 Class.forName("");
//获取连接
 Connection conn = DriverManager.getConnection("", "", "");

Connection

public interface Connection extends Wrapper, AutoCloseable

  • 概述

与特定数据库的连接(会话)。 执行SQL语句并在连接的上下文中返回结果。

Connection对象的数据库能够提供描述其表,其支持的SQL语法,其存储过程,此连接的功能等的信息。 该信息是用getMetaData方法获得的。

**注意:**配置Connection时,JDBC应用程序应使用适当的Connection方法,例如setAutoCommitsetTransactionIsolation 。 当有JDBC方法可用时,应用程序不应直接调用SQL命令来更改连接的配置。 默认情况下, Connection对象处于自动提交模式,这意味着它在执行每个语句后自动提交更改。 如果自动提交模式已禁用,必须显式调用方法commit才能提交更改; 否则数据库更改将不会被保存。

  • 常用方法
  • void close() Connection发布此 Connection对象的数据库和JDBC资源,而不是等待它们自动释放。 void commit() 使自上次提交/回滚以来所做的所有更改都将永久性,并释放此 Connection对象当前持有的任何数据库锁。

void setAutoCommit(boolean autoCommit) 将此连接的自动提交模式设置为给定状态。

More Actionsvoid``rollback() 撤消在当前事务中所做的所有更改,并释放此 Connection对象当前持有的任何数据库锁。

PreparedStatement prepareStatement(String sql) 创建一个 PreparedStatement对象,用于将参数化的SQL语句发送到数据库。

More ActionsCallableStatement``prepareCall(String sql) 创建一个调用数据库存储过程的 CallableStatement对象。

int getNetworkTimeout() 检索驱动程序等待数据库请求完成的毫秒数。

Statement createStatement() 创建一个 Statement对象,用于将SQL语句发送到数据库。

  • 事务

在数据库操作中,一项事务是指由一条或多条对数据库更新的sql语句所组成的一个不可分割的工作单元。只有当事务中的所有操作都正常完成了,整个事务才能被提交到数据库,如果有一项操作没有完成,就必须撤消整个事务。

例如在银行的转帐事务中,假定张三从自己的帐号上把1000元转到李四的帐号上,相关的sql语句如下:

update account set monery=monery-1000 where name=‘zhangsan’

update account set monery=monery+1000 where name=‘lisi’

这个两条语句必须作为一个完成的事务来处理。只有当两条都成功执行了,才能提交这个事务。如果有一句失败,整个事务必须撤消。

在connection类中提供了3个控制事务的方法:

(1) setAutoCommit(Boolean autoCommit):设置是否自动提交事务;

(2) commit();提交事务;

(3) rollback();撤消事务;

在jdbc api中,默认的情况为自动提交事务,也就是说,每一条对数据库的更新的sql语句代表一项事务,操作成功后,系统自动调用commit()来提交,否则将调用rollback()来撤消事务。

在jdbc api中,可以通过调用setAutoCommit(false) 来禁止自动提交事务。然后就可以把多条更新数据库的sql语句做为一个事务,在所有操作完成之后,调用commit()来进行整体提交。倘若其中一项 sql操作失败,就不会执行commit()方法,而是产生相应的sqlexception,此时就可以捕获异常代码块中调用rollback()方法撤消事务。

事务处理是企业应用需要解决的最主要的问题之一。J2EE通过JTA提供了完整的事务管理能力,包括多个事务性资源的管理能力。但是大部分应用都是运行在单一的事务性资源之上(一个数据库),他们并不需要全局性的事务服务。本地事务服务已然足够(比如JDBC事务管理)。

事务的特性

Atomic原子性、Consistency一致性、Isolation隔离性和Durability持久性。

  • 原子性:指整个事务是不可以分割的工作单元。只有事务中所有的操作执行成功,才算整个事务成功,事务中任何一个SQL语句执行失败,那么已经执行成功的SQL语句也必须撤销,数据库状态应该回到执行事务前的状态。
  • 一致性:指数据库事务不能破坏关系数据的完整性以及业务逻辑上的一致性。例如对于银行转账事务,不管事务成功还是失败,应该保证事务结束后两个转账账户的存款总额是与转账前一致的。
  • 隔离性:指的是在并发环境中,当不同的事务同时操纵相同的数据时,每个事务都有各自的完整数据空间。
  • 持久性:指的是只要事务成功结束,它对数据库所做的更新就必须永久保存下来。即使发生系统崩溃,重新启动数据库系统后,数据库还能恢复到事务成功结束时的状态。
 //事务
//   设置事务管理:
        conn.setAutoCommit(false);
//        【当参数为true时,代表允许自动提交(事务管理是关闭的,每一条命令都会自动提交);
//        当为false时,代表不允许自动提交,命令会在执行commit之后再统一提交(开启事务管理的)】

//        提交事务:
        conn.commit();

//        回滚事务:
        conn.rollback();

// 有些时候,在开发中是不会把两个操作放到一个地方的(在Javaweb中开发中存在service层和dao层。可以这么说,
// servlet是饭店前台,service层就是包厢里点菜的服务员(客户需要什么菜,他负责告诉后厨),dao层就是真正做
//菜的后厨(dao层通常是数据库方面的操作)。服务员一次性把需要的菜告诉后厨),这样耦合性较高,通常需要把它们
// 放到单独的地方去(就好比一个大厨做好几样菜会很忙,通常都会分工好),比如加钱是一个函数,减钱是一个函数。
//  把他们分开后,两个函数之间的Connection不同的话,就会无法统一进行事务管理。通常有两个解决方法:1.把同一
// 个Connection对象传给这两个参数。2.利用Threadlocal类,把Connection对象存进去,两个要用的时候再取,取
// 的是同一个对象。【这里可能不容易理解,只是做个提醒,可以不理解。】

Statement

public class Statement
extends Object

  • 概述

一个Statement对象表示一个原始语句,其中单个方法应用于目标和一组参数 - 如"a.setFoo(b)" 。 请注意,此示例使用名称来表示目标及其参数,语句对象不需要名称空间,并且使用值本身构造。 语句对象将named方法与其环境相关联,作为一组简单的值:目标和参数值

  • PreparedStatement

public interface PreparedStatement
extends Statement

表示预编译的SQL语句的对象。

SQL语句已预编译并存储在PreparedStatement对象中。 然后可以使用该对象多次有效地执行此语句。

注意:setter方法( setShortsetString用于设置IN参数值必须指定与所定义的SQL类型的输入参数的兼容的类型,等等)。 例如,如果IN参数具有SQL类型INTEGER ,则应使用方法setInt

boolean execute() 执行此 PreparedStatement对象中的SQL语句,这可能是任何类型的SQL语句。

ResultSet executeQuery() 执行此 PreparedStatement对象中的SQL查询,并返回查询 PreparedStatementResultSet对象。

More Actionsint``executeUpdate() 执行在该SQL语句PreparedStatement对象,它必须是一个SQL数据操纵语言(DML)语句,如INSERTUPDATEDELETE ; 或不返回任何内容的SQL语句,例如DDL语句。

void setTimestamp(int parameterIndex, Timestamp x) 将指定的参数设置为给定的 java.sql.Timestamp值。 void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) 使用给定的 Calendar对象将指定的 Calendar设置为给定的 java.sql.Timestamp值。

 //执行SQL语句:
//  1.使用Statement执行sql语句
// Statement对象的获取可以使用createStatement()来获取
// 获取Statement对象后,对于查询类的sql语句使用:executeQuery(sql),sql是一个字符串sql语句,返回结果是一个结果集【如果获取结果看下面的结果部分】
// 对于更新类(插入、修改、删除、更新)的语句使用:executeUpdate(sql),sql是一个字符串sql语句,返回结果是一个整数(受影响的行数)
        Statement statement = conn.createStatement();
// 2.使用PreparedStatement执行sql语句
// PreparedStatement对象的获取可以使用prepareStatement(sql)来获取,注意的是需要传入一条sql语句
// PreparedStatement的功能类似Statement,但不同的是PreparedStatement可以使用占位符,它是由占位符标识需要输入数据的位置,然后再逐一填入数据。当然,PreparedStatement也可以执行没有占位符的sql语句
//  使用占位符后,使用setString或setInt等方法来设置每一位的数据。【有各种对应数据类型的设置方法,比如还有setFloat】
//  setXXX方法中,第一个参数是位置,第二个是数据
 PreparedStatement preparedStatement = conn.prepareStatement("");
//        3.使用CallableStatement执行sql语句
//        CallableStatement主要用来调用存储过程
//对于输出参数,需要使用registerOutParameter注册,第一个参数是位置,第二个参数是参数类型(使用Types.xxx)
//        注册之后,想要获取输出参数,可以使用CallableStatement对象自身的getXXX方法来获取
        CallableStatement callableStatement = conn.prepareCall("");

ResultSet

public interface ResultSet extends Wrapper, AutoCloseable

  • 概述

表示数据库结果集的数据表,通常通过执行查询数据库的语句生成。

ResultSet对象保持一个光标指向其当前的数据行。 最初,光标位于第一行之前。 next方法将光标移动到下一行,并且由于在ResultSet对象中没有更多行时返回false ,因此可以在while循环中使用循环来遍历结果集。

默认的ResultSet对象不可更新,并且只有一个向前移动的光标。 因此,您只能从第一行到最后一行迭代一次。 可以生成可滚动和/或可更新的ResultSet对象。 以下代码片段(其中con是有效的Connection对象)说明了如何使可滚动且对其他人更新不敏感的结果集,这是可更新的。

所述ResultSet接口提供getter方法( getBooleangetLong ,用于从当前行检索列值,等等)。可以使用列的索引号或列的名称来检索值。一般来说,使用列索引将更有效率。列从1编号。为了最大可移植性,每行中的结果集列应以从左到右的顺序读取,每列应只读一次。

对于getter方法,JDBC驱动程序尝试将底层数据转换为getter方法中指定的Java类型,并返回合适的Java值。 JDBC规范具有一个表格,该表格显示了可由ResultSet getter方法使用的SQL类型到Java类型的允许映射。

用作getter方法输入的列名不区分大小写。 当使用列名称调用getter方法时,多个列具有相同的名称,将返回第一个匹配列的值。 列名称选项用于在生成结果集的SQL查询中使用列名时使用。 对于在查询中未明确命名的列,最好使用列号。 如果使用列名称,程序员应该小心保证它们唯一地引用预期的列,这可以通过SQL AS子句来确保。

  • 常用方法

More Actionsvoid``close() ResultSet释放此 ResultSet对象的数据库和JDBC资源,而不是等待其自动关闭时发生。

getDate(int columnIndex) 将该 ResultSet对象的当前行中指定列的值作为Java编程语言中的 java.sql.Date对象检索。

Date getDate(int columnIndex, Calendar cal) 将此 ResultSet对象的当前行中指定列的值 ResultSet为Java编程语言中的 java.sql.Date对象。

Date getDate(String columnLabel) 将此 ResultSet对象的当前行中的指定列的值作为Java编程语言中的 java.sql.Date对象检索。

Date getDate(String columnLabel, Calendar cal) 将该 ResultSet对象的当前行中指定列的值作为Java编程语言中的 java.sql.Date对象检索。

boolean previous() 将光标移动到此 ResultSet对象中的上一行。

getTime(int columnIndex) 将此 ResultSet对象的当前行中指定列的值作为Java编程语言中的 java.sql.Time对象检索。

Time getTime(int columnIndex, Calendar cal) 将此 ResultSet对象的当前行中的指定列的值作为Java编程语言中的 java.sql.Time对象检索。

Time getTime(String columnLabel) 将此 ResultSet对象的当前行中的指定列的值作为Java编程语言中的 java.sql.Time对象检索。

Time getTime(String columnLabel, Calendar cal) 将此 ResultSet对象的当前行中指定列的值作为Java编程语言中的 java.sql.Time对象检索。

Timestamp getTimestamp(int columnIndex) 将该 ResultSet对象的当前行中指定列的值作为Java编程语言中的 java.sql.Timestamp对象检索。

Timestamp getTimestamp(int columnIndex, Calendar cal) 将此 ResultSet对象的当前行中指定列的值作为Java编程语言中的 java.sql.Timestamp对象检索。

Timestamp getTimestamp(String columnLabel) 将此 ResultSet对象的当前行中指定列的值作为Java编程语言中的 java.sql.Timestamp对象检索。

Timestamp getTimestamp(String columnLabel, Calendar cal) 将此 ResultSet对象的当前行中指定列的值作为Java编程语言中的 java.sql.Timestamp对象检索。

数据库连接池

概述

数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个;释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏。这项技术能明显提高对数据库操作的性能。

原理

连接池基本的思想是在系统初始化的时候,将数据库连接作为对象存储在内存中,当用户需要访问数据库时,并非建立一个新的连接,而是从连接池中取出一个已建立的空闲连接对象。使用完毕后,用户也并非将连接关闭,而是将连接放回连接池中,以供下一个请求访问使用。而连接的建立、断开都由连接池自身来管理。同时,还可以通过设置连接池的参数来控制连接池中的初始连接数、连接的上下限数以及每个连接的最大使用次数、最大空闲时间等等。也可以通过其自身的管理机制来监视数据库连接的数量、使用情况等。

影响因素

数据库连接池在初始化时将创建一定数量的数据库连接放到连接池中,这些数据库连接的数量是由最小数据库连接数制约。无论这些数据库连接是否被使用,连接池都将一直保证至少拥有这么多的连接数量。连接池的最大数据库连接数量限定了这个连接池能占有的最大连接数,当应用程序向连接池请求的连接数超过最大连接数量时,这些请求将被加入到等待队列中。数据库连接池的最小连接数和最大连接数的设置要考虑到下列几个因素:

1. 最小连接数

是连接池一直保持的数据库连接,所以如果应用程序对数据库连接的使用量不大,将会有大量的数据库连接资源被浪费。

2. 最大连接数

是连接池能申请的最大连接数,如果数据库连接请求超过此数,后面的数据库连接请求将被加入到等待队列中,这会影响之后的数据库操作。

3. 最小连接数与最大连接数差距

最小连接数与最大连接数相差太大,那么最先的连接请求将会获利,之后超过最小连接数量的连接请求等价于建立一个新的数据库连接。不过,这些大于最小连接数的数据库连接在使用完不会马上被释放,它将被放到连接池中等待重复使用或是空闲超时后被释放。

使用

DataSource

public interface DataSource extends CommonDataSource, Wrapper

  • 概述

一个连接到这个DataSource对象所代表的物理数据源的工厂。 DriverManager设备的DriverManagerDataSource对象是获取连接的首选方法。 实现DataSource接口的对象通常将基于Java“命名和目录(JNDI)API”的命名服务注册。

DataSource接口由驱动程序供应商实现。 有三种类型的实现:

  1. 基本实现 - 生成标准的Connection对象
  2. 连接池实现 - 生成将自动参与连接池的Connection对象。 此实现与中间层连接池管理器配合使用。
  3. 分布式事务实现 - 生成可用于分布式事务的Connection对象,并且几乎总是参与连接池。 此实现与中间层事务管理器一起工作,并且几乎总是使用连接池管理器。

一个DataSource对象具有必要时可以修改的属性。 例如,如果将数据源移动到其他服务器,则可以更改服务器的属性。 好处是因为可以更改数据源的属性,所以不需要更改访问该数据源的任何代码。

经由一个访问的驱动器DataSource对象不与寄存器本身DriverManager 。 相反, DataSource对象虽然查找操作检索,然后用于创建Connection对象。 通过基本实现,通过DataSource对象获得的连接与通过DriverManager工具获得的连接DriverManager

  • 常用方法

More ActionsConnection``getConnection() 尝试建立与此 DataSource对象所代表的数据源的连接。

扩展

Spring JdbcTemplate

为了使 JDBC 更加易于使用,Spring 在 JDBCAPI 上定义了一个抽象层, 以此建立一个JDBC存取框架.

作为 SpringJDBC 框架的核心, JDBC 模板的设计目的是为不同类型的JDBC操作提供模板方法. 每个模板方法都能控制整个过程,并允许覆盖过程中的特定任务.通过这种

方式,可以在尽可能保留灵活性的情况下,将数据库存取的工作量降到最低.

JdbcTemplate主要提供以下五类方法:

  • execute方法:可以用于执行任何SQL语句,一般用于执行DDL语句;
  • update方法:update方法用于执行新增、修改、删除等语句;
  • batchUpdate方法:batchUpdate方法用于执行批处理相关语句;
  • query方法及queryForXXX方法:用于执行查询相关语句;
  • call方法:用于执行存储过程、函数相关语句。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值