• 两岸民心相亲不可违逆(观沧海) 2019-06-24
  • 习近平新时代中国特色社会主义思想为解决人类问题贡献中国智慧 2019-06-22
  • 反击!欧盟成员国一致支持对美28亿欧元产品征收报复性关税 2019-06-22
  • 专访李毅立:走进国家 了解国情 续写中华情 2019-06-08
  • 现在,表面上看,很多城市绿树成荫,花卉草地到处都是,实际上地下空间已经掏空,建了车库、地下商城,雨水根本渗不下去。 2019-06-08
  • 你反来复去说1+1=2,真痴呆了?你应该讲点其他的吧,譬如,1+1=2,是客观事实还是规律,是真理还是谬误。 2019-06-05
  • 蜈蚣精的出游必备战靴 旅行路上皆战场 2019-06-05
  • 《法医秦明2》“长腿CP”最萌身高差吸睛 剧情高能 2019-06-04
  • 【春到渭南】随手拍渭南各地区春景,一贴看尽渭南春色! 2019-06-04
  • 如何像皇帝、老佛爷那样避个暑? 2019-05-30
  • 印度总理寓所附近现UFO?网友:外星人也想看莫迪 2019-05-21
  • 人民网评:建设一支生态环境保护铁军 2019-05-21
  • 这三个史无前例,让美国有点懵了 2019-05-18
  • 唐嫣蜡像入驻上海杜莎夫人蜡像馆--旅游频道 2019-05-18
  • 生活调查:过午不食可以养生减肥是真的吗? 2019-05-18
  • 北京冰球俱乐部:

    北京 切换校区

    全国24小时免费热线

    400-009-1906

    Java Web系列:JDBC 基础

    时间:2019-01-22   来源:尚学堂   阅读:292

    ADO.NET在Java中的对应技术是JDBC,企业库DataAccessApplicationBlock??樵贘ava中的对应是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() {
    
    [email protected]
    ????????public Object doInTransaction(TransactionStatus status) {
    ????????????jdbcTemplate.execute(ddl);
    ????????????jdbcTemplate.execute(dml);
    ????????????return status;
    ????????}
    ????});
    
    ????User user = jdbcTemplate.query(query, new Object[] { "tom" }, new ResultSetExtractor<User>() {
    [email protected]
    ????????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));
    ?????}
    
    [email protected]("unchecked")
    ?????public void init(String ddl, String dml) {
    ?????????PlatformTransactionManager tm = new DataSourceTransactionManager(this.getDataSource());
    ?????????TransactionTemplate tt = new TransactionTemplate(tm);
    
    ????????tt.execute(new TransactionCallback() {
    
    [email protected]
    ????????????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>() {
    [email protected]
    ????????????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;
    ????????????}
    ????????});
    ????}
    }

    相关资讯

    • 北京校区
    • 山西校区
    • 郑州校区
    • 武汉校区
    • 四川校区
    • 长沙校区
    • 深圳校区
    • 上海校区
    • 广州校区
    • 保定招生办

    北京海淀区校区(总部):北京市海淀区西三旗街道建材城西路中腾建华商务大厦东侧二层尚学堂
    北京京南校区:北京亦庄经济开发区科创十四街6号院1号楼 赛蒂国际工业园
    咨询电话:400-009-1906 / 010-56233821
    面授课程:?JavaEE+微服务+大数据? ???大数据+机器学习+平台架构?????Python+数据分析+机器学习??人工智能+模式识别+强化学习???WEB前端+移动端+服务端渲染

     

    山西学区地址:山西省晋中市榆次区大学城大学生活广场万科商业A1座702

    郑州学区地址:河南电子商务产业园6号楼4层407
    咨询电话:0371-55177956

    武汉学区地址:武汉市东湖高新区光谷金融港B22栋11楼
    咨询电话:027-87989193

    四川学区地址:成都市高新区锦晖西一街99号布鲁明顿大厦2栋1003室
    咨询电话:028-65176856 / 13880900114

    网址://www.cssxt.com/
    咨询电话:0731-83072091

    深圳校区地址:深圳市宝安区航城街道航城大道航城创新创业园A4栋210(固戍地铁站C出口)
    咨询电话:0755-23061965 / 18898413781

    上海尚学堂松江校区地址:上海市松江区荣乐东路2369弄45号绿地伯顿大厦2层
    咨询电话:021-67690939

    广州校区地址:广州市天河区元岗横路31号慧通产业广场B区B1栋6楼尚学堂(地铁3号线或6号线到“天河客运站”D出口,右拐直走约800米)
    咨询电话:020-2989 6995

    保定招生办公室

    地址:河北省保定市竞秀区朝阳南大街777号鸿悦国际1101室

    电话:15132423123

    Copyright 2006-2019 北京尚学堂科技有限公司  京ICP备13018289号-19  京公网安备11010802015183  
    媒体联系:18610174079 闫老师  

    Java基础班,免费试学三周

  • 两岸民心相亲不可违逆(观沧海) 2019-06-24
  • 习近平新时代中国特色社会主义思想为解决人类问题贡献中国智慧 2019-06-22
  • 反击!欧盟成员国一致支持对美28亿欧元产品征收报复性关税 2019-06-22
  • 专访李毅立:走进国家 了解国情 续写中华情 2019-06-08
  • 现在,表面上看,很多城市绿树成荫,花卉草地到处都是,实际上地下空间已经掏空,建了车库、地下商城,雨水根本渗不下去。 2019-06-08
  • 你反来复去说1+1=2,真痴呆了?你应该讲点其他的吧,譬如,1+1=2,是客观事实还是规律,是真理还是谬误。 2019-06-05
  • 蜈蚣精的出游必备战靴 旅行路上皆战场 2019-06-05
  • 《法医秦明2》“长腿CP”最萌身高差吸睛 剧情高能 2019-06-04
  • 【春到渭南】随手拍渭南各地区春景,一贴看尽渭南春色! 2019-06-04
  • 如何像皇帝、老佛爷那样避个暑? 2019-05-30
  • 印度总理寓所附近现UFO?网友:外星人也想看莫迪 2019-05-21
  • 人民网评:建设一支生态环境保护铁军 2019-05-21
  • 这三个史无前例,让美国有点懵了 2019-05-18
  • 唐嫣蜡像入驻上海杜莎夫人蜡像馆--旅游频道 2019-05-18
  • 生活调查:过午不食可以养生减肥是真的吗? 2019-05-18
  • 生肖时时彩中奖几率 天霁彩票论坛 九线水果拉霸棋牌 西甲直播西班牙人巴拉多利德 热那亚鸡是什么味道 2005年5月25日利物浦 6场半全场18153期 浙江快乐彩中奖规则图 买中特肖怎么赔 球球大作战下载官方下载 天涯明月刀心法 真人娱乐旗舰厅 重庆时时彩开奖 星际争霸2视频 广岛三箭墨尔本胜利比分预测 寻宝记电子游戏