jfinal_多数据源连接

前言

​ JFinal,开发程序非常方便,尤其是控制台显示每次请求的具体信息,易读而且可以点击类名到对应的类中去修改。spring的日志真的密密麻麻,看的眼花。

​ 此文演示如何用JFinal连接多个数据库,我尝试过连着mysql和oracle,没有问题。连接多个数据库,可以兼容以前的代码,以前连接的数据库当做主数据库,后面添加的数据库当做从数据库。

​ 扩展:如何让JFinal使用sql文件,实现代码与sql分离。(多数据源演示)

配置JFinal并运行起来

​ 因为我本地没有JFinal项目,所以首先下载JFinal源码。下载完之后,根据

启动说明,把该配好的配好,试着运行一下。

​ 没有任何问题后,进行下一步操作。

安装数据库jar包

​ 默认情况,JFinal的demo已经包含有mysql驱动jar,所以无需安装。

​ 如果需要连接oracle,则需要在pom文件中引入jar包。

​ 因为此文是连接两个mysql,jar包根据实际需求引入,不再截图演示。

​ 然后准备两个数据库即可。

配置JFinal连接数据库

  1. 首先在配置文件(demo-config-dev.txt)中配置数据库地址和账号密码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    # 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
  2. 先在配置类(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的数据源

  1. 修改_JFinalDemoGenerator的getDataSource,生成对应的实体类,生成之前先切换数据库

    1
    2
    3
    4
    5
    6
    7
    8
    public static DataSource getDataSource() {
    // 数据库1的数据源
    //DruidPlugin druidPlugin = DemoConfig.createDruidPlugin();
    // 数据库2的数据源
    DruidPlugin druidPlugin = DemoConfig.createDruidPlugin2();
    druidPlugin.start();
    return druidPlugin.getDataSource();
    }

​ 提醒:如果你的数据库不是mysql,请修改main方法里面的设置数据库方言

​ 接着运行main方法就可以自动生成数据库2的实体类

  1. 创建数据库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);
    }
    }
  1. 在配置类(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. 添加数据库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
      23
      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与代码分离

  1. 首先看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);
    }
    }
    }

    }
  2. 在resource目录下新建文件夹和文件,具体如下:

  3. 分别写对应的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
  4. 修改对应的service,换成sql文件的方式,实现sql与代码分离

    以下是BlogService的分页查询的方法

    1
    2
    3
    4
    5
    6
    7
    8
    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的分页查询方法

    1
    2
    3
    4
    5
    6
    7
    8
    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");
    }
  5. 运行项目

结束

​ 以上内容,我是分成两个项目进行的,第一个项目连接多数据库,第二个项目在第一个项目的基础上实现sql与代码分离。以上代码经过测试,基本上不会出现问题。

评论