2016-10-31 11:12

提示jfinal-api-scaffold-master.wmquestionnaire 这张表不存在,检查一下,这里是关键提示部分:Table 'jfinal-api-scaffold-master.wmquestionnaire' doesn't exist

2016-10-30 17:59

确实有点问题, jfinal 2.3 已改进了这里,多多关注社区动态,感谢支持

2016-10-30 17:58

在有 static Xxx dao 对象的时候,如果你只使用 find 系列的方法也是线程安全的,因为 find 系列的方法中所使用的对象不涉及共享变量,全都是方法内部 new 出来的对象,所以是安全的

而 dao 中的 save、put、update 等方法,操作的数据是该 dao 对象内部所持有的 Map attrs 这个属性,这个属性是对所有线程可见的,在操作它的时候就不是线程安全的

2016-10-30 17:55

@lyh061619 是否有线程安全问题,不在于有没有使用 static,也不在于有没有共享变量,而在于对共享变量的使用方式

例如,你在 LogService 类中除了定义了这个 me 对象以外,完全没有定义任何其它任何属性,何来线程安全这一说? 因为根本没有共享的对象可言,而 me 这个对象虽然是共享的,但是它没有属性,只有方法,方法中 new 出来的变量是在方法用完后被释放的,没有线程安全问题

还有一种变量共享是绝对安全的,例如你有一个对象是只读的,那么任何线程拿到的值是一样的,也就不存在线程安全问程

总之只需要去了解,多个线程在访问同一块数据区域的时候,会不会造成数据混乱即可,不要被任何形式所拘泥,此外建议你多看看 java 线程安全方面的资料,极度重要

2016-10-30 17:46

在详细了解了那篇博文之后,我再给出如下的认知,补充那篇博文里面所说的:
1:假定你的资源路径使用的是相对路径,也就是说没有以 "/" 打头,或者是没有以 "http://" 打头的路径

2:根据 java web 规范,资源的最终路径会跟着地址栏当前路径去变化,例如,你的某个资源是 <img src="abc.jpg">

3:假定你当前地址栏里面是 "localhost/xxx" 那么资源的最终路径会变成: "locahost/xxx/abc.jpg",而当地址栏里面的路径是 "localhost/yyy" 的时候,你的资源最终路径会立即变成 "/localhost/yyy/abc.jpg"

4:这个问题与 jfinal 毫无关系,无论你用的什么 java 开发框架都是这个行为,是需要自己先有个认知

解决办法无非就是两个:
1:资源使用绝对路径,以 "/" 打头,或者以 "http://" 打头,并且将 contextpath 设置为 "" 值

2:否则就需要在资源路径前面使用一个变量,例如: <img src="${CONTEXT_PATH}abc.jpg"> 然后将这个 CONTEXT_PATH 始终赋上正确的值即可

很显然方法一最省事,不折腾

2016-10-30 11:12

@lyh061619 孺子可教也,是这么回事 ^_^

2016-10-30 00:18

@lyh061619 在业务层创建 dao 是可以的,但仍然不要去调用它的 dao.put/save/update/set 之类的方法,这个对象是共享的,不是线程安全的, java 这门语言是多线程语言,必须要考虑对象在多线程共享情况下的线程安全问题,这是极其重要的java基础知识,必须要对java 线程极其熟悉才能写出健壮的程序

2016-10-29 22:41

除非你将 static final LogService me 这一行代码去掉,那么 dao 则不是共享的,此外,还要保障在外部没有类似 static LogService 的定义, static 是有传递性的,这是 java 基础,建议多了解一下

2016-10-29 22:39

@lyh061619 去掉 final 没有意义,虽然这里不是 static 的,但是如果多线程使用的是同一个 LogService 对象,那么与使用 static 在本质上是一样的错误,总之这里的 dao 是共享变量,不能用于 set、put、save、update 等一切写数据的操作,只能使用 find 系列的方法

2016-10-29 17:37

@johnhan sql 可以采用外部配置文件管理起来,不一定要写在代码中,为此 jfinal 提供了 com.jfinal.plugin.activerecord.Sqls.java 这个工具类来管理

此外 jfinal 2.3 会提供一个功能非常强大的 sql 管理支持,不仅可以管理,而且可以方便地动态生成带参的 sql

2016-10-29 17:34

看到 dao.put(log).save() 这样的代码,就知道大错特错了,jfinal 手册有红色字体明确说明过

dao 是 static 声明的全局共享的东西,不同线程在使用它的时候,数据是共享的,那么你第一次 dao.put 进去东西,第二再使用的时候与第一次会混乱,如果是多线程并发使用,数据是乱窜

所以 jfinal 最佳实践已经明确明说了,要将 Model 中的 dao 彻底删掉,避免这样的误用

删掉以后,查询的时候可以 new Xxx().find(sql) 这样就永远没有线程安全问题了

2016-10-28 17:55

@Romeo jfinal 社区的 UI 我能保证做到简洁但美观方面,我不是学美术的,一定会有所欠缺,好在简洁的 UI 在美观方法也不会太差

2016-10-28 17:32

@andywei 还有一个办法是仿照 CaseInsensitiveContainerFactory 写一个 CamelCaseContainerFactory 在拿数据的时候来做个转换,转换的方法可以直接调用 com.jfinal.kit.Str.java 中的 toCamelCase(...)

2016-10-28 17:28

@andywei 因为这个配置就是通过字段名去取的值,所以最好的办法是将数据表字段也用驼峰命名,这样所有全部都统一了,三年前就已经采用这种方式为字段命名了,极爽

2016-10-28 16:22

这样封装以后,又将开发效率再次提升了。贴代码可以点击编辑器代码语言按钮,选择java语言,这样保存以后的代码就有语法高亮,可读性会提升几个级别。感谢分享