文档章节

视觉角度: jfinal的Model与Beetlsql比较

渔泯小镇
 渔泯小镇
发布于 2017/04/18 19:18
字数 3785
阅读 4918
收藏 122

JFinal 是目前在 git.oschina.net java中关注最多的项目.

亲自用JFinal开发过有上百张表的项目.项目完结后总要做个总结

这篇文章是介绍项目中开发的一些经历.

  1. 会首先列出JFinal的Model开发 (只是Model的使用)
  2. 使用Beetlsql替换JFinal的Model (给出一种较爽编码方式)
  3. 对比两个在写多条件查询sql时, (就是需要条件判断, 为null的不参与查询)

1.JFinal的Model开发

JFinal的ORM下面称JFinal的Model

这是Model的新增 修改 删除

jfinal 实体类1

public class Elephant extends Model<Elephant> {
    public static final Elephant Dao = new Elephant();
    public List<Integer> findIds() {
        return Db.query("select id from tb_bird");
    }
}

 

jfinal 测试用例1

@Log4j
public class ElephantTest {
    @Test
    public void testChainSave() {
        // 无需要创建字段
        new Elephant().set("age", 17).set("name", "jfinal").set("desc", "mvc + orm").save();
    }

    @Test
    public void testUpdate() {
        Elephant elephant = Elephant.Dao.findById(1);
        elephant.set("age", 18).update();
    }

    @Test
    public void testDelete() {
        Elephant elephant = Elephant.Dao.findById(1);
        elephant.delete();
    }
}

 

    说实话,刚开始看示例的时候感觉很不错. 毕竟不需要自己定义任何字段就能直接将数据保存到表中.

    刚开始也使用这种方式进行开发, 但是如果有多个地方使用了这样的代码, 并且产品开发过程中需要更改某几个字段,那么小噩梦就开始了. 毕竟没有工具可以进行这种检测. 表字段名直接写成字符串也都是合法的.那么唯一可以做的就只能搜索整个项目使用到这个类的地方, 然后逐个检查而且需要看得很细. 因为这是人工的检查,所以工具并不能帮上你很大忙.

还有一点是采用这种方式开发就是你必须记住每个表的每个字段, 并且不能出错(需要手动在代码中敲击数据库表字段的名字).

如果是几张表并且字段少的情况下这样玩代码也没有什么. 如果是百张表的项目你会工作得很愉快.

所以就约定了实体类代码必须提供getter,setter. 这样做工具可以提供错误检测

于是项目中的实体类就变成了下面的方式

jfinal 实体类2 getter, setter

public class Elephant extends Model<Elephant> {
    public static final Elephant Dao = new Elephant();

    public int getId() {
        return this.getInt("id");
    }

    public Elephant setId(int id) {
        this.set("id", id);
        return this;
    }

    public int getAge() {
        return this.getInt("age");
    }

    public Elephant setAge(int age) {
        this.set("age", age);
        return this;
    }

    public String getName() {
        return this.getStr("name");
    }

    public Elephant setName(String name) {
        this.set("name", name);
        return this;
    }

    public String getDesc() {
        return this.getStr("desc");
    }

    public Elephant setDesc(String desc) {
        this.set("desc", desc);
        return this;
    }

    public List<Integer> findIds() {
        return Db.query("select id from tb_bird");
    }
}

实体类代码提供了getter,setter (为了继续保持链式风格在setter都返回了自身). 这样做工具可以提供错误检测, 看起来这样很不错了.

jfinal 测试用例2

这是添加getter,setter后的测试用例

@Log4j
public class ElephantChainTest {
    @Test
    public void testChainSave() {
        new Elephant().setAge(17).setName("jfinal").setDesc("mvc + orm").save();
    }

    @Test
    public void testUpdate() {
        Elephant elephant = Elephant.Dao.findById(1);
        elephant.setAge(18).update();
    }

