在独立Java应用程序中使用Tomcat JDBC连接池

这是从我们的客人文章W4G伙伴克拉伦斯豪的作者临春3从A按。 您可能会在文章结尾找到本书的折扣券代码,仅适用于Java Code Geeks的读者! 请享用!

在需要数据访问权限的独立Java应用程序中使用JDBC连接池时,大多数开发人员将使用commons-dbcp或c3p0 。 在本教程中,我们将讨论在独立Java应用程序中的Apache Tomcat Web容器中使用JDBC连接池。

Tomcat 7的新功能之一是tomcat-jdbc连接池,它替代了commons-dbcp连接池。 下面列出了tomcat-jdbc相对于commons-dbcp和其他连接池库的主要优点:
  • 支持高度并发的环境和多核/ CPU系统
  • Commons-dbcp是单线程的,速度很慢
  • Commons-dbcp很复杂(超过60个类),而tomcat-jdbc核心仅包含8个类
  • 支持异步连接检索
  • XA连接支持
  • 连接池对象公开了可以注册用于监视目的的MBean
  • 支持common-dbcp中的大多数属性,以及许多增强的属性
  • 支持JDBC拦截器
有关配置的详细说明和文档,请参考Apache Tomcat网站上的官方文档页面。
在本教程中,我们将演示如何使用tomcat-jdbc开发简单的独立数据访问Java应用程序。 该应用程序将使用以下框架和库:
  • Spring Framework 3.1.1
  • 休眠4.1.3
  • Spring Data JPA 1.1.0
  • Tomcat JDBC连接池7.0.27
  • H2数据库1.3.167
  • 番石榴12.0
该示例是使用SpringSource Tool Suite开发的,可以在本文末尾下载压缩的存档 。 另一方面,本教程假定您已经对使用Spring和Hibernate开发JPA应用程序有所了解。

依存关系

项目依赖项由Maven管理。 以下是项目的POM文件(pom.xml)的片段。

清单1 –项目依赖性

