jfinal_多数据源连接
前言
JFinal,开发程序非常方便,尤其是控制台显示每次请求的具体信息,易读而且可以点击类名到对应的类中去修改。spring的日志真的密密麻麻,看的眼花。
此文演示如何用JFinal连接多个数据库,我尝试过连着mysql和oracle,没有问题。连接多个数据库,可以兼容以前的代码,以前连接的数据库当做主数据库,后面添加的数据库当做从数据库。
扩展:如何让JFinal使用sql文件,实现代码与sql分离。(多数据源演示)
配置JFinal并运行起来
因为我本地没有JFinal项目,所以首先下载JFinal源码。下载完之后,根据
启动说明,把该配好的配好,试着运行一下。
没有任何问题后,进行下一步操作。
安装数据库jar包
默认情况,JFinal的demo已经包含有mysql驱动jar,所以无需安装。
如果需要连接oracle,则需要在pom文件中引入jar包。
因为此文是连接两个mysql,jar包根据实际需求引入,不再截图演示。
然后准备两个数据库即可。
配置JFinal连接数据库
首先在配置文件(demo-config-dev.txt)中配置数据库地址和账号密码
1
2
3
4
5
6
7
8
9
10
11
12config
数据库1
jdbcUrl = jdbc:mysql://localhost/jfinal_demo?characterEncoding=utf8&useSSL=false&zeroDateTimeBehavior=convertToNull
user = root
password = 123456
数据库2
jdbcUrl2 = jdbc:mysql://localhost/double?characterEncoding=utf8&useSSL=false&zeroDateTimeBehavior=convertToNull
user2 = root
password2 = 123456
devMode = true先在配置类(DemoConfig)中创建一个方法,用来得到数据库2的数据源
1
2
3
4
5
6
7
8/***
* 得到数据库2的数据源
* @return
*/
public static DruidPlugin createDruidPlugin2(){
loadConfig();
return new DruidPlugin(p.get("jdbcUrl2"), p.get("user2"), p.get("password2"));
}因为已经有获取数据库1的数据源方法,所以无需再建立一个函数来获取数据库1的数据源
修改_JFinalDemoGenerator的getDataSource,生成对应的实体类,生成之前先切换数据库
1
2
3
4
5
6
7
8public static DataSource getDataSource() {
// 数据库1的数据源
//DruidPlugin druidPlugin = DemoConfig.createDruidPlugin();
// 数据库2的数据源
DruidPlugin druidPlugin = DemoConfig.createDruidPlugin2();
druidPlugin.start();
return druidPlugin.getDataSource();
}
提醒:如果你的数据库不是mysql,请修改main方法里面的设置数据库方言
接着运行main方法就可以自动生成数据库2的实体类
创建数据库2的映射类,同时复制数据库1的映射类,作为副本
因为_MappingKit这个类会根据数据库生成实体而改变,当有两个以上的数据库的时候,_MappingKit就不太适合了。
我们创建两个类,一个叫做_MappingKit1,一个叫做_MappingKit2,分别为数据库1实体映射和数据库2实体映射
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19/***
* 数据库1的映射
*/
public class _MappingKit1 {
public static void mapping(ActiveRecordPlugin arp) {
arp.addMapping("blog", "id", Blog.class);
}
}
/***
* 数据库2的映射
*/
public class _MappingKit2 {
public static void mapping(ActiveRecordPlugin arp) {
arp.addMapping("double_name", "id", DoubleName.class);
}
}
在配置类(DemoConfig)中修改configPlugin里面的方法内容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25/**
* 配置插件
*/
public void configPlugin(Plugins me) {
// 配置 druid 数据库连接池插件
// 数据库1
DruidPlugin druidPlugin = new DruidPlugin(p.get("jdbcUrl"), p.get("user"), p.get("password"));
me.add(druidPlugin);
// 配置ActiveRecord插件
ActiveRecordPlugin arp = new ActiveRecordPlugin(druidPlugin);
arp.setDialect(new MysqlDialect());//设置数据库方言,默认是mysql,可以不设置
_MappingKit1.mapping(arp);//将数据库1生成的实体类添加ActiveRecord插件
me.add(arp);// 数据库1添加到插件中
// 数据库2
DruidPlugin druidPlugin_2 = new DruidPlugin(p.get("jdbcUrl2"), p.get("user2"), p.get("password2").trim());
me.add(druidPlugin_2);
// 配置ActiveRecord插件
ActiveRecordPlugin arp_2 = new ActiveRecordPlugin("mysql2",druidPlugin_2);
//设置数据库方言,默认是mysql,可以不设置,如果是oracle,设置OracleDialect
arp_2.setDialect(new MysqlDialect());
_MappingKit2.mapping(arp_2);//将数据库1生成的实体类添加ActiveRecord插件
me.add(arp_2);//数据库2添加到插件中
}添加数据库2的增删改查,并添加路由和页面
添加对应的control类
添加对应的service类
添加路由
添加页面
上面省略具体步骤,照着原来的demo,做一个增删改查不难。
如果用dao或者实体类去操作数据库,你感觉不到你是在操作两个数据库,细节被隐藏,只需要按平常的写法写就可以了。
如果是Db操作数据库,需要使用use方法,具体请看代码演示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23public DoubleName findById(int id) {
// 仅当做示范,实际不可能这么做,用Db反而麻烦,Db针对于特殊的sql需求
DoubleName doubleName = new DoubleName();
String sql = "select * from double_name where id = ?";
SqlPara sqlPara = new SqlPara();
sqlPara.addPara(id);
sqlPara.setSql(sql);
// 因为连接的是数据库2,而不是数据库1,也就是连接 从数据库 需要使用Db.use("别名")
// mysql2 的别名来自于 DemoConfig 类中 configPlugin方法里
// 配置ActiveRecord插件
// ActiveRecordPlugin arp_2 = new ActiveRecordPlugin("mysql2",druidPlugin_2);
List<Record> recordList = Db.use("mysql2").find(sqlPara);
if(recordList != null && recordList.size() >= 0)
{
Record record = recordList.get(0);
Long id_ = record.get("id");
String name_ = record.get("name");
doubleName.setId(id_);
doubleName.setName(name_);
}
return doubleName;
//return dao.findById(id);
}
JFinal 连接多数据库完成
上面已经讲完JFinal怎么连接多个数据库的,下面介绍如何把sql语句写到sql文件中,而不是在java文件中写sql语句,下面是根据连接多个数据源的基础之上做的,只连接一个数据源也适用。
JFinal 如何将sql与代码分离
首先看DemoConfig,调用一个方法即可加载该数据库的sql模板
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50// 在configPlugin中
// 数据库1 添加sql模板
setSql(arp,"sql/mysql1");
// 数据库2 添加sql模板
setSql(arp_2,"sql/mysql2");
// 以下为setSql的函数内容
/***
* 添加sql文件到ActiveRecordPlugin插件中
* @param arp ActiveRecord插件
* @param sqlPath sql 加载路径
*/
public void setSql(ActiveRecordPlugin arp,String sqlPath)
{
Engine engine = arp.getEngine();
// 上面的代码获取到了用于 sql 管理功能的 Engine 对象,接着就可以开始配置了
engine.setToClassPathSourceFactory();//设置读取sql文件的基础路径为 resource 下,即classes下
engine.setDevMode(p.getBoolean("devMode", true));
//可以在这里添加指令和方法,就如同给html添加一样。
engine.addSharedObject("sk", new com.jfinal.kit.StrKit());
arp.setShowSql(p.getBoolean("devMode", true));//设置sql语句日志
arp.setDevMode(p.getBoolean("devMode", true));//设置热部署sql
//添加sql模板,注添加sql文件请重启服务
String basePath = PathKit.getRootClassPath();
sqlPath = basePath+File.separator+sqlPath;
arpAddSql(arp,sqlPath,basePath);
}
public static void arpAddSql(ActiveRecordPlugin arp,String sqlPath,String basePath)
{
File[]files = new File(sqlPath).listFiles();
if(files != null)
{
for(File f : files) {
if(f.isFile()&& f.getName().endsWith(".sql") ){
String absolutePath = f.getAbsolutePath();
String filePath = absolutePath.replace(basePath+File.separator,"");
System.out.println(filePath);
arp.addSqlTemplate(filePath);
}else if(f.isDirectory())
{
arpAddSql(arp,f.getAbsolutePath(),basePath);
}
}
}
}在resource目录下新建文件夹和文件,具体如下:
分别写对应的sql
以下是blog.sql 文件里面的内容
1
2
3
4
5
6
7
8
9
10
11
12
13### 名称空间
#namespace("blogSpace")
### sql语句
#sql("paginate")
select a.* from blog a where 1=1
#if(sk.notNull(blog))
#if(sk.notBlank(blog.title))
and a.title = #para(blog.title)
#end
#end
order by a.id desc
#end
#end以下是doubleName.sql 文件里面的内容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16### 数据库2的sql
### 名称空间
#namespace("dnSpace")
### sql语句
#sql("paginate")
select a.* from double_name a where 1=1
#if(sk.notNull(doubleName))
#if(sk.notBlank(doubleName.name))
and a.name like concat('%',#para(doubleName.name),'%')
#end
#end
order by a.id desc
#end
#end修改对应的service,换成sql文件的方式,实现sql与代码分离
以下是BlogService的分页查询的方法
1
2
3
4
5
6
7
8public Page<Blog> paginate(int pageNumber, int pageSize) {
Blog blog = new Blog();
blog.setTitle("test 2");
Kv cond = Kv.by("blog", blog);
SqlPara sqlPara = Db.getSqlPara("blogSpace.paginate", cond);
return dao.paginate(pageNumber,pageSize,sqlPara);
//return dao.paginate(pageNumber, pageSize, "select *", "from blog order by id asc");
}以下是DoubleNameService的分页查询方法
1
2
3
4
5
6
7
8public Page<DoubleName> paginate(int pageNumber, int pageSize) {
DoubleName doubleName = new DoubleName();
doubleName.setName("a");
Kv cond = Kv.by("doubleName", doubleName);
SqlPara sqlPara = Db.use("mysql2").getSqlPara("dnSpace.paginate", cond);
return dao.paginate(pageNumber,pageSize,sqlPara);
//return dao.paginate(pageNumber, pageSize, "select *", "from double_name order by id asc");
}运行项目
结束
以上内容,我是分成两个项目进行的,第一个项目连接多数据库,第二个项目在第一个项目的基础上实现sql与代码分离。以上代码经过测试,基本上不会出现问题。