关于jfinal模型的建议

model这块目前是充血模型,里面的内容可以分为几个部分

  1. map对象的提升方法。

  2. model自己属性的实例方法:比如set、keep、put、remove等。

  3. model取数据库配置的方法:getTable,config等。

  4. model数据库操作相关的:crud*(base+cache+sqlpara)

  5. 每个对象该有的:toString、toJson、equals、hashcode等

这些部分的设计中关于数据库操作的部分,我认为设计成静态方法会比较好,毕竟一个model从业务上来说一般只对应一套数据库的配置,而数据库操作相关的方法除了需要数据库配置信息外,并需要其它实例变量。

这么做的好处就是把与对象实例无关的数据库操作作为静态方法,不用在service、或者controller中实例化dao对象,有效的减少多余的实例化对象,进而降低运行时的内存需求。

PS:club项目中,每个service会去实例化自己需要的dao,这个实例化是通过new来做的,这样就会存在多个service中,需要同一个dao,这个dao在系统中就会存在多份,但本身dao就是纯上下文无关的方法操作,多份是没有意义的。所以我现在还是在model里面定义dao对象,然后service里面直接用。



评论区

lyh061619

2018-01-25 12:57

首先,感谢你的反馈,其次关于这个话题怎么说着呢,我就简单分析下:
1、为什么要实例化是为了确保线程安全,java是本身就一门多线程语言。
2、如果只考虑单数据库配置这块就有些片面了,因为现实项目中有一些项目是多数据源的,且也可能是不同库配置,所以在构建一个框架时,这些基本情景是必须要周全考虑的。
3、再说用new创建实例关于性能问题其实可以基本忽略不计,这的话题印象曾经在osc上看到其他的兄弟讨论过,波总也亲自在上解答过,蛮久的了你去你翻翻看。
4、club他实例的dao你追踪到底层你就会看到其实他是个静态实例对象,关于静态变量在初始实例么后,他从系统生命周期到结束在内存中始终保存一份。
5、为什么在每个service上都会实例自己需要的dao这么做的目的是便于代码重构,提供依据,家都知道当大型项目中随着时间、需要、人员更变,项目中的代码、功能模块变得异常的庞大时你就会发现,设计之初不做一些习惯上的改变,当后期代码进行重构是件非常痛苦的事情。

JFinal

2018-01-25 15:38

多数源的需求挺多的,所以不同的 model 对应不同的配置,做成 static 是肯定不行的,static 更适合于工具类方法,作为 java 不支持函数式编程的一个补充

dao 这个对象,每一个 service 单独持有一个对象,并不会造成多少浪费,因为 service 也是建议搞成共享的,这样 service 对象在项目中的个数也是极少的

在 jfinal club 中,dao 这个对象没有在 model 中搞成 pubic static 的,是为了防止开发者 Xxx.dao.find(...) 这样的代码满天飞,而数据库操作是要严格写在 service 层中的

JFinal

2018-01-25 15:40

jfinal 并不提倡充血模式, model 仅仅为作承载数来用,dao 仅用于查询数据库,而所有业务全部放在 service 层,一定要养成好习惯

jfinal 的业务层并不要求有接口、也不要求有抽象类,所以创建业务层是很变便捷的事情,当然,在确实需要抽象,或者要开放 service 层给外界时,可以为业务层添加抽象类或者接口

我要做菜鸟

2018-01-25 18:12

@lyh061619 1. 不实例化只要没有使用非实例化变量,就不会存在线程安全问题。
2. 没有说不存在多数据源的情况,而是说一个model一般不会对应多个数据源。
3. 不是说new创建实例的性能问题,而是说在减少实例化对象的问题。
4. 随便找了UserShareService的代码,private final Share dao = new Share().dao(); 这明明是在new对象,一个service new一个dao对象,而不是你所说的静态变量。
5. 你这个就有点太虚了,我提的是不要每个service都单独在new,而是把new放到model里面,并静态化,在service里面一样可以声明不同的dao变量,但最后指向的是静态化的dao对象,也就是你4中想的那样。当然,我觉得service其实也没必要搞成实例化的,原因是其并没有使用全局变量啊~

我要做菜鸟

2018-01-25 18:18

@JFinal 1. model中数据库配置是通过config来找的,如果变成静态的,可以提供带configname的重载方法来实现。
2. 我考虑的是一个model一般只有一个数据源,不是整个项目中多数据源的问题。
3. 我明白不在model中public static dao的设计,但我不是要让dao这个对象变成static,而是让相关的查询方法,比如findById这种。
4. service其实也可以纯静态化啊~毕竟没有全局状态变量。。。
5. 同意非充血,不要接口、抽象类、model只放数据、业务放service等观点。

我要做菜鸟

