前言
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)中配置数据库地址和账号密码
# config # 数据库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的数据源
/*** * 得到数据库2的数据源 * @return */ public static DruidPlugin createDruidPlugin2(){ loadConfig(); return new DruidPlugin(p.get("jdbcUrl2"), p.get("user2"), p.get("password2")); }
因为已经有获取数据库1的数据源方法,所以无需再建立一个函数来获取数据库1的数据源
-
修改_JFinalDemoGenerator的getDataSource,生成对应的实体类,生成之前先切换数据库
```java
public 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的映射 */ 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里面的方法内容
/** * 配置插件 */ 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方法,具体请看代码演示:
public 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模板
// 在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 文件里面的内容
### 名称空间 #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 文件里面的内容
### 数据库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的分页查询的方法
public 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的分页查询方法
public 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与代码分离。以上代码经过测试,基本上不会出现问题。