JFinal学习

您所在的位置:网站首页 jfinal项目 JFinal学习

JFinal学习

2023-09-14 00:55| 来源: 网络整理| 查看: 265

在项目中,我们会需要使用到数据库,那么JFinal中是如何使用数据库的呢?

要使用数据库,我们首先需要建立数据库连接,JFinal给我们提供了两种现成的JDBC连接池,分别是C3p0 和 Druid,对应的相应的类是 C3p0Plugin 和 DruidPlugin,这两个类都实现了IDataSourceProvider接口,接口中定义了 getDataSource() 获取数据源的方法。

那么JFinal是如何通过连接池类,来操作数据库的呢?

这里,就要引入插件的概念–Plugin。

在JFinal中,插件会继承IPlugin接口,其中有 start() 和 stop() 两个方法。C3p0Plugin 和 DruidPlugin 也都实现了这个接口。具体如下:

这里写图片描述

其中,ActiveRecordPlugin就是进行数据库映射、配置的类。

下面,是操作数据库的流程,这里以保存用户为例:

1.首先建立数据库

CREATE DATABASE IF NOT EXISTS `db_jfinal` USE `db_jfinal`; DROP TABLE IF EXISTS `t_user`; CREATE TABLE `t_user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(100) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

2.创建Model

public class User extends Model{ public static final User dao = new User(); }

3.在配置类中添加代码:

@Override public void configPlugin(Plugins me) { C3p0Plugin cp = new C3p0Plugin("jdbc:mysql://localhost:3306/db_jfinal", "root", "admin"); me.add(cp); ActiveRecordPlugin arp = new ActiveRecordPlugin(cp); me.add(arp); arp.addMapping("t_user", User.class); }

4.在Controller中执行保存用户操作

new User().set("name", "zorro").save();

在Jfinal中操作数据库就如上面这么简单,接下来,我们来看下具体是如何实现数据库保存的:

1.首先,在过滤器 JFinalFilter中的init方法中,静态变量jfinal会执行init方法,在这个方法中,会将配置类中的设置的插件取出,并启动。

com.jfinal.core.Config类中获取并启动插件:

static void configJFinal(JFinalConfig jfinalConfig) { jfinalConfig.configConstant(constants); initLogFactory(); jfinalConfig.configRoute(routes); jfinalConfig.configPlugin(plugins); startPlugins(); // very important!!! jfinalConfig.configInterceptor(interceptors); jfinalConfig.configHandler(handlers); }

2.由于在配置类中配置了两个插件,一个是C3p0Plugin,一个是ActiveRecordPlugin。 我们先看下C3p0Plugin的start方法:

public boolean start() { if (isStarted) return true; dataSource = new ComboPooledDataSource(); dataSource.setJdbcUrl(jdbcUrl); dataSource.setUser(user); dataSource.setPassword(password); try {dataSource.setDriverClass(driverClass);} catch (PropertyVetoException e) {dataSource = null; System.err.println("C3p0Plugin start error"); throw new RuntimeException(e);} dataSource.setMaxPoolSize(maxPoolSize); dataSource.setMinPoolSize(minPoolSize); dataSource.setInitialPoolSize(initialPoolSize); dataSource.setMaxIdleTime(maxIdleTime); dataSource.setAcquireIncrement(acquireIncrement); isStarted = true; return true; }

看代码知道,C3p0的启动,主要是实例化了一个数据源 dataSource,并给数据源设置了一些属性。

3.在看ActiveRecordPlugin,由于我们在配置类中实例化ActiveRecordPlugin的时候,将C3p0Plugin的实例传给了它,相当于ActiveRecordPlugin持有了数据源。

4.ActiveRecordPlugin的start() 方法如下:

public boolean start() { if (isStarted) { return true; } if (configName == null) { configName = DbKit.MAIN_CONFIG_NAME; } if (dataSource == null && dataSourceProvider != null) { dataSource = dataSourceProvider.getDataSource(); } if (dataSource == null) { throw new RuntimeException("ActiveRecord start error: ActiveRecordPlugin need DataSource or DataSourceProvider"); } if (config == null) { config = new Config(configName, dataSource); } if (dialect != null) { config.dialect = dialect; } if (showSql != null) { config.showSql = showSql; } if (devMode != null) { config.devMode = devMode; } if (transactionLevel != null) { config.transactionLevel = transactionLevel; } if (containerFactory != null) { config.containerFactory = containerFactory; } if (cache != null) { config.cache = cache; } new TableBuilder().build(tableList, config); DbKit.addConfig(config); Db.init(); isStarted = true; return true; }

这里会实例化一个com.jfinal.plugin.activerecord.Config类,该类将持有数据源dataSource,之后DbKit.addConfig(config),会将config实例赋值给DbKit类下的静态属性,这使用了单例模式,以后再要使用数据源来获取连接,就不需要再实例化了,只要DbKit.getConfig() 就可以。

再看上面的

new TableBuilder().build(tableList, config);

这个操作是实现数据库的映射,通过查询各个表,将表中各字段记录到Table类中。并将table 保存到TableMapping中。

void build(List tableList, Config config) { if (tableList.size() == 0) { return ; } Table temp = null; Connection conn = null; try { conn = config.dataSource.getConnection(); TableMapping tableMapping = TableMapping.me(); for (Table table : tableList) { temp = table; doBuild(table, conn, config); tableMapping.putTable(table); DbKit.addModelToConfigMapping(table.getModelClass(), config); } } catch (Exception e) { if (temp != null) { System.err.println("Can not create Table object, maybe the table " + temp.getName() + " is not exists."); } throw new ActiveRecordException(e); } finally { config.close(conn); } }

5.最后是保存数据。 实体类User 继承了com.jfinal.plugin.activerecord.Model类,这个Model类中,就包含的对数据库操作方法。

Model中有属性Map

public boolean save() { Config config = getConfig(); Table table = getTable(); StringBuilder sql = new StringBuilder(); List paras = new ArrayList(); config.dialect.forModelSave(table, attrs, sql, paras); // if (paras.size() == 0) return false; // The sql "insert into tableName() values()" works fine, so delete this line // -------- Connection conn = null; PreparedStatement pst = null; int result = 0; try { conn = config.getConnection(); if (config.dialect.isOracle()) pst = conn.prepareStatement(sql.toString(), table.getPrimaryKey()); else pst = conn.prepareStatement(sql.toString(), Statement.RETURN_GENERATED_KEYS); config.dialect.fillStatement(pst, paras); result = pst.executeUpdate(); getGeneratedKey(pst, table, config); getModifyFlag().clear(); return result >= 1; } catch (Exception e) { throw new ActiveRecordException(e); } finally { config.close(pst, conn); } }

仔细看下,其实就是普通的JDBC操作。至此,整个操作数据库的流程就完成了。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3