<properties><maven.test.failure.ignore>true</maven.test.failure.ignore><spring.framework.version>3.1.1.RELEASE</spring.framework.version><hibernate.version>4.1.3.Final</hibernate.version><spring.data.jpa.version>1.1.0.RELEASE</spring.data.jpa.version><tomcat.dbcp.version>7.0.27</tomcat.dbcp.version><h2.version>1.3.167</h2.version><slf4j.version>1.6.4</slf4j.version><log4j.version>1.2.16</log4j.version><guava.version>12.0</guava.version>
</properties><dependencies><!-- Hibernate --><dependency><groupId>org.hibernate</groupId><artifactId>hibernate-entitymanager</artifactId>       <version>${hibernate.version}</version></dependency><!-- Spring Framework --><dependency><groupId>org.springframework</groupId><artifactId>spring-context-support</artifactId><version>${spring.framework.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-aop</artifactId><version>${spring.framework.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-orm</artifactId><version>${spring.framework.version}</version></dependency><!-- Spring Data JPA --><dependency><groupId>org.springframework.data</groupId><artifactId>spring-data-jpa</artifactId><version>${spring.data.jpa.version}</version></dependency><!-- Tomcat DBCP --><dependency><groupId>org.apache.tomcat</groupId><artifactId>tomcat-jdbc</artifactId><version>${tomcat.dbcp.version}</version></dependency><!-- Logging --><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>${slf4j.version}</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>jcl-over-slf4j</artifactId><version>${slf4j.version}</version><scope>runtime</scope></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId><version>${slf4j.version}</version><scope>runtime</scope></dependency><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>${log4j.version}</version></dependency><!-- Others --><dependency><groupId>com.h2database</groupId><artifactId>h2</artifactId><version>${h2.version}</version></dependency><dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>${guava.version}</version></dependency>
</dependencies>

领域对象模型

对象模型是一个简单的联系信息模型。 每个联系人都有其名字,姓氏和出生日期。 同样,每个联系人将与零个或多个爱好(例如游泳,慢跑,阅读等)相关联。 在DOM中,有两个主要类,即Contact和Hobby类。 清单2和3分别显示了这些类的代码清单。

清单2 – Contact类

@Entity
@Table(name = "contact")
public class Contact {private Long id;private int version;private String firstName;private String lastName;private Date birthDate;private Set<Hobby> hobbies = new HashSet<Hobby>();@Id@GeneratedValue(strategy=GenerationType.IDENTITY)@Column(name = "ID")public Long getId() {return id;}public void setId(Long id) {this.id = id;}@Version@Column(name = "VERSION")public int getVersion() {return version;}public void setVersion(int version) {this.version = version;}@Column(name = "FIRST_NAME")public String getFirstName() {return firstName;}public void setFirstName(String firstName) {this.firstName = firstName;}@Column(name = "LAST_NAME")public String getLastName() {return lastName;}public void setLastName(String lastName) {this.lastName = lastName;}@Column(name = "BIRTH_DATE")@Temporal(TemporalType.DATE)public Date getBirthDate() {return birthDate;}public void setBirthDate(Date birthDate) {this.birthDate = birthDate;} @ManyToMany@JoinTable(name = "contact_hobby_detail", joinColumns = @JoinColumn(name = "CONTACT_ID"), inverseJoinColumns = @JoinColumn(name = "HOBBY_ID"))public Set<hobby> getHobbies() {return this.hobbies;}public void setHobbies(Set<hobby> hobbies) {this.hobbies = hobbies;}   public String toString() {  return "Contact - Id: " + id + ", First name: " + firstName + ", Last name: " + lastName + ", Birthday: " + birthDate;}  }

清单3 – Hobby类

@Entity
@Table(name = "hobby")
public class Hobby {private String hobbyId;private Set<Contact> contacts = new HashSet<Contact>();public Hobby() {}public Hobby(String hobbyId) {this.hobbyId = hobbyId;}public Hobby(String hobbyId, Set<Contact> contacts) {this.hobbyId = hobbyId;this.contacts = contacts;}@Id@Column(name = "HOBBY_ID")public String getHobbyId() {return this.hobbyId;}public void setHobbyId(String hobbyId) {this.hobbyId = hobbyId;}@ManyToMany@JoinTable(name = "contact_hobby_detail", joinColumns = @JoinColumn(name = "HOBBY_ID"), inverseJoinColumns = @JoinColumn(name = "CONTACT_ID"))public Set<Contact> getContacts() {return this.contacts;}public void setContacts(Set<Contact> contacts) {this.contacts = contacts;} }
在清单2和3中,注意到Contact和Hobby类之间存在多对多关系。

数据库架构

在本教程中,我们将使用H2内存数据库。 有3个表:

  • 联系人:该表存储联系人信息
  • HOBBY:该表存储可用于该应用程序的兴趣爱好列表
  • CONTACT_HOBBY_DETAIL:对Contact和Hobby类之间的多对多关系进行建模
清单4和5分别显示了数据库模式创建脚本和测试数据填充脚本的内容。

清单4 –数据库模式创建脚本(schema.sql)

DROP TABLE IF EXISTS CONTACT;CREATE TABLE CONTACT (ID INT NOT NULL AUTO_INCREMENT,FIRST_NAME VARCHAR(60) NOT NULL,LAST_NAME VARCHAR(40) NOT NULL,BIRTH_DATE DATE,VERSION INT NOT NULL DEFAULT 0,UNIQUE UQ_CONTACT_1 (FIRST_NAME, LAST_NAME),PRIMARY KEY (ID)
);CREATE TABLE HOBBY (HOBBY_ID VARCHAR(20) NOT NULL,PRIMARY KEY (HOBBY_ID)
);CREATE TABLE CONTACT_HOBBY_DETAIL (CONTACT_ID INT NOT NULL,HOBBY_ID VARCHAR(20) NOT NULL,PRIMARY KEY (CONTACT_ID, HOBBY_ID),CONSTRAINT FK_CONTACT_HOBBY_DETAIL_1 FOREIGN KEY (CONTACT_ID)REFERENCES CONTACT (ID) ON DELETE CASCADE,CONSTRAINT FK_CONTACT_HOBBY_DETAIL_2 FOREIGN KEY (HOBBY_ID)REFERENCES HOBBY (HOBBY_ID)
);

清单5 –测试数据填充脚本(test-data.sql)

insert into contact (first_name, last_name, birth_date) values ('Clarence', 'Ho', '1980-07-30');
insert into contact (first_name, last_name, birth_date) values ('Scott', 'Tiger', '1990-11-02');insert into hobby (hobby_id) values ('Swimming');
insert into hobby (hobby_id) values ('Jogging');
insert into hobby (hobby_id) values ('Programming');
insert into hobby (hobby_id) values ('Movies');
insert into hobby (hobby_id) values ('Reading');insert into contact_hobby_detail(contact_id, hobby_id) values (1, 'Swimming');
insert into contact_hobby_detail(contact_id, hobby_id) values (1, 'Movies'); 
insert into contact_hobby_detail(contact_id, hobby_id) values (2, 'Swimming');

服务层

在服务层中,存在2个接口:

  • ContactService:提供用于访问联系信息的服务
  • HobbyService:提供用于访问爱好信息的服务

清单6和7分别显示了ContactService和HobbyService接口。

清单6 – ContactService接口

public interface ContactService {public List<Contact> findAll();public Contact findById(Long id);public Contact save(Contact contact);}

清单7 – HobbyService接口

public interface HobbyService {public List<Hobby> findAll();}

弹簧配置

让我们看一下Spring配置。 清单8显示了数据源,事务和JPA配置。

清单8 – Spring JPA配置(datasource-tx-jpa.xml)

<!--Tomcat JDBC connection pool configutation -->
<bean id="dataSource" class="org.apache.tomcat.jdbc.pool.DataSource"><property name="driverClassName" value="org.h2.Driver" /><property name="url" value="jdbc:h2:mem:testdb" /><property name="username" value="sa" /><property name="password" value="" />
</bean><!--Intialize the database schema with test data -->
<jdbc:initialize-database data-source="dataSource"><jdbc:script location="classpath:schema.sql"/><jdbc:script location="classpath:test-data.sql"/>
</jdbc:initialize-database><bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"><property name="entityManagerFactory" ref="emf"/>
</bean><tx:annotation-driven transaction-manager="transactionManager" /><bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"><property name="dataSource" ref="dataSource" /><property name="jpaVendorAdapter"><bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/></property><property name="packagesToScan" value="com.skywidesoft.tomcat.dbcp.tutorial.domain"/><property name="jpaProperties"><props><prop key="hibernate.dialect">org.hibernate.dialect.H2Dialect</prop><prop key="hibernate.max_fetch_depth">3</prop><prop key="hibernate.jdbc.fetch_size">50</prop><prop key="hibernate.jdbc.batch_size">10</prop><prop key="hibernate.show_sql">true</prop></props></property>
</bean> <context:annotation-config/><!--Spring Data JPA Repository Configuration -->
<jpa:repositories base-package="com.skywidesoft.tomcat.dbcp.tutorial.repository"entity-manager-factory-ref="emf"transaction-manager-ref="transactionManager"/>

下面列出了清单8中配置的一些要点:

  • 对于dataSource bean,使用org.apache.tomcat.jdbc.pool.DataSource类为基础连接提供JDBC DataSource接口。 您将看到配置与使用commons-dbcp基本上相同。
  • <jdbc:initialize-database>标记是Spring 3.1对使用数据库架构和测试数据初始化数据库的支持
  • <jpa:repositories>标记用于配置Spring Data JPA的存储库抽象。

清单9显示了Spring应用程序上下文配置。

清单9 – Spring应用程序上下文(app-context.xml)

<import resource="classpath:datasource-tx-jpa.xml"/><context:component-scan base-package="com.skywidesoft.tomcat.dbcp.tutorial.service.jpa"/>

Spring Data JPA存储库抽象

Spring Data JPA的存储库抽象为开发基于JPA的数据访问应用程序提供了一种简化的方法。 有关详细信息,请访问项目网站 。 存储库抽象层是使用Java界面开发的。 清单10和11分别显示了ContactRepository和HobbyRepository接口的代码清单。

清单10 – ContactRepository接口

public interface ContactRepository extends CrudRepository<Contact, Long>{}

清单11 – HobbyRepository接口

public interface HobbyRepository extends CrudRepository<Hobby, String>{}

请注意,该接口只是扩展了Spring Data Common的CrudRepository <T,ID>接口,该接口已经提供了常见的数据访问操作(例如findAll,findOne,保存,删除等)。

JPA实施类

下一步是开发清单6和7中的服务层接口的JPA实现。这些类采用Spring Framework的注解用于Spring bean声明,依赖项的自动装配和事务需求等。清单12和13显示了ContactServiceImpl和HobbyServiceImpl类。

清单12 – ContactServiceImpl类

@Service("contactService")
@Repository
@Transactional
public class ContactServiceImpl implements ContactService {final static Logger logger = LoggerFactory.getLogger(ContactServiceImpl.class);@Autowiredprivate ContactRepository contactRepository;@Transactional(readOnly=true)public List<Contact> findAll() {logger.info("Finding all contacts");return Lists.newArrayList(contactRepository.findAll());}@Transactional(readOnly=true)public Contact findById(Long id) {return contactRepository.findOne(id);}public Contact save(Contact contact) {return contactRepository.save(contact);}}

清单13 – HobbyServiceImpl类

@Service("hobbyService")
@Repository
@Transactional
public class HobbyServiceImpl implements HobbyService {@Autowiredprivate HobbyRepository hobbyRepository;@Transactional(readOnly=true)public List<Hobby> findAll() {return Lists.newArrayList(hobbyRepository.findAll());}}

测试中

让我们看看实际的应用程序。 清单14显示了ContactServiceTest类,该类仅从app-context.xml文件中引导Spring应用程序上下文,查找contactService bean,并调用findAll操作以从数据库中检索所有联系人。

清单14 – ContactServiceTest类

public class ContactServiceTest {public static void main(String[] args) {GenericXmlApplicationContext ctx = new GenericXmlApplicationContext();ctx.load("classpath:app-context.xml");ctx.refresh();ContactService contactService = ctx.getBean("contactService", ContactService.class);List<Contact> contacts = contactService.findAll(); for (Contact contact: contacts) {System.out.println(contact);}  }}
运行上面的类将在控制台输出窗口中产生以下输出(省略了其他不相关的输出):

2012-05-25 13:35:43,552 INFO [com.skywidesoft.tomcat.dbcp.tutorial.service.jpa.ContactServiceImpl] -
<Finding all contacts>
contact0_.BIRTH_DATE as BIRTH2_0_, contact0_.FIRST_NAME as FIRST3_0_,

从上面的输出中,您可以看到从数据库中正确检索了由test-data.sql脚本填充的联系信息。

结论

本教程介绍了如何在独立的Java应用程序中使用Tomcat的JDBC连接池。 Tomcat的JDBC连接池替代了commons-dbcp连接池,提供了更快,功能更丰富的JDBC连接池解决方案。 它的简洁设计,高性能,对高度并发环境的支持以及多核/ cpu系统使其成为Tomcat Web容器和独立Java应用程序环境中的JDBC连接池提供程序的极具吸引力的选择。

下载完整的Eclipse Maven Project 。

参考:来自我们的W4G合作伙伴 Clarence Ho的 独立Java应用程序中的Tomcat JDBC连接池使用

Clarence Ho是APress的Pro Spring 3的主要作者。 借助Pro Spring 3 ,您将学习Spring的基础知识和核心主题,并获得作者关于远程处理, Hibernate和EJB的见解和实际经验。 除了基础知识之外,您还将学习如何利用Spring框架构建企业Java应用程序的各个层或部分,例如事务,Web和表示层,部署等。 完整的示例应用程序使您可以应用本书中介绍的许多技术,并了解它们如何协同工作。

APress已为Java Code Geeks的读者提供了优惠券代码。 优惠券代码为: SPR76 ,有效期至20127月6日 。 该代码仅可从apress.com获得40%的电子书折扣


翻译自: https://www.javacodegeeks.com/2012/06/using-tomcat-jdbc-connection-pool-in.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/372528.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python之路【目录】 2

http://www.cnblogs.com/wupeiqi/articles/4938499.html转载于:https://www.cnblogs.com/cp-miao/p/5750211.html

vs2019 缺android sdk,VS2019由于缺少NuGet Microsoft.NET.Sdk.Functions程序包而无法加载项目,但也无法添加此程序包(示例代码)...

我在解决方案中拥有的一个项目未在VSE2019中加载。它将引发此错误&#xff1a;C:MyProgramsrcMyProgram.Functions.csproj : error : The project file cannot be opened by the project system, because it is missing some critical imports or the referenced SDK cannot be…

数据库事物操作

事务 什么是事务?转账&#xff1a;1. 给wc账户减1000元2. 给wcxf账户加1000元 当给wc账户减1000元后&#xff0c;抛出了异常&#xff01;这会怎么样呢&#xff1f;我相信从此之后&#xff0c;wc再也不敢转账了。 使用事务就可以处理这一问题&#xff1a;把多个对数据库的操作绑…

通过OpenShift超越云技术

您是否厌倦了为您的应用程序请求新的开发机器&#xff1f; 您是否为应用程序设置新的测试环境感到烦恼&#xff1f; 您是否只想专注于和平开发应用程序而不会一直“沉迷于堆栈”&#xff1f; 我们听到你的声音。 我们也去过那里。 不用担心&#xff0c;OpenShift就在这里&#…

android+4.4+稳定性,新系统新UI!台电A10h四核安卓4.4.2性能测试

国内著名商标&#xff0c;数码用户首选品牌的台电科技在12月20日全国首发了安卓4.4.2系统&#xff0c;并且运行台电全新tUI同时&#xff0c;支持从安卓4.2系统OTA一键升级至安卓4.4.2系统&#xff01;作为国内首款升级到目前全球最新的Android4.4.2系统之后&#xff0c;整体性能…

网络知识点小结

VMware虚拟机三种联网方法及原理一、Brigde——桥接&#xff1a;默认使用VMnet0 1、原理&#xff1a; Bridge 桥"就是一个主机&#xff0c;这个机器拥有两块网卡&#xff0c;分别处于两个局域网中&#xff0c;同时在"桥"上&#xff0c;运行着程序&#xff0c;让…

在JUnit中超越核心Hamcrest

在通过JUnit和Hamcrest改进对assertEquals的文章中&#xff0c;我介绍了将Hamcrest与JUnit一起使用 。 然后&#xff0c;我查看了JUnit的内置Hamcrest Core Matcher支持 。 在本文中&#xff0c;我将介绍如何将Hamcrest的非核心匹配器与JUnit一起应用。 这些非核心匹配器默认情…

4pics1word android,4 Pics 1 Word

4 Pics 1 Word是一款非常有意思的看图猜词游戏&#xff0c;这款游戏中会给我们四张图片&#xff0c;玩家需要通过图片给出的信息来猜出是哪个词&#xff0c;看西西的介绍你可能以为这是一款千篇一律的看图猜词游戏&#xff0c;不过这里猜的不是中文而是英语单词。4 Pics 1 Word…

页面内锚点定位及跳转方法总结

接着上一篇&#xff0c;其实是一个功能&#xff0c;本来感觉挺简单的一个问题&#xff0c;没想到遇到两个坎儿&#xff0c;无语。。。 上一篇是关于scroll事件绑定的问题&#xff0c;这一篇的问题是&#xff1a;点击锚点跳转到相应DIV的问题。 最简单的方法是锚点用<a>标…

基于android的水稻叶片特征测量系统,基于Android的水稻叶片特征参数测量系统

基于Android的水稻叶片特征参数测量系统路艳1&#xff0c;肖志勇2&#xff0c;3&#xff0c;杨红云2&#xff0c;3*&#xff0c;周琼1&#xff0c;孙玉婷1【摘要】摘要&#xff1a;【目的】提供基于Android的水稻叶片特征参数测量系统&#xff0c;为农学研究提供精准数据。【方…

JAVA学习绘图颜色及其笔画属性设置字体显示文字

package com.graphics;import java.awt.*; import java.awt.geom.Rectangle2D; import java.util.Date;import javax.swing.*;/*** * author biexiansheng**/ public class DrawString extends JFrame{private Shape rect;//矩形对象private Font font;//字体对象private Date …

lightoj 1044 - Palindrome Partitioning(需要优化的区间dp)

题目链接&#xff1a;http://lightoj.com/volume_showproblem.php?problem1044 题意&#xff1a;求给出的字符串最少能分成多少串回文串。 一般会想到用区间dp暴力3个for但是这里的数据有1000&#xff0c;3个for肯定超时的。 但是这题只是判断回文串有多少个所以可以先预处理一…

对JavaFX Mobile应用程序进行性能分析

注意&#xff1a;本文最初发表于2009年&#xff0c;仅供参考。 请查阅我们其余的JavaFX文章 。 对于每个JavaFX Mobile应用程序开发人员来说&#xff0c;今天都是美好的一天。 你想知道为什么吗&#xff1f; 因为JavaME SDK 3.0已发布。 根据我午休时听到的消息&#xff0c;这是…

第六天20160810

a) 形参与实参 一、 形参为基本数据类型&#xff1a;形参改变&#xff0c;实参不变。 二、 形参为引用数据类型&#xff1a;形参改变&#xff0c;实参通常都会改变。 b) 可变长参数&#xff1a;JDK1.5开始出现 一、可变长参数只能用于…

android原生系统开发板,安卓学习必备开发板-Rayeager PX2

由谷歌主导并推动的移动终端操作系统Android&#xff0c;由于其开源开放的特性&#xff0c;自发布之日起便受到全球各大IT厂商的欢迎。在各厂商的热情推动下&#xff0c;基于Android系统的手机、平板、智能手表等各类产品层出不穷&#xff0c;迅速普及到人们的日常生活&#xf…

变量类型取值范围

ascii&#xff1a;Oct Dec Hex Char──────────────────────────101 65 41 A102 66 42 B103 67 43 C141 97 61 a142 98 62 b143 99 63 c 取值范围&#xff1a;-1 ~ 0xFFFFFFFF ~ 全1127 ~ 0x7F255 ~ 0xFF ~ 11111111 char -128 ~ 127 …

热点中的即时编译器(JIT)

即时编译器&#xff08;JIT&#xff09;的概念以及更广泛的自适应优化是除Java&#xff08;.Net&#xff0c;Lua&#xff0c;JRuby&#xff09;之外的许多语言中众所周知的概念。 为了解释什么是JIT编译器&#xff0c;我想先定义一个编译器概念。 根据维基百科&#xff0c;编译…

3.30下午

在另一台机子安装VMware workstation12和win8服务器 总是秘钥不行 很烦转载于:https://www.cnblogs.com/bgd140206314/p/6647159.html

Java并发性-任务反馈

从我 上一篇 关于java.util.concurrent包的 文章 的结尾处 摘下来 &#xff0c;这很有趣&#xff0c;有时甚至必须在并发任务启动后从它们那里获得反馈。 例如&#xff0c;假设一个应用程序必须发送电子邮件批处理&#xff0c;除了使用多线程机制外&#xff0c;您还想知道成功发…

JS中的函数(二):函数参数(你可能不知道的参数传递)

前言&#xff1a; 函数分为有参有返回值&#xff0c;有参无返回值&#xff0c;无参无返回值&#xff0c;无参有返回值&#xff1b;那么对于无参数的函数你想使用函数的调用怎么办呢&#xff1f;如果你想封装一个代码&#xff0c;实现多种功能&#xff0c;但是形参大于实参或者实…