2018-01-25 18:26

@JFinal 再补充下,静态化的前提是没有aop。在需要AOP的情况下,确实还是得实例化。但club中的service、dao貌似也没有AOP吧?可能是club的版本太老了。。。

JFinal

2018-01-25 18:51

@我要做菜鸟 贴子的内容比较多,而我时间很有限,每个贴子通常也就一二十秒的阅读时间,所以其实我不太理解你全部的建议,先只是凭那一二十秒获取的信息量凭直觉回复你

非常希望你能给出具体的建议用法的例子,代码是最好的,信息量足,阅读速度快

lyh061619

2018-01-25 19:27

@我要做菜鸟
1、建议你在提建议或反馈问题这点上,一定要给被建议人、问题回答人一看就明白你想表达的意思,不然就现在你所说的情况,一直在靠猜去解答你的问题或理解你的建议,是会有不同的见解与出入。
2、关于第5点你说这个太虚了是随着项目的演变也算是业界标准了,单靠我这里就一两句话说不出其中的奥妙的,因为涉及到的东西太广泛了,再进一步去拓展解析,呆会就觉得说得更虚了,因为每个人的认知理接触的面也不同,不太好去把握这个面,只能在实践中才能体会。

我要做菜鸟

2018-01-30 11:17

@lyh061619 时间匆忙就写得不是太明白,但我觉得提问的内容还不至于那么不清楚,“一个model从业务上来说一般只对应一套数据库的配置”,注意下“一个model”,应该就不会理解成多数据源配置。我觉得很多时候这种问题的产生是因为答题者会不自觉有一种“居高”的思想在里面,不是为了说你,也不是为了吵架,如果你觉得我说的不对,或者太过了,我先向你道歉,毕竟我真不是来吵架的。
关于5,我是觉得你又开始提一些理念,理念有几年经验都会或多或少了解一些,而我的问题、我的回复你也没有仔细读,直接就上理念,所以说你提的虚,没有解决问题。你最开始的回复提到每个service都实例化dao对代码重构有好处,我的回复是在service中不需要每次都实例化dao,把dao的实例化工作放到model中,在service中添加dao的引用。跟每个service实例化dao的区别就是引用变少了而已。像波总回复的内容“dao 这个对象,每一个 service 单独持有一个对象,并不会造成多少浪费,因为 service 也是建议搞成共享的,这样 service 对象在项目中的个数也是极少的”,虽然我觉得能提高一点算点,不太赞同波总的观点。

最后,我觉得每个回答者都应该尽量努力的去理解提问者的问题,努力去回答最好。如果回答不够清楚,只能扯到编程理念或者类似于php是最好的语言这种问题上,要么真能把编程理念讲清楚,要么就不要回答误导新人。

最后的最后,还是感谢你的热心,我也来句虚的,开源的路不容易,感谢有你这样的热心者。

我要做菜鸟

2018-01-30 11:28

@JFinal
model如下:
public class Project extends BaseProject {
public static final Project dao = new Project();
}
service如下:
public class UserProjectService {
private static final Project dao = Project.dao;
public static List findAll(int accountId) {
return dao.find("select * from project where accountId=? order by createAt desc", accountId);
}
}
上述把dao实例化放到了model中,把service的查询方法变成静态化,减少了controller层或者其他service关于UserProjectService的对象引用。

model中关于静态化的部分也类似于上述中findAll方法,把类似的数据库查询方法变成静态方法。

==================================================

不过我也基本想明白了,静态化的主要问题其实是AOP这类的代理没法做。一旦静态化了,后期想再duang一下都做不到了。也算是一个提前设计吧。不过是否可以考虑在model中增加这类的静态化方法,对不需要AOP的场景(大部分)可以更好地使用。

lyh061619

2018-01-30 18:29

@我要做菜鸟
1、其实如果你想这么去做是完全可以的,只需在代码生成器,设置下:gen.setGenerateDaoInModel(true),即可得到你想要结果。
2、至于为什么后来官方的club不推荐这么做的目的,就是防止如:Project.dao.findById()这类不好的使用习惯漫天飞,所引发问题的原因就是之前提到有"争议"的那个第5点问题信息量有关,在这不做解释了。

纵横

2018-06-13 10:35

jfinal模型多条件查询,为什么不在model定义实现???https://my.oschina.net/myaniu/blog/137065

JFinal

2018-06-13 10:42

@纵横 sql 管理功能使用的是模板引擎,比在 Java 代码中拼接 sql 要简单多了,而且有利于维护:
http://www.jfinal.com/doc/5-13

sql 模板的核心设计理念是,尽可能少去打扰 sql,让 sql 尽可能保持原汁原味,注意看 #sql #para 这两个指令的用法就知道了

热门反馈

扫码入社