如何创建 DataSource

Dec 19, 2018 8:59:11 PM

作者:zozohwendal

何为DataSource

先看看JDK中对DataSource的描述:

  • 作为 DriverManager 工具的替代项,DataSource 对象是获取连接的首选方法。
  • 基本实现 - 生成标准的 Connection 对象
  • 连接池实现 - 生成自动参与连接池的 Connection 对象。此实现与中间层连接池管理器一起使用。
    简单来说,就是获取数据库连接的一个通用接口, 常见的dbcp,c3p0,druid都是DataSource的实现.

NutDao也选用DataSource作为获取数据库连接的方式, 且只调用其无参数的getConnection()方法,也是大部分数据库连接池唯一支持的方法.

提醒一下, DataSource只是接口,不等于连接池

NutDao不挑剔任何连接池/DataSource实现,只要实现了DataSource接口就行,不存在是否支持"XXXX连接池"的问题

这篇文档该怎么用?

直接书写 Java 代码

  • 请使用DaoUp类

通过 Nutz.Ioc 的 JSON 配置文件

  • Nutz项目中最常见的配置方式, 由NutIoc来管理DataSource和NutDao实例
  • 特别强调, NutDao与NutIoc没有任何依赖关系, NutDao在NutIoc看来,只是普通的bean
  • 严禁new NutIoc然后单单为了获取一个Dao实例!!

通过 Nutz.Ioc 的 XML 配置文件

  • 满足XML强迫症的程序猿, 功能与JSON配置文件类似

再特别特别强调

  • NutDao几乎不需要任何配置文件(只有一个nutz_jdbc_experts.js 绝大部分时间你不会遇到它!)
  • 本文说到的js/xml文件,都是NutIoc的文件,不是NutDao的配置文件!!
  • 不要重复创建DataSource,不要重复创建NutDao!!!!!!!
  • 务必参考本小节末尾的提醒!!

内置的SimpleDataSource

Nutz内置,无需额外下载其他连接池/DataSource实现,方便尝试NutDao的功能.

  • 不要生产环境中使用这个DataSource!!
  • 不要用它来测试NutDao的性能!!
  • 自动加载NutDao所支持的数据库的驱动(说白了就是我们认识那几款,不就Class.forName一下嘛)
  • 无额外依赖,适合新手试用
  • 非连接池,配置简单
  • Oracle数据库不能使用,原因是Oracle的数据库连接是重量级的,必须用连接池才不会崩

完整的NutDao配置js文件

  1. var ioc = {
  2. dao : {
  3. type : "org.nutz.dao.impl.NutDao",
  4. args : [{refer:"dataSource"}]
  5. },
  6. dataSource : {
  7. type : "org.nutz.dao.impl.SimpleDataSource",
  8. fields : {
  9. jdbcUrl : 'jdbc:postgresql://localhost:5432/mydatabase',
  10. username : 'demo',
  11. password : '123456'
  12. }
  13. }
  14. }

如何使用这些配置? 请看文章末尾.

Druid(推荐)

国产精品连接池,淘宝温少诚意出品,带强大的监控功能哦, 推荐1.0.25+

druid : 通过 Nutz.Ioc 的 JSON 配置文件

  1. {
  2. dataSource : {
  3. type : "com.alibaba.druid.pool.DruidDataSource",
  4. events : {
  5. depose : 'close'
  6. },
  7. fields : {
  8. url : "jdbc:postgresql://localhost:5432/mydatabase",
  9. username : "enzozhong",
  10. password : "123",
  11. maxWait: 15000, // 若不配置此项,如果数据库未启动,druid会一直等可用连接,卡住启动过程
  12. defaultAutoCommit : false // 提高fastInsert的性能
  13. }
  14. }
  15. }

Apache DBCP

dbcp: 通过 Nutz.Ioc 的 JSON 配置文件

  1. {
  2. dataSource : {
  3. type : "org.apache.commons.dbcp.BasicDataSource",
  4. events : {
  5. depose : 'close'
  6. },
  7. fields : {
  8. driverClassName : 'org.postgresql.Driver',
  9. url : 'jdbc:postgresql://localhost:5432/mydatabase',
  10. username : 'demo',
  11. password : '123456'
  12. }
  13. }
  14. }

C3P0(不推荐)

c3p0: 通过 Nutz.Ioc 的 JSON 配置文件

  1. {
  2. dataSource : {
  3. type : "com.mchange.v2.c3p0.ComboPooledDataSource",
  4. events : {
  5. depose : 'close'
  6. },
  7. fields : {
  8. driverClass : 'org.postgresql.Driver',
  9. jdbcUrl : 'jdbc:postgresql://localhost:5432/mydatabase',
  10. user : 'demo',
  11. password : '123456'
  12. }
  13. }
  14. }

Proxool(严重不推荐)

proxool: 通过 Nutz.Ioc 的 JSON 配置文件

  1. {
  2. dataSource : {
  3. type : "org.logicalcobwebs.proxool.ProxoolDataSource",
  4. fields : {
  5. driver : 'org.postgresql.Driver',
  6. driverUrl : 'jdbc:postgresql://localhost:5432/mydatabase',
  7. user : 'demo',
  8. password : '123456'
  9. }
  10. }
  11. }