    @Test
    public void testDelete() {
        Elephant elephant = Elephant.Dao.findById(1);
        elephant.delete();
    }
}

 

    好了, Model实体类都拥有了getter, setter方法了. 即便表业务需要改一个字段的名字也没什么大碍, 我就改这个实体类对应的方法名就行. 工具会给我们报错在代码的哪一行使用到了这个属性(字段). 并且也不需要使用到这个实体类的地方都手动敲击这个字段名了. 很不错. 方便了很多!

    但是我要告诉你们的是这些getter, setter代码都是人工手动敲上去的. 当初是想用JFinal的Model节省时间的,毫无疑问的是这样做并没有节省我的时间,而且还浪费了很多时间.

这里只是其中一个表对应的实体类(字段也很少, 因为是举例这里只用了4个字段). 如果百个实体类而有的实体类有8个,15个甚至更多属性(是的,你没看错, 你会越来越愉快).

    上面说到为什么这些代码是人工手动敲上去的. 工具不是可以生成getter,setter吗. 我想说的的确是可以生成, 但是工具生成这些代码是有前提条件的. 这些条件就是你必须显示的拥有类的成员属性.

所以很遗憾, 你享受不到工具带来的便捷

    好了, 代码约定Model实体类都必须提供getter, setter方法. 那么代码总要加上点注释吧. 于是代码就变成如下:

public class Elephant extends Model<Elephant> {
    public static final Elephant Dao = new Elephant();

    /**
     * @return 年龄
     */
    public int getAge() {
        return this.getInt("age");
    }

    /**
     * @param age 年龄
     * @return this
     */
    public Elephant setAge(int age) {
        this.set("age", age);
        return this;
    }

    /**
     * @return 名字
     */
    public String getName() {
        return this.getStr("name");
    }

    /**
     * @param name 名字
     * @return this
     */
    public Elephant setName(String name) {
        this.set("name", name);
        return this;
    }

    /**
     * @return 描述
     */
    public String getDesc() {
        return this.getStr("desc");
    }

    /**
     * @param desc 描述
     * @return this
     */
    public Elephant setDesc(String desc) {
        this.set("desc", desc);
        return this;
    }

    public List<Integer> findIds() {
        return Db.query("select id from tb_bird");
    }
}

 

    这样从一个最初只有1行代码的实体类, 最后变成了这样. 如果你在看这篇文字, 感觉变成了这样并有没什么. 但是你想知道变成拥有getter, setter加上注释花了多少时间吗? (请读者自行建立一个拥有8个字段的实体玩下).

我在想我为什么要花如此多的时间创建在model上 (我这样安慰我自己的, 这也属于有氧运动吧).

JAVA 极速WEB+ORM框架 JFinal

JFinal 是基于 Java 语言的极速 WEB + ORM 框架,其核心设计目标是开发迅速、代码量少、学习简单、功能强大、轻量级、易扩展、Restful。在拥有Java语言所有优势的同时再拥有ruby、python等动态语言的开发效率!为您节约更多时间,去陪恋人、家人和朋友 ;)

    块引用中的开发迅速与代码量少.没有明确的说是JFianl的代码量少还是使用JFinal开发项目的代码量少. 至少我认为项目中的Model如果显示提供getter,setter代码量就已经巨大且编码效率极慢(仅是JFinal的ORM给我的感觉. 也并不完全是感觉, 毕竟上面的代码示例包含了我想说的话了).

显示提供也不是,不显示提供也不是. 两难.

2.使用Beetlsql替换JFinal的Model

beetlsql + java8 + lombok 结合使用,达到代码最简洁效果, 并且可阅读性更强 (下面称为第二种编码方式)

(极简版)实体类1

@Data
@FieldDefaults(level = AccessLevel.PRIVATE)  // 属性默认都是private
@lombok.experimental.Accessors(chain = true) // 链式编程
@Table(name = "tb_bird")                     // 实体类与表映射
public class Bee implements $Sql { // 实现$Sql接口, 可以在对象上直接使用 save, update, delete 方法 (不是必须的)
    int id;
    /** 年龄 */
    Integer age;
    /** 名字 */
    String name;
    /** 描述 */
    String desc;
}

lombok.@Data自动提供getter,setter,toString等方法. 所以并不需要在代码中显示的生成getter,setter方法(方法上都会有注释), 这让实体类更加的干净.

上面的示例中实体类只需要实现接口,而不需要任何继承就能达到想要的效果.(Effective Java 第18条:接口优于抽象类)

