上一篇写了一些基本数据库操作,以及批处理、调用存储过程等内容,这一次主要是使用事务以及使用连接池来提高效率,当然最好还是选用比较成熟的连接池,这些在框架中应该都已经集成了,但是现在不是没学嘛~多了解一点也是有好处的
到这里 JDBC 基本就差不多了,如果还看到什么知识点的话就再补充一篇
使用事务
关于什么是事务,以及有什么特点,我在这篇文章中更新过了,下面就主要说说在 JDBC 中如何使用事务,还是以 MySQL 为例,其他的也都一致,就是注意下隔离级别的问题,像 Oracle 就只支持 2 种;首先来看下最基本的使用:
1 | public static void main(String[] args) { |
主要操作的是 conn 对象,首先我们要关闭它的自动提交,否则每发送一条 SQL 会立即完成,关闭后相当于开启了一个事务,无论执行多少次 SQL 只要不进行 commit ,数据库就会进行回滚操作
下面再说下手动设置事务的回滚点,并且手动回滚操作:
1 | private static void custPoint() throws SQLException { |
采用的方式是设置一个回滚点 Savepoint ,当然应该还有其他方式的….先说这一种
然后是手动设置隔离级别,就是一句话的事:
1 | private static void test() throws SQLException { |
补充一点,产生 conn 的方法还可以使用工厂模式来生产 Dao
它能使各层之间能达到完全解耦的目的,但是相应的代码的复杂度会增加
如果项目确定不会更换 Dao 层,那么其实不使用工厂模式比较好
代码参考: Github
使用连接池
首先,要明确数据库能创建的连接数(也就是 conn)是非常有限的,并且创建出来也很不容易,所以,每次操作数据库的时候就让数据库给创建连接效率是非常低的,于是就有了连接池的概念
就是说,事先先创建好一批连接,存到一个“池”里,当需要的时候就从这个池里取,用完后不要释放而是再放回这个池里,这样会极大的提高效率
思路大概就是这样了….
下面来手写个连接池,当然是最基本的;简单说就是实现 DataSource 接口,这个接口只有两个方法,其他都是继承过来的,可以简单的认为实现了DataSource 接口的就是一个连接池
1 | public class JdbcPool implements DataSource { |
DBCP连接池
对于新手,自己写的连接池是很不放心啊,所以还是用比较成熟的开源的比较好,比如 BDCP 和 C3P0
哦,对了 DBCP 是 Apache 的,下面是使用的参考代码,记得导入相关的包,没记错的话应该是需要三个包,一个是 DBCP 的还需要 logging 和 pool2 的包,有点麻烦,不过都是 Apache 家的,在 Apache 的官网都可以找到
主包地址:https://commons.apache.org/proper/commons-dbcp/
1 | public class JdbcUtilsDBCP { |
顺便贴下 DBCP 的配置文件:
1 | ########DBCP配置文件########## |
C3P0连接池
使用步骤和 DBCP 类似,不过貌似效率更高一些
官网地址:http://www.mchange.com/projects/c3p0/
1 | public class JdbcUtilsC3P0 { |
如果在 src 下有配置文件直接 new 就可以了,如果没有那就只能手动指定了,配置文件统一命名为 c3p0-config.xml
,示例:
1 | "1.0" encoding="UTF-8" xml version= |
default 对应空构造函数,如果你还配置了其他的,比如上面的就是叫 named ,在 new ComboPooledDataSource 的时候把名字作为参数传入就好了,这样更加灵活
Tomcat自带连接池
其实就是用的 DBCP,因为 DBCP 是 Apache 的,Tomcat 也是 Apache 的,都是一家子嘛~~
使用自带的连接池的步骤在 Tomcat 的文档中写的也算是很清楚了,见:JNDI Resources 目录下
因为使用自带的连接池需要配 Context ,Context 的配置方式一共有 5 种 (:应该是
见:官方在线文档
除去前面介绍 Tomcat 时说的几种,还有一种是在工程的 Web 目录下新建 META-INF 目录,然后再新建 context.xml 文件,在这个文件中进行配置
其实这种方式最终会复制一份到 conf\Catalina\localhost
下,一般以应用名开头,所以清理项目的时候记得手动删除
好了,继续说,首先按照文档先要把驱动拷到服务器的 lib 文件夹,然后进行配置 Context 就可以了:
1 | <Context ...> |
获取链接的示例代码为:
1 | // 初始化 JNDI |
文档为啥会在 JNDI 目录下呢,因为数据库池(DataSource)保存在 web 服务器的 JNDI 容器中(当然也是可以存其他东西的)
所以说,服务器传对象给 Servlet 其实又多了一种方式,那就放在 JNDI 容器中,需要的时候向 JNDI 中获取就行了
JNDI科普
什么是 JNDI ?
JNDI是 Java 命名与目录接口(Java Naming and Directory Interface),在J2EE规范中是重要的规范之一.
JNDI 是 Java 平台的一个标准扩展,提供了一组接口、类和关于命名空间的概念。如同其它很多 Java 技术一样,JDNI 是 provider-based 的技术,暴露了一个 API 和一个服务供应接口(SPI)。
这意味着任何基于名字的技术都能通过 JNDI 而提供服务,只要 JNDI 支持这项技术。
JNDI 目前所支持的技术包括 LDAP、CORBA Common Object Service(COS)名字服务、RMI、NDS、DNS、Windows 注册表等等。
很多 J2EE 技术,包括 EJB 都依靠 JNDI 来组织和定位实体。可以把它理解为一种将对象和名字捆绑的技术,对象工厂负责生产出对象,这些对象都和唯一的名字绑在一起,外部资源可以通过名字获得某对象的引用。
简单来说就是,原来我们写代码需要在代码中指定数据库的连接、用户名、密码等信息,现在只需要在 XML 配置文件中指定就可以了,达到了解耦的目的;现在这些问题都由 J2EE 容器来配置和管理,程序员只需要对这些配置和管理进行引用即可。
J2EE 规范要求所有 J2EE 容器都要提供 JNDI 规范的实现。JNDI 是通过资源的名字来查找的,资源的名字在整个j2ee应用中(j2ee 容器中)是唯一的
JTA与EJB科普
java Transaction API(Java事务 API)完整的名称应该是:Java Transaction API(Application Programming Interface)
JTA Transaction 是指由 J2EE Transaction manager 去管理的事务。其最大的特点是调用 UserTransaction 接口的 begin,commit 和 rollback 方法来完成事务范围的界定,事务的提交和回滚。
JTATransaction 可以实现同一事务对应不同的数据库,但是它仍然无法实现事务的嵌套。
就是我们所说的全局事务
顺便再补充下什么是 EJB 吧:
企业级JavaBean(Enterprise JavaBean, EJB)是一个用来构筑企业级应用的服务器端可被管理组件。
用通俗话说,EJB 就是:”把你编写的软件中那些需要执行制定的任务的类,不放到客户端软件上了,而是给他打成包放到一个服务器上了”。
是的,没错!EJB 就是将那些”类”放到一个服务器上,用 C/S 形式的软件客户端对服务器上的”类”进行调用。
EJB 包含的 3 种 bean 是:session bean(会话 bean), entity bean(实体 bean), message bean(消息 bean)
更详细的内容可参考:http://blog.csdn.net/cuiran/article/details/40950487
评论框加载失败,无法访问 Disqus
你可能需要魔法上网~~