容器提供的连接池(JNDI)

Java代码方式:

不写了,这个大家都懂,不懂的自己去google查. 别跟我说baidu没查到!!

由于是通过JNDI获取,所以不再是一个Ioc的bean, 我们只需要引用它就可以了,不需要再写dataSource的bean.例如:

  1. {
  2. dao : {
  3. type : "org.nutz.dao.impl.NutDao",
  4. args : [{jndi:"jdbc/dataSource"}]
  5. }
  6. }

遗留系统

指一些不能提供连接池或自定义获取Connection的项目,可以实现如下封装类,代理为DataSource

  1. public class MyDataSource implements DataSource {
  2. public Connection getConnection() throws SQLException {
  3. // 调用遗留系统中获取数据库连接的方法即可
  4. }
  5. // 还有其他一些方法,全部默认实现就可以了,不会调用到.
  6. }
  7.  

配置

  1. {
  2. dao : {
  3. type : "org.nutz.dao.impl.NutDao",
  4. args : [{refer:"dataSource"}]
  5. },
  6. dataSource : {
  7. type : "net.wendal.nutzbook.MyDataSource"
  8. }
  9. }

如何使用这些配置

推荐使用org.nutz.dao.util.DaoUp类,非Mvc环境下的全生命周期Dao工具.下面描述的是纯手工创建的代码.

Java代码的方式:

  1. //创建dataSource, 代码仅供演示,实际使用的话必须单例或使用DaoUp类(推荐)
  2. SimpleDataSource ds = new SimpleDataSource();
  3. ds.setUrl("jdbc:postgresql://localhost:5432/mydatabase");
  4. ds.setUsername("demo");
  5. ds.setPassword("123456");
  6. Dao dao = new NutDao(ds);//实际使用的话必须单例或使用DaoUp类(推荐)
  7. dao.create(User.class, true);
  8. dao.insert(User.create("wendal","123456"));
  9. //.... ... ...
  10. //所有操作都已经完成,关闭连接池,退出系统
  11. ds.close();
  12. return;
  13. //额外提醒,NutDao是线程安全的,请不要多次创建NutDao,除非你有多个DataSource

通过 Nutz.Ioc 的 JSON 配置文件

  1. //将配置信息保存到dao.js,并存放于src文件夹下. 代码仅供演示,实际使用的话必须单例
  2. Ioc ioc = new NutIoc(new JsonLoader("dao.js"));
  3. DataSource ds = ioc.get(DataSource.class);
  4. Dao dao = new NutDao(ds); //如果已经定义了dao,那么改成dao = ioc.get(Dao.class);
  5. dao.create(User.class, true);
  6. dao.insert(User.create("wendal","123456"));
  7. ioc.depose(); //关闭Ioc容器

通过 Nutz.Ioc 的 XML 配置文件

  1. //将配置信息保存到dao.xml,并存放于src文件夹下. 代码仅供演示,实际使用的话必须单例
  2. Ioc ioc = new NutIoc(new XmlIocLoader("dao.xml"));
  3. DataSource ds = ioc.get(DataSource.class);
  4. Dao dao = new NutDao(ds); //如果已经定义了dao,那么改成dao = ioc.get(Dao.class);
  5. dao.create(User.class, true);
  6. dao.insert(User.create("wendal","123456"));
  7. ioc.depose(); //关闭Ioc容器

重要提醒

  • 非Mvc环境建议用DaoUp类.
  • Mvc环境下请使用IocBy.
  • 上面提及的Java代码均为演示(main方法中的简单示例),实际用的时候, 必须将ioc容器本身单例化(例如存放到一个static属性)
  • 重复创建DataSource(例如反复创建ioc容器, new NutIoc(…))会导致数据库连接数耗尽.
  • ioc容器本身,应该尽可能作为单例, 不要创建一个ioc容器后,获取ioc对象,然后就抛弃, 例如:

绝对错误的用法

  1. public Dao getDao() { // 无论改方法被调用一次还是N次, 均为错误!!
  2. Ioc ioc = new NutIoc(new JsonLoader("ioc/dao.js")); // 反复创建ioc容器
  3. return ioc.get(Dao.class); //方法返回后, ioc必然被gc, 从而触发ioc的depose事件,导致DataSource关闭!
  4. }

不那么错误的用法,严重建议用DaoUp类

  1. private static Ioc ioc;
  2. public Dao getDao() { // 暂不考虑线程同步的问题
  3. if (ioc == null)
  4. ioc = new NutIoc(new JsonLoader("ioc/dao.js"));
  5. return ioc.get(Dao.class);
  6. }

Mvc中的正确用法,使用IocBy配置ioc,尽可能通过@Inject等方式获取ioc的bean.在无法直接获取Ioc容器的代码中,使用下列代码

  1. // 在request作用域内
  2. public Dao getDao() {
  3. Mvcs.getIoc().get(Dao.class);
  4. }
  5. // 在request作用域之外
  6. public Dao getDao() {
  7. Mvcs.ctx().getDefaultIoc().get(Dao.class);
  8. }

本页面的文字允许在知识共享 署名-相同方式共享 3.0协议GNU自由文档许可证下修改和再使用。

原文: http://nutzam.com/core/appendix/create_datasource.html