测试类

@Log4j
public class BeeChainTest {
    @Test
    public void testChainSave() {
        new Bee().setAge(17).setName("beetl").setDesc("beetlsql + orm").save();
    }

    @Test
    public void testUpdate() {
        Bee bee = Bee.Dao.$.unique(1);
        bee.setAge(18).update();
    }

    @Test
    public void testDelete() {
        Bee bee = Bee.Dao.$.unique(1);
        bee.delete();
    }
}

    可以看出, 就ORM方式而言. 我更倾向于后面这种结合.

  1. 自动拥有getter setter, 在也不需要手工敲击(有氧运动)
  2. 代码更加清晰,简洁, 甚至可以说真正的做到了代码量少. 让你开发更迅速.

    在上面JFinal的Model中和下面一种方式, 如果我们都在两个实体类中在追加1个字段(并加上注释), 第二种方式无疑是最方便的.

    因为JFinal的Model添加一个字段的getter setter并加上注释 需要14行代码, 而第二种方式只需要两行(可以在上面给出的示例中自己数).也就是说实体类每增加一个字段, 你的Model类相比使用第二种方式多出12行代码(7倍代码量, 这还是在你手工敲击getter setter名字完全正确率100%的情况下, getName getNema不出现这种拼写意外).

    所以为了防止这种意外你也许会说我可以在Model里面先定义属性并确定类型, 然后使用工具生成getter setter经过部分改动接着在把这个定义的属性删除掉就行了(这样就不会产生拼写意外, 而且能享受工具生成代码的便捷). 我想说的是你很幽默. 并且我想对你说的是曾经我也这样幽默过.

    说实话假设类有10个字段. 那么一个是140代码量和一个是20行代码量的,你更愿意看见哪一个? 不知道你们是怎么想的,我看140行代码的时候, 我还得在工具里上下翻滚.而第二种方式我一眼就能明白是怎么回事.

如果字段改个名字那么Model需要改动的地方有7处(换句话说就是维护7处). 第二种方式只需要改1处. (这里仅计算实体类里面的改动, 暂不考虑被项目中其他地方引用该实体类的地方)

 

beetlsql的链式编程

有一个坏消息是beetlsql在发布这篇文章的时候还不能支持链式编程

作者( @闲大赋 )在论坛上是这样回复的:

因为setter方法这种写法不是Javabean的标准写法,所以beetl无法认定这是一个属性,因此才会有刚才那种生成的sql语句

beetlsql会在下个版本支持读取field而不是getter,setter,不过需要点时间

当然有坏消息就会有好消息. 细心的朋友会发现将来的版本中作者会提供

 

 

3.对比两个在写多条件查询sql时

    当然,如果仅仅是从上面的Model做对比还是无法吸引你的话,那么这一节中就要拿出Beetlsql锋利的一面了(这里不会列举得很详细,只是简单的几个方法介绍).更具体的得到beetlsql官网上查阅资料.

有多个条件参数(就是需要条件判断, 为null的不参与查询)

下面各举三个方法执行同样的sql查询做比较

  • 查询所有id - findIds
  • 三个条件参数来查询单个对象 - findOne
  • 两个条件参数来查询一个对象列表 - finds

jfinal Model类现在的代码加上这三个查询后的代码

public class Elephant extends Model<Elephant> {
    public static final Elephant Dao = new Elephant();

    /**
     * @return 年龄
     */
    public int getAge() {
        return this.getInt("age");
    }

    /**
     * @param age 年龄
     * @return this
     */
    public Elephant setAge(int age) {
        this.set("age", age);
        return this;
    }

    /**
     * @return 名字
     */
    public String getName() {
        return this.getStr("name");
    }

    /**
     * @param name 名字
     * @return this
     */
    public Elephant setName(String name) {
        this.set("name", name);
        return this;
    }

    /**
     * @return 描述
     */
    public String getDescription() {
        return this.getStr("description");
    }

    /**
     * @param description 描述
     * @return this
     */
    public Elephant setDescription(String description) {
        this.set("description", description);
        return this;
    }

    public List<Integer> findIds() {
        return Db.query("select id from tb_bird");
    }

