Java Web系列:JDBC 基础
ADO.NET在Java中的对应技术是JDBC,企业库DataAccessApplicationBlock模块在Java中的对应是spring-jdbc模块,EntityFramework在Java中对应的ORM是Hibernate。关系数据库、SQL、数据库事务、分布式事务的概念都是通用的。
1.JDBC
JDBC代码和ADO.NET代码一样,除了学习时写demo来掌握核心对象外,不适合在项目中直接使用。另外Java中万年不变的学术派抽象接口给我目前看到的大多数容器和框架带来了极大的不便,如Tomcat和Spring中定义的一些抽象类型无论是属性和方法都和.NET中的很相似,但又不得不和Java中的基础接口适配。抽象不能像Java中一样只关注操作接口而不关注基础的数据结构,正确的类型的抽象比方法的抽象更重要,但Java中抽象的做法好像还有一个原则就是与众不同,而不只是关注操作。
(1)核心对象
ADO.NET中的4个核心抽象类是DbConnection、DbCommand、DbParameter和DbTransaction.DataAdapter和DataSet构建在核心对象之上。
JDBC的4个核心接口DataSource、Connection、Statement和ResultSet。PreparedStatement是Statement的子类型。
虽然两者不能完全匹配,对数据库操作的核心操作是一致的,都是打开链接、发送命令和关闭连接的过程。
(2)参数处理
参数的核心是索引和参数值。ADO.NET中提供了DbDataParameter类型用于参数的抽象。JDBC中没有提供参数的抽象类型,而是通过PreparedStatement定义的方法来设置参数,可以通过Connection对象获取该类型对象。
(3)事务处理
事务的核心操作是提交和回滚。ADO.NET中提供了DbTransaction类型用于事务的抽象,可以通过DbConnection的BeginTransaction方法开启显式事务.JDBC中没有提供事务的抽象类型,而是通过Connection定义的setAutoCommit、commit和rollback方法来操作事务。隐性事务的自动提交和显性事务的手动控制方面两者是一致的。
(4)数据源
JDBC中的Connection不具备连接池等高级功能。DataSource定义了数据源接口,用于连接管理、连接池和分布式事务等高级功能,连接池的重要性不用强调了。我们可以使用Apache Commons DBCP 2或C3P0(Hibernate)等第三方DataSource实现,Spring框架也有内置的一些简单的DataSource实现,如SimpleDriverDataSource、SingleConnectionDataSource、DriverManagerDataSource等。
我们分别使用DriverManager、commons-dbcp2(参考1)、c3p0(参考2)和h2database(参考3)演示无连接池、dbcp2连接池、c3p0连接池的使用:
package test.jdbc; import java.beans.PropertyVetoException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.sql.DataSource; import org.apache.commons.dbcp2.BasicDataSource;
import com.mchange.v2.c3p0.ComboPooledDataSource; public class Jdbc {
public static void main(String[] args) throws ClassNotFoundException, SQLException, PropertyVetoException {
String ddl = "create table user(id integer not null primary key,username varchar(64))";
String dml = "insert into user (id,username) values(1,'tom')";
String query = "select id,username from user where username=?";
String className = "org.h2.Driver";
String url = "jdbc:h2:mem:test";
// Connection conn = DriverManager.getConnection(url);
Connection conn = get_dbcp2_dataSource(className, url).getConnection();
// Connection conn = get_c3p0_dataSource(className,//
// url).getConnection();
conn.setAutoCommit(false);
conn.prepareStatement(ddl).execute();
conn.createStatement().execute(dml);
conn.commit();
conn.setAutoCommit(true);
PreparedStatement statement = conn.prepareStatement(query);
statement.setString(1, "tom");
ResultSet rs = statement.executeQuery();
User user = new User();
while (rs.next()) {
user.setId(rs.getInt(1));
user.setUsername("username");
break;
}
conn.close();
System.out.println(String.format("id:%d,username:%s", user.getId(), user.getUsername()));
} public static Connection getConnection(String driverClassName, String url) {
try {
Class.forName(driverClassName);
} catch (ClassNotFoundException e1) {
e1.printStackTrace();
}
Connection conn = null;
try {
conn = DriverManager.getConnection(url);
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
} public static DataSource get_dbcp2_dataSource(String clssName, String url) { BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName(clssName);
dataSource.setUrl(url);
return dataSource;
} public static DataSource get_c3p0_dataSource(String clssName, String url) throws PropertyVetoException { ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setDriverClass(clssName);
dataSource.setJdbcUrl(url);
return dataSource;
}
}
其中2dbcp、c3p0和h2database的Maven依赖如下:
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.190</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
2.Spring Jdbc
JDBC和ADO.NET的API类似,都不适合我们直接使用,如果不适用ORM框架,在.NET中我们使用DataAccessApplicationBlock,在Java中我们可以使用Spring JDBC。Spring JDBC的核心类是JdbcTemplate。
(1)Sprnig的委托实现
要使用Spring Jdbc的功能,首先要理解Spring中委托的使用方式,Spring定义一个包含该委托签名的接口(这些接口通常都是没有内置实现的),当需要委托参数时,使用该接口作为参数类型,利用Java中的匿名类功能,可以在内联代码中实现接口定义的委托,下面列举几个常见的委托接口:
Func<Connection,PreparedStatement>:PreparedStatement接口的createPreparedStatement方法。
public interface PreparedStatementCreator {
PreparedStatement createPreparedStatement(Connection con) throws SQLException;
}
Func<PreparedStatement,T>:PreparedStatementCallback泛型接口的doInPreparedStatement方法。
public interface PreparedStatementCallback<T> {
T doInPreparedStatement(PreparedStatement ps) throws SQLException, DataAccessException;
}
Func<TransactionStatus,T>:TransactionCallback泛型接口的T doInTransaction(TransactionStatus status)方法。
public interface TransactionCallback<T> {
T doInTransaction(TransactionStatus status);
}
Fcun<ResultSet,T>:ResultSetExtractor泛型方法的T extractData(ResultSet rs)方法。
public interface ResultSetExtractor<T> {
T extractData(ResultSet rs) throws SQLException, DataAccessException;
}
(1)JdbcTemplate
JdbcTemplate需要配合DataSource一起使用。JdbcTemplate的代码中很多都是通过IDE自动生成匿名类导致的,真正手写的代码量并不多。
public static void main(String[] args) throws ClassNotFoundException, SQLException, PropertyVetoException {
String ddl = "create table user(id integer not null primary key,username varchar(64))";
String dml = "insert into user (id,username) values(1,'tom')";
String query = "select id,username from user where username=?";
String className = "org.h2.Driver";
String url = "jdbc:h2:mem:test";
DataSource dataSource = get_dbcp2_dataSource(className, url);
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
PlatformTransactionManager tm = new DataSourceTransactionManager(dataSource);
TransactionTemplate tt = new TransactionTemplate(tm);
tt.execute(new TransactionCallback() {
@Override
public Object doInTransaction(TransactionStatus status) {
jdbcTemplate.execute(ddl);
jdbcTemplate.execute(dml);
return status;
}
});
User user = jdbcTemplate.query(query, new Object[] { "tom" }, new ResultSetExtractor<User>() {
@Override
public User extractData(ResultSet rs) throws SQLException, DataAccessException {
User user = new User();
while (rs.next()) {
user.setId(rs.getInt(1));
user.setUsername(rs.getString("username"));
break;
}
return user;
}
});
System.out.println(String.format("id:%d,username:%s", user.getId(), user.getUsername()));
}
(3)TransactionTemplate
在上面的代码中出现了TransactionTemplate用于事务处理,TransactionTemplate依赖PlatformTransactionManager,Spring Jdbc中定义的DataSourceTransactionManager实现类用于处理数据库事务。在Spring的orm、jsm、tx等模块中还有其他的实现。
(4)JdbcDaoSupport
JdbcDaoSupport是一个在内部使用JdbcTemplate字段并且实现了DaoSupport接口的抽象类,可供我们自定义DAO类时参考或用作基类。
class MyDao extends JdbcDaoSupport {
public MyDao(DataSource dataSource) {
this.setJdbcTemplate(new JdbcTemplate(dataSource));
}
@SuppressWarnings("unchecked")
public void init(String ddl, String dml) {
PlatformTransactionManager tm = new DataSourceTransactionManager(this.getDataSource());
TransactionTemplate tt = new TransactionTemplate(tm);
tt.execute(new TransactionCallback() {
@Override
public Object doInTransaction(TransactionStatus status) {
getJdbcTemplate().execute(ddl);
getJdbcTemplate().execute(dml);
return status;
}
});
}
public User getUser(String query, String username) {
return this.getJdbcTemplate().query(query, new Object[] { username }, new ResultSetExtractor<User>() {
@Override
public User extractData(ResultSet rs) throws SQLException, DataAccessException {
User user = new User();
while (rs.next()) {
user.setId(rs.getInt(1));
user.setUsername(rs.getString("username"));
break;
}
return user;
}
});
}
}
参考
(1)http://commons.apache.org/proper/commons-dbcp/download_dbcp.cgi
(2)http://sourceforge.net/projects/c3p0/
(3)http://www.h2database.com/html/cheatSheet.html
(4)http://commons.apache.org/proper/commons-dbcp/guide/jndi-howto.html
Java Web系列:JDBC 基础的更多相关文章
- 重拾Java Web应用的基础体系结构
目录 一.背景 二.Web应用 2.1 HTML 2.2 HTTP 2.3 URL 2.4 Servlet 2.4.1 编写第一个Servlet程序 2.5 JSP 2.6 容器 2.7 URL映射到 ...
- Java Web系列:Spring MVC基础
1.Web MVC基础 MVC的本质是表现层模式,我们以视图模型为中心,将视图和控制器分离出来.就如同分层模式一样,我们以业务逻辑为中心,把表现层和数据访问层代码分离出来是一样的方法.框架只能在技术层 ...
- Java Web系列:Spring Security 基础
Spring Security虽然比JAAS进步很大,但还是先天不足,达不到ASP.NET中的认证和授权的方便快捷.这里演示登录.注销.记住我的常规功能,认证上自定义提供程序避免对数据库的依赖,授权上 ...
- Java Web系列:Java Web 项目基础
1.Java Web 模块结构 JSP文件和AXPX文件类似,路径和URL一一对应,都会被动态编译为单独class.Java Web和ASP.NET的核心是分别是Servlet和IHttpHandle ...
- java web filter 之一 基础实现
本文主要对filter的基本使用进行了讲解,其中涉及到了 filter是什么 一个filter处理一个jsp 多个filter处理一个jsp filter是什么 Filter 是java下的一种过滤器 ...
- Java Web系列:Spring Boot 基础
Spring Boot 项目(参考1) 提供了一个类似ASP.NET MVC的默认模板一样的标准样板,直接集成了一系列的组件并使用了默认的配置.使用Spring Boot 不会降低学习成本,甚至增加了 ...
- Java Web系列:Spring依赖注入基础
一.Spring简介 1.Spring简化Java开发 Spring Framework是一个应用框架,框架一般是半成品,我们在框架的基础上可以不用每个项目自己实现架构.基础设施和常用功能性组件,而是 ...
- Java Web系列:Spring Boot 基础 (转)
Spring Boot 项目(参考1) 提供了一个类似ASP.NET MVC的默认模板一样的标准样板,直接集成了一系列的组件并使用了默认的配置.使用Spring Boot 不会降低学习成本,甚至增加了 ...
- Java Web系列:JAAS认证和授权基础
1.认证和授权概述 (1)认证:对用户的身份进行验证. .NET基于的RBS(参考1)的认证和授权相关的核心是2个接口System.Security.Principal.IPrincipal和Syst ...
随机推荐
- Chrome JS断点调试技巧
Chrome调试折腾记_(2)JS断点调试技巧 技巧一:格式化压缩代码 技巧二:快速跳转到某个断点的位置 技巧三:查看断点内部的作用范围[很实用] 技巧4:监听事件断点 技巧5:DOM及 XHR监听跳 ...
- ElasticSearch之CURL操作
CURL的操作 curl是利用URL语法在命令行方式下工作的开源文件传输工具,使用curl可以简单实现常见的get/post请求.简单的认为是可以在命令行下面访问url的一个工具.在centos ...
- 中信信用卡淘气金卡,V金卡,大众点评金卡,易卡白金卡
中信 | 谈谈经典多倍积分卡:易卡&悦卡(超详细+图解+思考)! http://www.flyertea.com/thread-1972766-1-1.html 易卡积分测试,购物/机票/外卖 ...
- python socket 详细介绍
Python 提供了两个基本的 socket 模块. 第一个是 Socket,它提供了标准的 BSD Sockets API. 第二个是 SocketServer, 它提供了服务器中心类,可以简化网络 ...
- C#遍历XmlDocument对象所有节点名称、类型、属性(Attribute)
C#遍历XmlDocument对象所有节点名称.类型.属性(Attribute) 源码下载 代码 static void Main(string[] args) { System.Xml.XmlDoc ...
- 开始Django之旅
MTV 与 MVC 模型 1.MVC模型 Web服务器开发领域里著名的MVC模式,所谓MVC就是把Web应用分为 模型(M) ,控制器(C) 和 视图(V) 三层,他们之间以一种插件式的.松耦合的方式 ...
- Django学习---组合搜索组件
组合搜索组件 我们都会写博客,写文章之后我们要给文章设置目录,设置类型.之后我们在浏览文章的时候就能够按类别进行精确定位到文章,那这个组合搜索我们应该怎么做呢? 首先我们先创建3张表,分别存放文章,文 ...
- React-Todos
最近学完React的最基本概念,闲下来的时候就自己写了一个Todo-List的小应用.这里做个简略的说明,给想好好学React的新手看. React-Todo 学习前提 这里我用了webpackb做了 ...
- vc通过进程名返回进程id
std::string WcharToChar(const wchar_t* wp, size_t m_encode = CP_ACP) { std::string str; , wp, wcslen ...
- gradle 刷新缓存
gradle build --refresh-dependencies -x test