如何创建 DataSource
By:zozoh<zozohtnt@gmail.com>wendal<wendal1985@gmail.com>

何为DataSource

Top

先看看JDK中对DataSource的描述:

Top

简单来说,就是获取数据库连接的一个通用接口, 常见的dbcp,c3p0,druid都是DataSource的实现.

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

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

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

这篇文档该怎么用?

Top

直接书写 Java 代码

Top

通过 Nutz.Ioc 的 JSON 配置文件

Top

通过 Nutz.Ioc 的 XML 配置文件

Top

再特别特别强调

Top

内置的SimpleDataSource

Top

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

Top

完整的NutDao配置js文件

Top
var ioc = {
	dao : {
		type : "org.nutz.dao.impl.NutDao",
		args : [{refer:"dataSource"}]
	},
	dataSource : {
		type : "org.nutz.dao.impl.SimpleDataSource",
		fields : {
			jdbcUrl : 'jdbc:postgresql://localhost:5432/mydatabase',
			username : 'demo',
			password : '123456'
		}
	}
}

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

Druid(推荐)

Top

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

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

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

Apache DBCP

Top

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

Top
{
	dataSource : {
		type : "org.apache.commons.dbcp.BasicDataSource",
		events : {
			depose : 'close'
		},
		fields : {
			driverClassName : 'org.postgresql.Driver',
			url : 'jdbc:postgresql://localhost:5432/mydatabase',
			username : 'demo',
			password : '123456'
		}
	}
}

C3P0(不推荐)

Top

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

Top
{
	dataSource : {
		type : "com.mchange.v2.c3p0.ComboPooledDataSource",
		events : {
			depose : 'close'
		},
		fields : {
			driverClass : 'org.postgresql.Driver',
			jdbcUrl : 'jdbc:postgresql://localhost:5432/mydatabase',
			user : 'demo',
			password : '123456'
		}
	}
}

Proxool(严重不推荐)

Top

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

Top
{
	dataSource : {
		type : "org.logicalcobwebs.proxool.ProxoolDataSource",
		fields : {
			driver : 'org.postgresql.Driver',
			driverUrl : 'jdbc:postgresql://localhost:5432/mydatabase',
			user : 'demo',
			password : '123456'
		}
	}
}

容器提供的连接池(JNDI)

Top

Java代码方式:

Top

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

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

Top
{
	dao : {
		type : "org.nutz.dao.impl.NutDao",
		args : [{jndi:"jdbc/dataSource"}]
	}
}

遗留系统

Top

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

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

配置

Top
{
	dao : {
		type : "org.nutz.dao.impl.NutDao",
		args : [{refer:"dataSource"}]
	},
	dataSource : {
		type : "net.wendal.nutzbook.MyDataSource"
	}
}

如何使用这些配置

Top

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

Java代码的方式:

Top
//创建dataSource, 代码仅供演示,实际使用的话必须单例或使用DaoUp类(推荐)
SimpleDataSource ds = new SimpleDataSource();
ds.setUrl("jdbc:postgresql://localhost:5432/mydatabase");
ds.setUsername("demo");
ds.setPassword("123456");
Dao dao = new NutDao(ds);//实际使用的话必须单例或使用DaoUp类(推荐)

dao.create(User.class, true);
dao.insert(User.create("wendal","123456"));

//.... ... ...

//所有操作都已经完成,关闭连接池,退出系统
ds.close();
return;

//额外提醒,NutDao是线程安全的,请不要多次创建NutDao,除非你有多个DataSource

通过 Nutz.Ioc 的 JSON 配置文件

Top
//将配置信息保存到dao.js,并存放于src文件夹下. 代码仅供演示,实际使用的话必须单例

Ioc ioc = new NutIoc(new JsonLoader("dao.js"));
DataSource ds = ioc.get(DataSource.class);
Dao dao = new NutDao(ds); //如果已经定义了dao,那么改成dao = ioc.get(Dao.class);

dao.create(User.class, true);
dao.insert(User.create("wendal","123456"));

ioc.depose(); //关闭Ioc容器

通过 Nutz.Ioc 的 XML 配置文件

Top
//将配置信息保存到dao.xml,并存放于src文件夹下. 代码仅供演示,实际使用的话必须单例

Ioc ioc = new NutIoc(new XmlIocLoader("dao.xml"));
DataSource ds = ioc.get(DataSource.class);
Dao dao = new NutDao(ds); //如果已经定义了dao,那么改成dao = ioc.get(Dao.class);

dao.create(User.class, true);
dao.insert(User.create("wendal","123456"));

ioc.depose(); //关闭Ioc容器

重要提醒

Top

绝对错误的用法

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

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

Top
private static Ioc ioc;

public Dao getDao() { // 暂不考虑线程同步的问题
	if (ioc == null)
		ioc = new NutIoc(new JsonLoader("ioc/dao.js")); 
	return ioc.get(Dao.class);
}

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

Top
// 在request作用域内
public Dao getDao() {
	Mvcs.getIoc().get(Dao.class);
}

// 在request作用域之外
public Dao getDao() {
	Mvcs.ctx().getDefaultIoc().get(Dao.class);
}