    public Elephant findOne(int age, String name, String description) {
        StringBuilder sql = new StringBuilder("select * from tb_bird where 1 = 1");
        List<Object> pars = new LinkedList<>();

        if (age != 0) {
            sql.append(" and age = ? ");
            pars.add(age);
        }

        if (name != null) {
            sql.append(" and name = ? ");
            pars.add(name);
        }

        if (description != null) {
            sql.append(" and description = ? ");
            pars.add(description);
        }

        return this.findFirst(sql.toString(), pars.toArray());
    }

    public List<Elephant> finds(int age, String name) {
        StringBuilder sql = new StringBuilder("select * from tb_bird where 1 = 1");
        List<Object> pars = new LinkedList<>();

        if (age != 0) {
            sql.append(" and age = ? ");
            pars.add(age);
        }

        if (name != null) {
            sql.append(" and name = ? ");
            pars.add(name);
        }

        return Db.query(sql.toString(), pars.toArray());
    }
}

 

jfinal Model查询测试用例

@Log4j
public class ElephantFindTest {
    @Before
    public void bf() {
        Config.jfinalInit();
    }

    @Test
    public void findIds() {
        // 查询所有主键
        List<Integer> ids = Elephant.Dao.findIds();
        log.info(ids);
    }

    @Test
    public void findOne() {
        Elephant one = Elephant.Dao.findOne(18, "a", "n");
        log.info(one);
    }

    @Test
    public void finds() {
        List<Elephant> list = Elephant.Dao.finds(18, "b");
        log.info(list);
    }
}

 

 

(极简版) 第二种方式类现在的代码加上这三个查询后的代码

@Data
@FieldDefaults(level = AccessLevel.PRIVATE)  // 属性默认都是private
@lombok.experimental.Accessors(chain = true) // 链式编程
@Table(name = "tb_bird")                     // 实体类与表映射
public class Bee implements $Sql { // 实现$Sql接口, 可以在对象上直接使用 save, update, delete 方法 (不是必须的)
    int id;
    /** 年龄 */
    Integer age;
    /** 名字 */
    String name;
    /** 描述 */
    String description;

    // 自定义sqlDao处理类. (如果没有自定义sql就没必要定义这个接口)
    public interface Dao extends $Mapper<Bee> {
        /** 约定使用$符号表示自己 (这句代码也不是必须的) */
        Dao $ = mapper(Dao.class);

        /**
         * 使用注解忽略默认的内置处理
         * 也可以写成下面的方式, 这里只是示例使用
         * @return 查询表所有主键
         */
        @Ignore
        default List<Integer> findIds() {
            return $().execute(new SQLReady("select id from tb_bird"), Integer.class);
        }

        // 这里无需再写接口实现类, 只需要在bee.md文件写sql
        @SqlStatement(params = "age,name,description")
        Bee findOne(int age, String name, String description);

        // 这里无需再写接口实现类, 只需要在bee.md文件写sql
        @SqlStatement(params = "age,name")
        List<Bee> finds(int age, String name);
    }
}

 

第二种方式查询测试用例

@Log4j
public class BeeFindTest {
    @Before
    public void bf() {
        Config.dbInit();
    }

    @Test
    public void findIds() {
        // 查询所有主键
        List<Integer> ids = Bee.Dao.$.findIds();
        log.info(ids);
    }

    @Test
    public void findOne() {
        Bee one = Bee.Dao.$.findOne(18, "a", "n");
        log.info(one);
    }

    @Test
    public void finds() {
        List<Bee> list = Bee.Dao.$.finds(18, "b");
        log.info(list);
    }
}

    从上面两个示例代码中可以看出优缺点:

试着想一下,假设这类有15个字段并且与数据库交互的方法有10个左右.这里只是这样列举了一个类的三个方法(并且最多的查询条件只有三个,Model需要代码量就太多了点.那么我相信你的项目中有条件参数的并且大于三个的不会没有), 实际项目中表的数量比这个恐怖得多,这个时候就不是假设了,而是玩真的了.

关于Model

    Model把所有与数据库打交道的地方都写在一个类里面. , 你可以想象这个Model的代码有多庞大与臃肿,维护费时

关于beetlsql

    不需要编写数据库打交道的实体类. 只需要定义接口并编写对应 md文件

所有sql语句都存放类对应的md文件中管理 (如果简单的语句可以直接写在接口中, 声明default就可以)

在两个实现同样功能的情况下, 而第二种方式编写代码是极其的简洁, 甚至预览代码都快很多倍.

 

这里在放上第二种方式与md(sql)文件管理的截图

 

最后

上面都是亲自开发在有很多表的项目中的一些总结与讨论.

当然本文并不是说JFinal的Model不好用也不是说jfinal的缺点, 而是找到了一种(这个是仅是自认为)可以替代Model更好的编码方式.

这里是一个 beetlsql demo 大家可以参考.

最后我想说的是,一旦你使用beetlsql并结合上面推荐的方式编码. 你就在也回不去了,因为真的很爽.

曾经使用过 (Hibernate Mybatis) 在使用beetlsql, 你也不会想回到过去

 

 

 

 

© 著作权归作者所有

渔泯小镇

渔泯小镇

粉丝 42
博文 8
码字总数 19203
作品 0
深圳
程序员
私信 提问
加载中

评论(97)

p
prada
当作者发表博文的时候,提到生成几百张远程服务器表实体类非常缓慢时,我曾经感到担忧,但现在刚好有一个项目大概120多张表字段不算少,生成实体类与本地区别并不明显,那么几秒钟的时间。 必须在此发表一下,也给后面看到的读者一个参考吧。
程序猿猴
程序猿猴

引用来自“光束蜗牛”的评论

是旧文吗?自己写model?jfinal不是有提供生成器?一键生成表对应的model,修改字段重新生成即可,至于查询条件有增强model可以继承,修改自动生成配置即可,数据库基本操作完全不需要手工代码。
作者当时用jfinal开发项目的时候应该是2.x的版本,jfinal还没有提供自动生成model的功能。
张家宁
张家宁
虽然博主写这篇文字相对来说比较片面,但是是一篇好文,赞一个!!!
光束蜗牛
光束蜗牛
是旧文吗?自己写model?jfinal不是有提供生成器?一键生成表对应的model,修改字段重新生成即可,至于查询条件有增强model可以继承,修改自动生成配置即可,数据库基本操作完全不需要手工代码。
talent-tan
talent-tan

引用来自“Sohnny”的评论

看了第一个个问题我就不想再往下看了,jfinal 你会用吗?自动生成model的那个工具类你都没用过,在这大放狂言,告诉你的秘密,人家有setter getter 方法,而且自动生成!!

引用来自“渔泯小镇”的评论

很不错, 我又多了一个秘密!

引用来自“JFinal”的评论

通过你的这些回复看得出来博主性格非常好,言辞都非常得体,没有任何过激言论,绝对不是故意抹黑 jfinal 的人。

如果要出 3.0 版本的博文,强烈建议一是用上 jfinal 2.1 就有的 getter、setter,这个下载 jfinal 官方 demo就有相关代码可用,二是用上jfinal 极简设计的 sql 管理功能

我非常有信心,3.0 版对比博文出来之时,就是你全面了解当前 jfinal 极简特性之日。jfinal 的 getter、setter 并没有抛弃原来的 model,而是结合 model 动态后的全新体验,动与静的优势结合

而 jfinal 的 sql 管理功能,仅有三个指令实现 mybatis 的核心功能,而且完全不需要 mabatis 中 xml、mapper、interface、annotation、handler、interceptor 这些概念,每增加一个概念都是要花时间学习的,jfinal 的设计在降低学习成本方面付出的努力是常人难以想象的,例如这两天在开发的 sql 管理分页功能,已推导重来三次,昨天晚上才正式定稿

引用来自“渔泯小镇”的评论

没理由去抹黑任何一个开源作者,也使用jfinal好几年了.
文章描述的也是jfinal的确存在过的, 并不是无中生有.(仅ORM)
没用上代码生成是因为开发环境的原因. (团队用的云端数据库, 这样不必每个人都在本地安装mysql.数据表现一致性,即使回家编码(帮助团队成员调试也只需要在本机做)也可以保持一致性的数据. )

下周 3.1出来后我尽量客观的对比与分析,期望在3.1PDF中有sql关于动态条件的demo和连表查询相关的.
3.1 我会用jfinal推荐的编码方式代码生成的来描述.
喜闻乐见这样的情况!博主加油!
渔泯小镇
渔泯小镇 博主

引用来自“Sohnny”的评论

看了第一个个问题我就不想再往下看了,jfinal 你会用吗?自动生成model的那个工具类你都没用过,在这大放狂言,告诉你的秘密,人家有setter getter 方法,而且自动生成!!

引用来自“渔泯小镇”的评论

很不错, 我又多了一个秘密!

引用来自“JFinal”的评论

通过你的这些回复看得出来博主性格非常好,言辞都非常得体,没有任何过激言论,绝对不是故意抹黑 jfinal 的人。

如果要出 3.0 版本的博文,强烈建议一是用上 jfinal 2.1 就有的 getter、setter,这个下载 jfinal 官方 demo就有相关代码可用,二是用上jfinal 极简设计的 sql 管理功能

我非常有信心,3.0 版对比博文出来之时,就是你全面了解当前 jfinal 极简特性之日。jfinal 的 getter、setter 并没有抛弃原来的 model,而是结合 model 动态后的全新体验,动与静的优势结合

而 jfinal 的 sql 管理功能,仅有三个指令实现 mybatis 的核心功能,而且完全不需要 mabatis 中 xml、mapper、interface、annotation、handler、interceptor 这些概念,每增加一个概念都是要花时间学习的,jfinal 的设计在降低学习成本方面付出的努力是常人难以想象的,例如这两天在开发的 sql 管理分页功能,已推导重来三次,昨天晚上才正式定稿
没理由去抹黑任何一个开源作者,也使用jfinal好几年了.
文章描述的也是jfinal的确存在过的, 并不是无中生有.(仅ORM)
没用上代码生成是因为开发环境的原因. (团队用的云端数据库, 这样不必每个人都在本地安装mysql.数据表现一致性,即使回家编码(帮助团队成员调试也只需要在本机做)也可以保持一致性的数据. )

下周 3.1出来后我尽量客观的对比与分析,期望在3.1PDF中有sql关于动态条件的demo和连表查询相关的.
3.1 我会用jfinal推荐的编码方式代码生成的来描述.
JFinal
JFinal

引用来自“Sohnny”的评论

看了第一个个问题我就不想再往下看了,jfinal 你会用吗?自动生成model的那个工具类你都没用过,在这大放狂言,告诉你的秘密,人家有setter getter 方法,而且自动生成!!

引用来自“渔泯小镇”的评论

很不错, 我又多了一个秘密!
通过你的这些回复看得出来博主性格非常好,言辞都非常得体,没有任何过激言论,绝对不是故意抹黑 jfinal 的人。

如果要出 3.0 版本的博文,强烈建议一是用上 jfinal 2.1 就有的 getter、setter,这个下载 jfinal 官方 demo就有相关代码可用,二是用上jfinal 极简设计的 sql 管理功能

我非常有信心,3.0 版对比博文出来之时,就是你全面了解当前 jfinal 极简特性之日。jfinal 的 getter、setter 并没有抛弃原来的 model,而是结合 model 动态后的全新体验,动与静的优势结合

而 jfinal 的 sql 管理功能,仅有三个指令实现 mybatis 的核心功能,而且完全不需要 mabatis 中 xml、mapper、interface、annotation、handler、interceptor 这些概念,每增加一个概念都是要花时间学习的,jfinal 的设计在降低学习成本方面付出的努力是常人难以想象的,例如这两天在开发的 sql 管理分页功能,已推导重来三次,昨天晚上才正式定稿
渔泯小镇
渔泯小镇 博主

引用来自“Sohnny”的评论

看了第一个个问题我就不想再往下看了,jfinal 你会用吗?自动生成model的那个工具类你都没用过,在这大放狂言,告诉你的秘密,人家有setter getter 方法,而且自动生成!!
很不错, 我又多了一个秘密!
Sohnny
Sohnny
看了第一个个问题我就不想再往下看了,jfinal 你会用吗?自动生成model的那个工具类你都没用过,在这大放狂言,告诉你的秘密,人家有setter getter 方法,而且自动生成!!
JFinal
JFinal

引用来自“蓝水晶飞机”的评论

支持动态语句以及planobject都是很有必要的,业务层充满了拼接SQL的逻辑是十分的难以维护(即使你有写原生语句的注释)但依然难开发难调试,开发一些比较复杂的系统简直就是噩梦啊。
转战Mybatis和自己写的mapperXML生成器方法是实现注解和XML元素类API,在此基础上实现编程输出XML
因此,jfinal 3.0 添加了极简的 sql 管理模块:https://www.oschina.net/news/81225/jfinal-3-0-released
BeetlSQL,简单和强大数据库访问工具(更新)

beetlsql 特点 BeetSql是一个全功能DAO工具, 同时具有Hibernate 优点 & Mybatis优点功能,适用于承认以SQL为中心,同时又需求工具能自动能生成大量常用的SQL的应用。 无需注解,自动生成大量...

闲大赋
2015/08/17
11.6K
61
SpringBlade 1.0 发布 , Java 快速开发平台

SpringBlade 1.0 正式版发布,正式版更新如下: 增加table风格的表单组件 增加下拉查询树组件 增加shiro基于redis的缓存实现 增加redis操作工具(单机、集群可自由切换) 增加配置文件加密策略...

smallchill
2017/01/23
4.6K
11
BeetlSql 2.2.1 发布,mybatis 功能 beetl 实现

BeetlSQL 2.2.1发布了,BeetSQL 是一个全功能DAO工具, 同时具有Hibernate 优点 & Mybatis优点功能,适用于承认以SQL为中心,同时又需求工具能自动能生成大量常用的SQL的应用。 #90 在注解控...

闲大赋
2016/03/29
2.5K
15
建议以依赖的方式,而非copy的方式使用jfinal代码

Springblade 的技术组合是 spring+springmvc+beetl+beetlsql+shiro,刚看了一下源码,其中大量直接 copy 的 jfinal 源码,例如 render 模块、json 模块相当于整模块原封不动地 copy 使用。项...

JFinal
2016/09/05
1K
15
beetlsql 1.0.0 正式发布,mybatis 的 beetl 实现

beetlsql 1.0.0 正式发布,此版本更新内容如下: 新增 1 mysql 数据库支持 运行运行sql 3 spring,jfinal 集成 4 新增use 和 join 函数,use 可以重用sql片段和,join函数用于sql的 in语句 ...

闲大赋
2015/09/14
4.1K
37

没有更多内容

加载失败,请刷新页面

加载更多

最简单的获取相机拍照的图片

  import android.content.Intent;import android.graphics.Bitmap;import android.os.Bundle;import android.os.Environment;import android.provider.MediaStore;import andr......

MrLins
今天
4
0
说好不哭!数据可视化深度干货,前端开发下一个涨薪点在这里~

随着互联网在各行各业的影响不断深入,数据规模越来越大,各企业也越来越重视数据的价值。作为一家专业的数据智能公司,个推从消息推送服务起家,经过多年的持续耕耘,积累沉淀了海量数据,在...

个推
今天
8
0
第三方支付-返回与回调注意事项

不管是支付宝,微信,还是其它第三方支付,第四方支付,支付机构服务商只要涉及到钱的交易都要进行如下校验,全部成功了才视为成功订单 1.http请求是否成功 2.校验商户号 3.校验订单号及状态...

Shingfi
今天
4
0
简述Java内存分配和回收策略以及Minor GC 和 Major GC(Full GC)

内存分配: 1. 栈区:栈可分为Java虚拟机和本地方法栈 2. 堆区:堆被所有线程共享,在虚拟机启动时创建,是唯一的目的是存放对象实例,是gc的主要区域。通常可分为两个区块年轻代和年老代。更...

DustinChan
今天
6
0
Excel插入批注:可在批注插入文字、形状、图片

1.批注一直显示:审阅选项卡-------->勾选显示批注选项: 2.插入批注快捷键:Shift+F2 组合键 3.在批注中插入图片:鼠标右键点击批注框的小圆点【重点不可以在批注文本框内点击】----->调出批...

东方墨天
今天
6
1

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部