手机信号字母表示

使用智能手机的朋友会发现,在手机信号旁边或者上面都会有一些奇怪的字母,比如3G、E、H等等,这些字母都代表什么意思呢?哪种网络状态速度最快?下面让我们详细了解一下吧!

  1. G指GPRS,它是GSM移动电话用户可用的一种移动数据业务,GPRS可说是GSM的延续,是2.5G网络。在iPhone手机上显示O;2.5G的速度约为10KB/s

  2. E指EDGE网络,是增强型数据速率GSM演进技术,属2.75G,速度约为20KB~30KB/s

  3. 3G指普通3G网络,在国内常见的3G有电信的CDMA2000、联通的WCDMA和移动的TD-SCDMA三种,速度在2-7M;

  4. H见于联通的WCDMA手机上,指3G的升级版HSDPA网络,是3.5G,速度可达14.4M;

  5. H+常见于中国联通的WCDMA手机上,hsdpa的升级版HSPA+,是3.75G,速度可达21M-42M;

从网络速度对比来看,从慢到快依次是 G<E<3G<H<H+

日常生活中,在使用手机的过程中,我们常常可以在屏幕的状态栏上方看到网络信号的标识,大概有G/3G/T/E/1X/H/H+这些信号标识,这些标志代表什么含义呢?

移动卡网络信号有:G、E、T(或者H)

China Mobile

G:G是GPRS通用分组无线服务技术(General Packet Radio Service)的简称,它是GSM移动电话用户可用的一种移动数据业务,GPRS可说是GSM的延续。GPRS的传输速率可提升至56甚至114Kbps,理论上资费较为便宜。具有高速数据传输速度10倍于GSM、永远在线、仅按数据流量计费的特点;

E:E是EDGE(Enhanced Data Rate for GSM Evolution)增强型数据速率GSM演进技术的简称,是一种从GSM到3G的过渡技术,GPRS到第三代移动通信的过渡性技术方案(GPRS俗称2.5G, EDGE俗称2.75G.)。现在中国移动的EDGE网络已经基本上覆盖全国,只有一些较为偏僻的地区无法访问,其传输速率在峰值可以达到384kbps,现在比较主流的无线网络传输方式;

T或者(H):T是TD-SCDMA(Time Division-Synchronous Code Division Multiple Access时分同步码分多址)的简称,其是中国提出的第三代移动通信标准(简称3G),也是ITU批准的三个3G标准中的一个以我国知识产权为主的、被国际上广泛接受和认可的无线通信国际标准。现在使用的版本是R4版本,理论下载数值为378.2KB/S。

移动卡的用户在信号不稳定时,手机可以在这些信号中自动转换,使你的手机基本通话要求得以保证不间断。

联通卡网络信号有:G、3G(或者H或者3.5G)、H+

unicom

G:这里不用介绍了,和移动的G是一样的,但是由于联通建的基站比较少,所以网络信号质量很差,大家都不愿意用了;

3G(或者H或者3.5G):HSDPA(High Speed Downlink Packet Access)高速下行分组接入,是一种移动通信协议,亦称为3.5G(3½G),它的下载速度理论呢是可以达到7.2Mbp/s。在国内的三大运营商中,联通的3G是做的最好的,很多人用;

H+:HSPA+的英文全称为 High-Speed Packet Access+,增强型高速分组接入技术,是HSPA的强化版本,最高的下行21Mbps,大部分HSPA+手机基本都是支持5.76Mbps的最高上行速度和21Mbps或者28Mbps的最高下行速度,相比较HSPA的速度更快。总的来说HSPA+比HSPA的速度更快,性能更好,技术更先进,同时网络也更稳定,是目前LTE技术运用之前的最快的网络!其属于联通3.75G网络,当前的联通3G网络覆盖较好。显示H+的时候网速是最快的,理论速率可以达到42Mbp/s的,也就是联通目前畅销的WO卡。

电信卡网络信号有:1X、3G

telecom

1X:1X即CDMA1x,也就是我们通常所说的电信的2G网络,CDMA1X手机上网的传输速率可达每秒钟144Kb,不过在现在的情况下,1X已经满足不了用户的需求了。不过电信2G(也就是1X)对比其它运营商的G属于是最稳定的,也是表现最好的信号;

3G:3G是指3G信号CDMA2000(EVDO.A),EV-DO是3G CDMA的技术名称,在手机上为了简便显示为3G,它的速率理论上达到3M,但实际上一般只有1.6M左右。它是基于移动网络的多址分发同时提供网络流量,这3家运营商的3G网络信号覆盖最好最广的就是电信的3G信号了,他的实测下载速度峰值可以达到290Kb/s左右,电信卡的资费理论上也比较便宜点;

reference


2014-10-24 Android , Knowledge

照片添加GPS信息

在玩Ingress之后的很长一段时间内,我觉得如果照片没有地理位置信息是一种缺失,而去年买的 Nikon 单反没有GPS模块,Nikon提供的GPS模块需要单独购买价格不便宜并且携带不方便,于是我找到一种既便宜又简洁的方式可以给照片添加上GPS信息。

需要借助的工具:

具体原理是:按照时间顺序,将手机记录的GPS信息写入相机拍摄的照片中。

具体步骤:

  1. 调校相机时间和手机时间保持一致
  2. 使用My Tracks应用记录GPS信息,保证在使用单反拍照前后一直在记录。所以最好的办法是出门前打开My Tracks,回家关闭记录。
  3. 回到家,导出照片,安装GeoSetter软件,将My Tracks记录的文件导出为gpx文件
  4. 打开GeoSetter,全选所有照片,在菜单中找到和GPS文件同步,快捷键Ctrl+G,找到Android手机中Export出的gpx文件,同步。
  5. Ctrl+S,保存。

之后GPS信息就被写到照片文件中了。


2014-10-02 DSLR , GPS , Nikon , 摄影

优化 Java 中正则表达式

Java 中和正则相关的工具类都在 java.util.regex 包下,Java 使用了 Nondeterministic Finite Automaton (NFA),之所以称为非确定性是因为当正则匹配给定字符串时,每一个字符都可能和正则匹配多次。这个匹配引擎被广泛的使用在 .NET, PHP, perl, Python, Ruby 中。很多人认为正则处理很快,很强大,但是其实不同正则表达式的写法可能导致消耗的时间和空间相差几十倍甚至上百倍,当在一些移动设备中使用正则时则要更加注意。

在引擎内部,NFA 使用回溯(backtracking) ,通常情况下针对给定的字符串,正则表达式可能有不止一种匹配方式,那么规则匹配引擎则会尽可能匹配所有可能,直到失败。

为了更好的理解 NFA 和回溯,举一个简单的例子,比如有一个正则表达式 sc(ored|ared|oring)x ,而输入的文本是 scared

在开始的时候,引擎会查找到 sc,立即找到匹配的前两个字符,接着会从第三个字符开始匹配 ored,发现不匹配则会尝试下一个可能 ared,这个匹配成功,继续匹配后面的 x,此时发现不成功,那么引擎会回溯回去匹配第三个可能 oring,同样也没有匹配。那么引擎会回溯到第二个字符开始继续匹配 sc,直到匹配到字符结尾,然后抛出匹配失败。

优化回溯

在上面的例子中就能看到,NFA 使用回溯来进行规则匹配,上面的例子也非常容易发现回溯的一个问题,就是即使是很简单的例子,也可能导致回溯非常多次。由此可以想象,当回溯失控时对应用程序的性能影响。因此优化正则表达式的一个很重要的部分就是尽量减少回溯的次数。

因为回溯的存在,在遇到现实复杂情况时,正则匹配可能需要花费大量时间来寻找完整的匹配。更糟糕的是,引擎花费大量的时间来匹配从而宣告一次失败,这个时间远比一次成功的匹配来得多。因此需要记住的是,当测试正则表达式的速度时,测试正则匹配不成功的时候,而不是测试成功的匹配。而当测试匹配时,则尽量使用刚刚好匹配的字符串,因为这种字符串花费最长的时间。

避免重新编译正则

当程序中需要不止一次使用相同的正则表达式时,预先编译好后使用。先使用 Pattern.compile() 定义好,而不是直接使用 Pattern.matches()matches() 方法内部每一次都会重新编译表达式。

并且记住对于不同的输入字符串,我们可以复用 Matcher 对象,不过要记住调用 reset() 方法。

合理使用括号

如果不需要引用括号内容,使用非捕获型括号 (?:PATTERN),节省捕获时间,减少回溯使用状态数量。只在必要时使用括号捕获。

不要滥用字符组

比如在 [Ff] 应当使用不区分大小写的匹配而不是字符组

准确表达意图

正则表达式提供很多结构(字符组,多选结构,量词等等),很多结构功能存在重叠,做同一件事情可能有不同的表达,这个时候应该选择最适当的结构。比如多选结构和字符组,多选结构完全覆盖了字符组。(a|b|c|d)[abcd] 匹配的文本是一样的,但是多选结构用于处理“可能出现若干表达式”,而字符组是专门用于处理“可能出现若干字符”的,这种情况字符组效率要远远高于多选结构。所以应当选择用 [abcd].

避免多选结构多个分支匹配相同文本

正则非常灵活,往往同一个表达式可能匹配多种不同形态的文本,但是如果一个表达式中包含若干”能匹配不同形态文本“的子表达式,那么子表达式能匹配的文本有重叠就可能有效率问题。

比如 a+a+,再比如 [0-9]+\w+ 前后连接部分产生重复匹配问题。

两条规则

  • 凡是 regex1*regex2*(量词不限于*) 的表达式,都要尽力避免 regex1 和 regex2 能匹配相同的内容
  • 凡是 (regex1|regex2) 的表达式,尽力避免 regex1 和 regex2 匹配相同的内容

使用起始终止锚点

除非是及其罕见的情况,否则以 .* 开头的正则表达式都应该在最前面添加 ^ 或者 \A 如果这个正则表达式在某个字符串的开头不能匹配,那么显然在其他位置它也不能匹配。添加锚点无论是手工添加还是通过优化自动添加都能够配合开头字符 / 字符串 / 字串识别优化,节省大量不必要的工作

在表达式前面独立出 ^ 和 \G

^(?:abc|123)(^abc|^123) 在逻辑上是等价的,但是许多正则引擎指挥对第一个表达式使用 开头字符 / 字符串 / 字串识别优化。所以第一种办法的效率高得多

在表达式结尾独立出 $

确定起止锚点能够提高匹配速度,如果使用了 $ 标记结尾,正则引擎会从符合条件的长度开始匹配,而略过目标字符串中其他不关心的字符。

暴露尽可能多的匹配部分

xx* 替代 x+ 能够暴露必须匹配的 x 同样,用-----{0,2}代替-{5,7}

th(?:is|at) 替代 (?:this|that) ,就能暴露出必须的 th。如果不同的多选分支的结尾部分相同,我们也可以从右面”提取”。例如 (?:optim|standard)ization

对于传统 NFA,一旦匹配到结果就会停止。

用字符组代替分支条件

比如对于想要匹配的 a 或 b 或 c 或 d,使用 [a-d] 而不要使用 (?:a|b|c|d)。字符组比使用分支条件速度快。

谨慎使用点号

谨慎使用点号,星号,加号这样的元字符,只要能确定范围,就不要用点号。只要能够预测重复范围,就不要使用量词。

别过分依赖正则

正则表达式确实很强大,但是不要过分依赖正则。

最常见的错误就是,只要字符串操作就能完成,但非要用正则。比如判定一个字符串以什么开头,或者什么结尾,或者判断是否包含某一个子串。

reference


2014-09-30 java , regex

log4j XML 配置

我们都知道 log4j 有两种配置文件的语法,本文主要介绍 XML 格式的配置格式。

log4j XML 配置的一些细节记录。

priority 和 level 的区别

我们都知道日志打印的级别,从低到高依次是 TRACE, DEBUG, INFO, WARN, ERROR and FATAL.

日常使用中经常会看到 root 或者 logger 节点配置 <level value="INFO"> 这样的语句,root 节点中也有 priority 的配置

<logger name="com.package">
    <level value="WARN" />
</logger>

<root>
  <priority value ="debug" />
  <appender-ref ref="console" />
</root>

定义了 priority 的 root 只会将 DEBUG 级别及其以上级别的日志发送到 Appender 中。logger 的 level 同理,只会将 WARN 级别和以上的日志发送到 appender 中。

他们的区别只在于 priority 在 root 中用,level 则 logger 中用。

appender 中 Threshold 的使用

appender 的配置

<appender name="fileAppender" class="org.apache.log4j.RollingFileAppender">
   <param name="Threshold" value="ERROR"/>
</appender>

假设有如下两种情况。

priority value="DEBUG" and param name="Threshold" value="ERROR"

priority value="ERROR" and param name="Threshold" value="DEBUG"
  1. 第一种情况 Logger 设置优先级 DEBUG,appender Threshold 设置为 ERROR,意味着 logger 会将 DEBUG,INFO,WARN,ERROR 和 FATAL 级别的日志发送到 appender,但是 appender 只会接受 ERROR 和 FATAL 的日志,所以最后日志中只会有 ERROR 和 FATAL 级别的日志。
  2. 第二中情况,logger 设置为 ERROR,appender 设置为 DEBUG,意味着 logger 会将 ERROR 和 FATAL 级别日志 pass 到 appender,而 appender 能够接受 DEBUG,INFO,WARN,ERROR,FATAL 级别的日志,但最后的日志中也只有 ERROR 和 FATAL 级别的日志。

所以两者的最后结果是一致的。组合二者的使用能够更有效率的打印测试环境或者生产环境的日志。

同一份日志打印到多个地方

定义不同的 appender ,然后在 logger 中定义多个在 pass 到 appender 即可。

不同的 package 使用不同的 appender

则在定义 logger 时 name 中指定对应的 package name,然后引用对应的 appender。

不同的 appender 相同的文件

log4j 不支持不同的 appender 打印到相同的文件中。

reference


2014-09-28 java , log4j , log4j12 , log4j12-config

正则学习指导

从开始接触正则到现在已经过去很多年了,然而依然没有完全学会正则,每一次回顾的时候总是有很多很多的新东西。

什么是正则,看中文非常抽象,而英文 regular expression 就好理解得多,regular expression 它是一个有规律,常规的,经常需要用的表达式,究其根本就是一个用来搜索特定字符串的表达式,这个表达式遵循一定的规律,有自身的逻辑表达,通过这种通用的方式可以写出比较容易理解的搜索语句。

根据维基百科的说明 正则一词是美国数学家 Stephen Cole Kleene 于 1950s 正式使用。而这个概念则是在 1980s 因为 Unix 下文本编辑器工具的使用而变得常见。自此之后正则的语法规则 POSIX 和 Perl 区别。

常用表达

表示或

gray|grey

表示匹配 gray 或者 grey 两个单词

分组,用来定义边界,或者确定执行顺序

gr(a|e)y

和上面表达等效

常见的定量表达

?       表示前面的字符出现 0 次或者 1 次
*       表示前面的字符出现 0 次或者多次
+       表示前面的字符出现 1 次或者多次
{n}     表示前面的字符出现 n 次
{m,}    至少 m 次
{m, n}  m 到 n 次

通配符 . 可以匹配任何一个字符

字符组 Character class

字符组 Character Class 是一个比较好理解的,就是一组字符,用方括号来标示,表示匹配其中某一个字符。比如常见的

[aef]
[0-9]
[a-zA-Z]

字符组中的范围表示使用的是 ASCII 编码中的码值,所以不能写成 [9-0]

排除型字符组,在方括号后增加 ^

[^0-9]       # 非 0-9
[^ae]       # 非 a 或 e

字符组简记法,常见的字符组,比如数字,英文字符组,可以用简单的缩写形式来表示。

\d      [0-9]

元字符 meta-character

比如字符组中的 - 还有括号 [, ] 还有常见的 ^, $ 这些特殊意义的字符都是元字符。如果遇到想要匹配这些特殊的字符就需要转义。

^
$
.
[]
[^]
*
()
{}
\b          单词边界
\d          [0-9]
\w          字母数字下划线和汉字
\s          任意空白

后向引用

当用小括号指定子表达式后,匹配这个子表达式的文本(分组捕获)会自动拥有一个组号,从左到右,分组的左括号为标志,出现的第一个分组为 1,其后 2,3,4 类推。

后向引用则可以利用分组捕获的文本来匹配比如重复的单词

\b(\w+)\b\s+\1\b

其中的 \1 在表示引用前面 (\w+) 括号中捕获的文本,比如 go go 则会被匹配。分组捕获通常用在想要获取匹配字符串中部分子串时使用。

但是在使用捕获时一定要注意,过多的捕获会影响正则表达式的效率,如果不需要捕获则可以使用

(?:exp)

来忽略捕获的内容。

分组还有一些其他的语法

(?<name>exp)        匹配 exp,将捕获的文本放到名字为 name 的组,也可以写成 (?'name'exp)
(?#comment)         注释,无任何作用

零宽断言

了解零宽断言需要分两部分来理解,第一是匹配宽度为 0,第二断言表示满足一定的条件。匹配宽度指的是匹配时占字符宽度,比如在匹配不包含 a 或 b 开头的单词时,如果使用 [^ab] 那么 [] 则会占用一个字符宽度。零宽断言用于查找在某些内容(但并不包括这些内容)之前或之后的东西时。

零宽断言的英文是 Lookahead and Lookbehind Zero-Length Assertions 这就好理解很多了,就是正则表达式先要匹配的内容往前或者往后的断言,也就是比如我想要匹配的一串数字必须在 id= 后面就可以使用先行断言

(?=id=)\d+

零宽断言又分四种

(?=exp)         断言自身出现的位置的后面能匹配表达式 exp
(?<=exp)        断言自身出现的位置的前面能匹配表达式 exp
(?!exp)         断言此位置的后面不能匹配表达式 exp
(?<!exp)        断言此位置的前面不能匹配表达式 exp

先行断言

先行断言,也叫零宽度正预测先行断言 (?=exp) 表示匹配表达式前面的位置

比如,b\w+(?=ing\b) ,匹配以 ing 结尾的单词的前面部分(除了 ing 以外的部分)

注意:先行断言的执行步骤是这样的,先从要匹配的字符串中的最右端找到第一个 ing(也就是先行断言中的表达式)然后再匹配其前面的表达式,若无法匹配则继续查找第二个 ing 再匹配第二个 ing 前面的字符串,若能匹配则匹配

例如: .*(?=ing) 可以匹配 cooking singing 中的 cooking sing 而不是 cook

后发断言

后发断言,也叫零宽度正回顾后发断言 (?<=exp) 表示匹配表达式后面的位置

例如 (?<=abc).* 可以匹配 abcdefg 中的 defg

注意:后发断言跟先行断言相反,它的执行步骤是这样的:先从要匹配的字符串中的最左端找到第一个 abc(也就是先行断言中的表达式)然后 再匹配其后面的表达式,若无法匹配则继续查找第二个 abc 再匹配第二个 abc 后面的字符串,若能匹配则匹配

例如 (?<=abc).* 可以匹配 abcdefgabc 中的 defgabc 而不是 abcdefg

负向零宽断言

负向零宽断言 (?!exp) 也是匹配一个零宽度的位置,不过这个位置的“断言”取表达式的反值,同样,负向零宽断言也有“先行”和“后发”两种,负向零宽后发断言为 (?<!exp)

比如说想要匹配文本中所有等号后面的数字,但是就是不想匹配 id=123 这样 id= 开始的数字

(?<!id)=\d+

这四个断言的中文翻译的太烂了,完全不知道说的什么,用英语解释就清晰很多。

Atomic groups

Atomic groups 光看字面意思完全无法理解,但是如果举例说明,比如

a(bc|b)c

这是一个普通的分组正则,可以匹配 abcc 或者 abc,但是

a(?>bc|b)c

使用 Atomic groups 之后则只能匹配 abcc 而不能匹配 abc.

Atomic groups 在匹配 abc 时,括号中匹配到 bc 就退出了,而此时无法匹配括号外的 c 则失败了。

Atomic groups 会查找到第一个匹配的子串,然后就退出匹配,也不会回溯。所以如果在一些匹配到第一项,而后面不需要考虑的情况下可以使用 Atomic groups。

实例

比如说字符串 foobarbarfoo:

bar(?=bar)     finds the 1st bar ("bar" which has "bar" after it)
bar(?!bar)     finds the 2nd bar ("bar" which does not have "bar" after it)
(?<=foo)bar    finds the 1st bar ("bar" which has "foo" before it)
(?<!foo)bar    finds the 2nd bar ("bar" which does not have "foo" before it)

组合使用:

(?<=foo)bar(?=bar)    finds the 1st bar ("bar" with "foo" before it and "bar" after it)

表示匹配 bar 要求前面是 foo 而后面是 bar,那么就匹配第一个 bar 了。

Look ahead positive (?=)

Find expression A where expression B follows:

A(?=B)

Look ahead negative (?!)

Find expression A where expression B does not follow:

A(?!B)

Look behind positive (?<=)

Find expression A where expression B precedes:

(?<=B)A

Look behind negative (?<!)

Find expression A where expression B does not precede:

(?<!B)A

Atomic groups (?>)

An atomic group exits a group and throws away alternative patterns after the first matched pattern inside the group (backtracking is disabled).

  • (?>foo|foot)s applied to foots will match its 1st alternative foo, then fail as s does not immediately follow, and stop as backtracking is disabled

A non-atomic group will allow backtracking; if subsequent matching ahead fails, it will backtrack and use alternative patterns until a match for the entire expression is found or all possibilities are exhausted.

  • (foo|foot)s applied to foots will:

    1. match its 1st alternative foo, then fail as s does not immediately follow in foots, and backtrack to its 2nd alternative;
    2. match its 2nd alternative foot, then succeed as s immediately follows in foots, and stop.

网页

匹配网页标题

<head>([^<]+)</head>

然后取分组 1

网页图片

<img\s+[^>]*? src=['"]?([^"'\s]+)['"]?[^>]*>

取分组 1

身份证

简单版本,不精确

[1-9]\d{14}
[1-9]\d{14}\d{2}[0-9xX]

reference


2014-09-27 regex , regular-expression , java , python , nlp

log4j 根据 package 打印日志到不同目的地

log4j 可以配置不同的包打印到不同的 appender 中,通过在配置中添加如下配置。

<!-- 这里的 additivity 配置了该 package 下的 appender 是否需要传递到 root , 默认为 true , 造成日志打印两遍 -->
<logger name="com.jutils.appender.LogLevelATest" additivity="false">
  <level value="INFO"/>
  <appender-ref ref="consoleAppender"/>
</logger>
<logger name="com.jutils.appender.LogLevelBTest" >
  <level value="WARN"/>
</logger>

定义 logger 在 name 中指定需要 include 的 package full path,然后在 appender-ref 中指定需要打到的 Appender 中。


2014-09-27 log4j , log4j12 , log4j12-conf , log4j12-xml

记账 App 选择

很久之前产生记账的需求,所以当时试用了市场上很大一批的记账软件和 App,我的需求无非有几样:

  • 多平台同步,至少 Web,Android 平台有产品
  • 记账方便,随时随地能够使用
  • 界面简洁美观,能方便查看使用记录,和历史统计信息
  • 方便导出

在使用了近半年之后,我终于稳定的在使用一款叫做“随手记”的记账软件了。而事实上我看到很多 Google+ 的好友在使用类 Excel 工具记账,我也曾经使用过一段时间的 Excel,却没有坚持下来。使用这样一类工具时,我总感觉不是很方便,虽然也可以使用 Dropbox 或者其他工具同步到手机上,再使用 Office 打开编辑,但是终究多了些步骤。

过去一段时间我试用过的应用有:

随手记的开发人员是中国人,所以使用习惯还是挺符合国人的。当然对于基本的记账功能,随手记和 Expense Manager 都是有的。只是最后归结到细节的功能上,Expense Manager 只有 Android 端,虽然 UI 符合 Holo 风格,界面简洁明了,但是细节的功能太少,不值得玩味,并且不支持同步,虽然 Expense Manager 能够导出到 Excel,但还是将流程复杂了。 而随手记,有几个功能确实非常实用:

  • 丰富的分类,和子分类
  • 记账模板
  • 周期自动记账

虽然一开始我觉得随手记的分类太过复杂,记一笔账还得找好一会儿分类,但是用过一段时间之后发现其实这样对于以后查看使用是很有帮助的,并且分类和子分类都可以自定义,非常方便。而记账模板则是可以自定义一套模板,之后记录相同的账目可以套用一套模板。对于一些经常记录的分类,比如早午晚餐,周期性的购物都可以使用一套模板。另外周期自动记账就是可以将每月固定的支持,收入自动记录账目。

想要了解更多 Expense Manager 可以到电脑玩物

另外一些记账软件

2018 06 08 更细

最近又发现一款设计精致使用方便的记账应用,叫做 圈子账本 核心概念就是记账,能够同步账本,共享账本,初体验感觉似乎适合轻量的记账需求。有需求的人可以体验体验。至于我虽然限免的时候下载了 Pro 版本的记账,但于我,还不想迁移到这个应用来,虽然设计体验都还不错,但是因为之前一直用的随手记,加之基本消费都用信用卡,所以单独再去换一个记账 App 也没有什么必要了。 PS. 支持 Android 和 iOS。

写下这段文字的时候,边写边看了他们官网的宣传视频,提到这款产品 15 年上市,想来写下这篇文章竟然已经过了 4 年。这 4 年里老牌的随手记依然还在,新出来很多记账软件,各有各的特点,选择一款,然后记录吧。


2014-09-09 android , web , android-app , app , ios

电影版本中的缩写是什么意思

在网络下载资源时经常遇到一些整齐划一的命名,于是产生了这样的疑惑。

CAM(枪版)

CAM通常是用数码摄像机从电影院盗录。有时会使用小三角架,但大多数时候不可能使用,所以摄像机会抖动。因此我们看到画面通常偏暗人物常常会失真,下方的 字幕时常会出现倾斜。 由于声音是从摄像机自带的话筒录制,所以经常会录到观众的笑声等声音。因为这些因素,图象和声音质量通常都很差。

TS(准枪版)

TS是TELESYNC的缩写。TS与CAM版的标准是相同的。但它使用的是外置音源(一般是影院座椅上为听力不好的人设的耳机孔)这个音源不能保证是好的音源,因为受到很多背景噪音的干扰。TS是在空的影院或是用专业摄像机在投影室录制,所以图象质量可能比CAM好。但画面的起伏很大。论坛上常出现的有一般TS版和经过修复清晰TS版

TC(胶片版)

TC是TELECINE的缩写。TC使用电视电影机从胶片直接数字拷贝。画面质量还不错,但亮度不足,有些昏暗。很多时候制作TC使用的音源来自TS,因此音质很差,但画面质量远好过TS。如果不是太讲究的话TC版还是不错的选择。

DVDSCR(预售版)

SCR是SCREENER的缩写。DVDSCR预览版的或者是测试版的DVD,非正式出版的版本。从预览版 DVD 中获取,通过mpeg-4技术进行高质量压缩的视频格式。能比DVDRip早发布,但画质稍差。(经常有一些不在黑边里在屏幕下方滚动的消息,包含版权和反盗版电话号码 ,会影响观看。)如果没有严格的划分它的画质应与TC版差不多。

R5(俄罗斯5区版)

俄罗斯5区版的DVD,因为配音为俄语,所以需要去寻找英语音轨,R5版本就是一种合成版本(俄5区DVD视频+通过其它渠道获得的英语音轨),R5版本的画质一般都不错,音频部分由于音轨的来源不同,效果有好有差。

这里的 R=Region 美国电影协会划分的DVD区域码有:

  • 第一区:美国、加拿大; 第二区:日本、欧洲、埃及、南非、中东;
  • 第三区:中国台湾、中国香港特别行政区、南韩、东南亚;
  • 第四区:澳洲、新西兰、中南美洲、南太平洋岛屿;
  • 第五区:俄罗斯、蒙古、印度、中亚、东欧、北韩、北非、西北亚一带等;
  • 第六区:中国(除台、港地区)

HD RIP(高清版)

HDRip 是HDTVRip(高清电视资源压缩)的缩写,是用DivX/XviD/x264等MPEG4压缩技术对HDTV的视频图像进行高质量压缩,然后将视频、音频部分封装成一个.avi或.mkv文件,最后再加上外挂的字幕文件而形成的视频格式。画面清晰度更高。

BD(蓝光版)

BD是Blue Disk的简称,翻译成中文是“蓝光影碟”的意思。就是从蓝光影碟转录的视频和音频,画面清晰度很高。

DVD,HDVD,DVD5,DVD9

DVD的英文全名是Digital Video Disk,即数字视频光盘或数字影盘,它利用MPEG2的压缩技术来储存影像。

HDVD(压缩碟或者经济版DVD)

HDVD俗称压缩碟或者经济版DVD,介质通常为DVD-5(容量4.7G)也有DVD-9的(容量8.5G),采用MPEG-1或MPEG-2编码,由于码流较低,所以每张盘可容纳长达7个小时的视频节目,画质水平略高于或等同于VCD。用于看连续剧最省钱。

VHSRip

VHSRip是从零售版VHS录象带转制,主要是滑冰/体育内容的发布。

TVRip

从电视(最好是从数码有线电视/卫星电视捕捉)转制的电视剧,或接收由卫星提前几天向电视网传送的预播节目(不包含加密但有时有雪花)。有些节目,比如WWF RAW IS WAR包含多余的部分;”DARK MATCHES”和CAMERA/COMMENTARY测试被包含在TVRip里。PDTV是从PCI数码电视卡捕捉,通常效果最好;破解组织倾向于使用SVCD来发布。VCD/SVCD/DivX/XviD rips也都被用于发布TVRip。

WORKPRINT (WP)

WORKPRITN (WP)是从未完成的电影拷贝转制而成,可能会缺失镜头和音乐。质量可能从最好到很差。有些WP可能和最终版本相差很远。(MEN IN BLACK的WP丢失了所有的外星人,代之以演员);另一些则包括多余的镜头(Jay and Silent Bob). WPs可以作为有了好质量的最终版本后的附加收藏。

DivX Re-Enc

DivXRe-Enc是从原始VCD发布用DivX编码成的小一些的文件。通常可在文件共享网络找到。它们通常以 Film.Name.Group(1of2)等形式命名。常见的发布组织有SMR和TND。这些版本通常不值得下载,除非你不清楚某部电影,只想要200MB的版本。一般应避免。

Watermarks

很多从Asian Silvers/PDVD (参看下面)来的电影带有制作人的标记。通常是一个字母,名字缩写或图标,位于屏幕一角。最有名的是”Z”,”A”和”Globe”。

Asian Silvers / PDVD

Asian Silvers / PDVD是亚洲盗版商发行影片的,通常被一些发布组织购买来当做他们自己的发布。Silvers很便宜,在很多国家都很容易找到。发布Silvers很容易,所以现在有很多发布,主要是由一些小的组织发布;这些组织通常发布几个RELEASE后就不见了。PDVD和Silver一样,不过是压在DVD上。 PDVD通常有外挂字幕,质量也比Silver好。PDVD象普通的DVD一样转制,但通常用VCD的格式发布Scene Tags发布文件的标志。

PROPER

根据发布规则,最先发布Telesync (TS)的组织赢得(TS发布的)比赛。但是,如果这个发布版本质量很差,同时另一组织有另一TS版本(或质量更好的同一片源),那么标记PROPER被加到目录上以避免重复。PROPER是一个最主观的标记,很多人会争论是否PROPER比原始发布版本好。很多发布组织只不过因为输掉了发布比赛而发布 PROPER。发布PROPER的原因因该总是包含在NFO文件里。

SUBBED

对于VCD发布而言,SUBBED通常表示字幕被压进了电影。它们通常是马来语/中文/泰文等,有时有两种语言。它们可能占据了很大一部分屏幕。SVCD支持外挂字幕,所以DVDRip用外挂字幕发布。这些信息可以在NFO文件中找到。

UNSUBBED

当一部电影曾经发布过有字幕的SUBBED版本,没字幕的UNSUBBED版本也可能发布。

LIMITED

LIMITED电影指该电影只在有限的电影院放映,通常少于250家。通常较小的电影(比如艺术电影)的发行是LIMETED。

INTERNAL

INTERNAL发布有几个原因。经典的DVD组织有很多.INTERNAL.发布版本,这样不会引起混淆。同时,低质量的发布会加以 INTERNAL标记,这样不会降低发布组织的声誉,或由于已经发布的数量。

INTERNAL发布可以正常的在组织的会员网站上获取,但没有其他网站管理员的要求它们不可以被交换到其他网站。一些TERNAL发布仍然流到IRC/NEWSGROUP,这通常取决于电影及其流行度。今年早些时候,人们把 CENTROPY做为INTERNAL。这表示发布组织只向其会员和网站管理员发布。这和其通常意思不同。

STV

STV表示电影从未在电影院放映过就被发布,因此很多望网站不允许STV。

ASPECT RATIO TAGS

ws表示宽银幕,FS表示全屏幕。

RECODE

RECODE是以前已经发布过的版本,通常用TMPGenc编码过滤以去除字幕,纠正颜色等。虽然它们看起来好一些,但通常不认为这是好的行为因为发布组织应该去找他们自己的片源。

REPACK

如果发布组织发布了一个坏的版本,他们会发布REPACK来解决这些问题。

NUKED

一个发布可能因为多种原因被NUKE掉。有些网站会因为违犯他们的规则而NUKE发布(比如不允许发布TS版本)。但如果发布的版本有很大的问题(如20分钟没有声音,CD2是错误的电影或游戏),那么所有的网站都会NUKE这个发布。在这些网站上交换NUKED版本的人会失掉他们的信誉。但NUKED发布仍然可以通过P2P/USENET传播,所以应该总是首先找到其被NUKE的原因以防万一。如果发布组织发觉他们的发布有问题,他们可以要求NUKE。


2014-09-03 Movie , Knowledge

MyBatis Generator Plugins

MyBatis Generator(以下简称 MBG) 插件可以很方便的生成 Objects、Mapper 接口以及对应的 XML 文件。在使用 MBG 的时候也可以配置一些插件来自定义生成的文件的内容。

MBG 提供了一些自带的插件,比如缓存的,分页的等等,如果想要实现更多的功能可以参考这里 自己实现插件。

MBG 提供的插件都在 org.mybatis.generator.plugins 包下。插件源代码可以参考这里

org.mybatis.generator.plugins.CachePlugin

缓存插件,用来生成在 XML 中的 <cache> 元素

  • cache_eviction
  • cache_flushInterval
  • cache_readOnly
  • cache_size
  • cache_type

org.mybatis.generator.plugins.CaseInsensitiveLikePlugin

用来在 Example 类中生成大小写敏感的 LIKE 方法

org.mybatis.generator.plugins.EqualsHashCodePlugin

用来给 Java 模型生成 equals 和 hashcode 方法

org.mybatis.generator.plugins.FluentBuilderMethodsPlugin

生成带有 fluent 风格的 model 代码,该插件不接受任何参数。

通常是生成 setXX 方法,而使用这个插件后会生成 public MyClass withXX(String XX) 这样的方法。

这样就可以像使用 Builder 方法一样级联起来使用,比如

new MyDomain().withFoo("Test").withBar(4711);

org.mybatis.generator.plugins.MapperAnnotationPlugin

Only MyBatis3 环境,用来在 mapper 接口中增加 @Mapper 注解。

org.mybatis.generator.plugins.MapperConfigPlugin

插件会产生一个 MapperConfig.xml 模板文件,该文件包含了 MBG 产生的 XML mapper 文件。

org.mybatis.generator.plugins.RenameExampleClassPlugin

这个插件演示了使用 initialized 方法来重命名 MBG 自动产生的 example classes。

插件有两个属性

  • searchString 必须,正则表达式用来搜索默认的产生的名字
  • replaceString 必须,用来替换 searchString 搜索到的内容

比如,重命名 example 类从 xxxExample 到 xxxCriteria,那么在 searchString 中使用 Example$ 然后配置 replaceString 为 Criteria.

<property name="searchString" value="Example$" />
<property name="replaceString" value="Criteria" />

org.mybatis.generator.plugins.RowBoundsPlugin

该插件会增加一个新版本的 selectByExample 方法,接受一个 RowBounds 参数。该方法支持 MyBatis RowBounds 方法会返回指定开始位置之后一个指定长度的结果列表,在分页应用中非常有用。

org.mybatis.generator.plugins.SerializablePlugin

该插件给生成的 Java 类增加了接口 java.io.Serializable。该插件同样会增加一个 serialVersionUID 字段。

org.mybatis.generator.plugins.SqlMapConfigPlugin

该插件产生一个 SqlMapConfig.xml 模板,包含 sqlMap 条目所有生成的 SQL 映射

org.mybatis.generator.plugins.ToStringPlugin

该插件给生成的 Java 类增加 toString() 方法。

org.mybatis.generator.plugins.UnmergeableXmlMappersPlugin

该插件会禁用 XML 覆盖生成。

org.mybatis.generator.plugins.VirtualPrimaryKeyPlugin

该插件会模拟指定的 columns 作为 primary key,即使在数据库中并没有定义为 primary key。通常在数据库没有指定 primary key 的时候有用。正常情况下如果没有定义 primary key, MBG 只会产生非常少的方法,而该插件可以生成很多的方法。

启用该插件的方法,在 table 配置下增加一个 virtualKeyColumns 属性

<table tableName="foo">
  <property name="virtualKeyColumns" value="ID1, ID2" />
</table>

自定义插件

所有 MBG 的插件都是实现的 Plugin 接口,其中定义了一些方法,这些方法都是在代码生成中可能被多次调用的,PluginAdapter 抽象类实现了 Plugin 部分方法。推荐在实现自己的插件时继承 PluginAdapter 类即可。或者如果有能力完整实现 Plugin 接口也可以。

插件是有生命周期的

  • The setXXX methods are called one time
  • The validate method is called one time
  • The initialized method is called for each introspected table
  • The clientXXX methods are called for each introspected table
  • The providerXXX methods are called for each introspected table
  • The modelXXX methods are called for each introspected table
  • The sqlMapXXX methods are called for each introspected table
  • The contextGenerateAdditionalJavaFiles(IntrospectedTable) method is called for each introspected table
  • The contextGenerateAdditionalXmlFiles(IntrospectedTable) method is called each introspected table
  • The contextGenerateAdditionalJavaFiles() method is called one time
  • The contextGenerateAdditionalXmlFiles() method is called one time

插件和 contexts 相关,每一个 contexts 都可能有一个或者多个插件,如果同一个插件在不同的 context 中,那么每一个 context 都会持有一个插件的实例。

几个重要的方法

void initialized(IntrospectedTable introspectedTable);

该方法在 getGeneratedXXXFiles 方法调用前被调用,插件可以复写该方法来在真正生成代码前覆盖任何属性,或者数据库 introspection 的结果。属性会在 IntrospectedTable 中作为静态 Strings 被列出,并且拥有 ATTR_ 前缀。

一个比较好的例子是在重写该方法来改变生成的代码文件名字,改变 target 包,或者改变生成的 SQL map 文件。官方提供的插件 RenameExampleClassPlugin 就是一个很好的例子,在该方法中改变了 Example 文件的名字。

boolean validate(List<String> warnings);

validate 方法会在所有 setXXX 方法后被调用,但是会在其他方法调用前被调用。该方法用来决定插件是否运行,例如插件需要依赖某配置属性来运行,然而该配置没有设置,那么插件无效,并不会执行。对于不需要任何配置的插件,直接返回 true 即可。

boolean clientGenerated(Interface interfaze, TopLevelClass topLevelClass, IntrospectedTable introspectedTable);

该方法会在整个 client 生成后被调用。如果要增加额外的方法或者字段就实现该方法。

boolean clientCountByExampleMethodGenerated(Method method, TopLevelClass topLevelClass, IntrospectedTable introspectedTable);

该方法会在 client 实现类中 countByExample 方法生成后被调用。

boolean clientDeleteByExampleMethodGenerated(Method method, TopLevelClass topLevelClass, IntrospectedTable introspectedTable);

同理在客户端实现类生成 deleteByExample 后被调用。其他的方法列举如下:

boolean clientDeleteByPrimaryKeyMethodGenerated(Method method, TopLevelClass topLevelClass, IntrospectedTable introspectedTable);
boolean clientInsertMethodGenerated(Method method, TopLevelClass topLevelClass, IntrospectedTable introspectedTable);
boolean clientInsertSelectiveMethodGenerated(Method method, TopLevelClass topLevelClass, IntrospectedTable introspectedTable);
boolean clientSelectByExampleWithBLOBsMethodGenerated(Method method, TopLevelClass topLevelClass, IntrospectedTable introspectedTable);
boolean clientSelectByExampleWithoutBLOBsMethodGenerated(Method method, TopLevelClass topLevelClass, IntrospectedTable introspectedTable);
boolean clientSelectByPrimaryKeyMethodGenerated(Method method, TopLevelClass topLevelClass, IntrospectedTable introspectedTable);
boolean clientUpdateByExampleSelectiveMethodGenerated(Method method, TopLevelClass topLevelClass, IntrospectedTable introspectedTable);
boolean clientUpdateByExampleWithBLOBsMethodGenerated(Method method, TopLevelClass topLevelClass, IntrospectedTable introspectedTable);
boolean clientUpdateByExampleWithoutBLOBsMethodGenerated(Method method, TopLevelClass topLevelClass, IntrospectedTable introspectedTable);
boolean clientUpdateByPrimaryKeySelectiveMethodGenerated(Method method, TopLevelClass topLevelClass, IntrospectedTable introspectedTable);

等等等,太多了就略去一部分。 clientXXX 这组方法还有一组参数不同的方法,其中第二个参数是 Interface

boolean clientCountByExampleMethodGenerated(Method method, Interface interfaze, IntrospectedTable introspectedTable);

这组方法会在 client interface 的 countByExample 方法被生成后调用。

boolean modelFieldGenerated(Field field, TopLevelClass topLevelClass,
        IntrospectedColumn introspectedColumn,
        IntrospectedTable introspectedTable, ModelClassType modelClassType);

modelXXX 方法会在 table 中指定的列 field 被生成后调用。

reference


2014-08-28 mybatis , mybatis-generator , java , orm , mysql

Mybatis Generator 配置详解

通常情况下会用 xml 来配置 Mybatis Generator 通常在 src/main/resources/generatorConfig.xml 文件中。

官方的配置文档可以在这里 找到。

Generator 的配置文件主要定义了:

  • 如何连接数据库
  • 需要自动生成什么 Objects,以及如何生成
  • 哪一张 table 需要用来生成 Objects

下面是一个简单的示例:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
  PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
  "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">

<generatorConfiguration>
  <classPathEntry location="/Program Files/IBM/SQLLIB/java/db2java.zip" />

  <context id="DB2Tables" targetRuntime="MyBatis3">
    <jdbcConnection driverClass="COM.ibm.db2.jdbc.app.DB2Driver"
        connectionURL="jdbc:db2:TEST"
        userId="db2admin"
        password="db2admin">
    </jdbcConnection>

    <javaTypeResolver >
      <property name="forceBigDecimals" value="false" />
    </javaTypeResolver>

    <javaModelGenerator targetPackage="test.model" targetProject="\MBGTestProject\src">
      <property name="enableSubPackages" value="true" />
      <property name="trimStrings" value="true" />
    </javaModelGenerator>

    <sqlMapGenerator targetPackage="test.xml"  targetProject="\MBGTestProject\src">
      <property name="enableSubPackages" value="true" />
    </sqlMapGenerator>

    <javaClientGenerator type="XMLMAPPER" targetPackage="test.dao"  targetProject="\MBGTestProject\src">
      <property name="enableSubPackages" value="true" />
    </javaClientGenerator>

    <table schema="DB2ADMIN" tableName="ALLTYPES" domainObjectName="Customer" >
      <property name="useActualColumnNames" value="true"/>
      <generatedKey column="ID" sqlStatement="DB2" identity="true" />
      <columnOverride column="DATE_FIELD" property="startDate" />
      <ignoreColumn column="FRED" />
      <columnOverride column="LONG_VARCHAR_FIELD" jdbcType="VARCHAR" />
    </table>

  </context>
</generatorConfiguration>

更加复杂的例子:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
  PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<!-- 配置生成器 -->
<generatorConfiguration>
<!-- 可以用于加载配置项或者配置文件,在整个配置文件中就可以使用 ${propertyKey}的方式来引用配置项
    resource:配置资源加载地址,使用 resource,MBG 从 classpath 开始找,比如 com/myproject/generatorConfig.properties
    url:配置资源加载地质,使用 URL 的方式,比如 file:///C:/myfolder/generatorConfig.properties.
    注意,两个属性只能选址一个;

    另外,如果使用了 mybatis-generator-maven-plugin,那么在 pom.xml 中定义的 properties 都可以直接在 generatorConfig.xml 中使用
<properties resource="" url="" />
 -->

 <!-- 在 MBG 工作的时候,需要额外加载的依赖包
    location 属性指明加载 jar/zip 包的全路径
<classPathEntry location="/path/to/IBM/SQLLIB/java/db2java.zip" />
  -->

<!--
    context: 生成一组对象的环境
    id: 必选,上下文 id,用于在生成错误时提示
    defaultModelType: 指定生成对象的样式
        1,conditional:类似 hierarchical;
        2,flat:所有内容(主键,blob)等全部生成在一个对象中;
        3,hierarchical:主键生成一个 XXKey 对象 (key class),Blob 等单独生成一个对象,其他简单属性在一个对象中 (record class)
    targetRuntime:
        1,MyBatis3:默认的值,生成基于 MyBatis3.x 以上版本的内容,包括 XXXBySample;
        2,MyBatis3Simple:类似 MyBatis3,只是不生成 XXXBySample;
    introspectedColumnImpl:类全限定名,用于扩展 MBG
-->
<context id="mysql" defaultModelType="hierarchical" targetRuntime="MyBatis3Simple" >

    <!-- 自动识别数据库关键字,默认 false,如果设置为 true,根据 SqlReservedWords 中定义的关键字列表;
        一般保留默认值,遇到数据库关键字(Java 关键字),使用 columnOverride 覆盖
     -->
    <property name="autoDelimitKeywords" value="false"/>
    <!-- 生成的 Java 文件的编码 -->
    <property name="javaFileEncoding" value="UTF-8"/>
    <!-- 格式化 java 代码 -->
    <property name="javaFormatter" value="org.mybatis.generator.api.dom.DefaultJavaFormatter"/>
    <!-- 格式化 XML 代码 -->
    <property name="xmlFormatter" value="org.mybatis.generator.api.dom.DefaultXmlFormatter"/>

    <!-- beginningDelimiter 和 endingDelimiter:指明数据库的用于标记数据库对象名的符号,比如 ORACLE 就是双引号,MYSQL 默认是`反引号; -->
    <property name="beginningDelimiter" value="`"/>
    <property name="endingDelimiter" value="`"/>

    <!-- 必须要有的,使用这个配置链接数据库
        @TODO: 是否可以扩展
     -->
    <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql:///pss" userId="root" password="admin">
        <!-- 这里面可以设置 property 属性,每一个 property 属性都设置到配置的 Driver 上 -->
    </jdbcConnection>

    <!-- java 类型处理器
        用于处理 DB 中的类型到 Java 中的类型,默认使用 JavaTypeResolverDefaultImpl;
        注意一点,默认会先尝试使用 Integer,Long,Short 等来对应 DECIMAL 和 NUMERIC 数据类型;
    -->
    <javaTypeResolver type="org.mybatis.generator.internal.types.JavaTypeResolverDefaultImpl">
        <!--
            true:使用 BigDecimal 对应 DECIMAL 和 NUMERIC 数据类型
            false:默认,
                scale>0;length>18:使用 BigDecimal;
                scale=0;length[10,18]:使用 Long;
                scale=0;length[5,9]:使用 Integer;
                scale=0;length<5:使用 Short;
         -->
        <property name="forceBigDecimals" value="false"/>
    </javaTypeResolver>


    <!-- java 模型创建器,是必须要的元素
        负责:1,key 类(见 context 的 defaultModelType);2,java 类;3,查询类
        targetPackage:生成的类要放的包,真实的包受 enableSubPackages 属性控制;
        targetProject:目标项目,指定一个存在的目录下,生成的内容会放到指定目录中,如果目录不存在,MBG 不会自动建目录
     -->
    <javaModelGenerator targetPackage="com._520it.mybatis.domain" targetProject="src/main/java">
        <!--  for MyBatis3/MyBatis3Simple
            自动为每一个生成的类创建一个构造方法,构造方法包含了所有的 field;而不是使用 setter;
         -->
        <property name="constructorBased" value="false"/>

        <!-- 在 targetPackage 的基础上,根据数据库的 schema 再生成一层 package,最终生成的类放在这个 package 下,默认为 false -->
        <property name="enableSubPackages" value="true"/>

        <!-- for MyBatis3 / MyBatis3Simple
            是否创建一个不可变的类,如果为 true,
            那么 MBG 会创建一个没有 setter 方法的类,取而代之的是类似 constructorBased 的类
         -->
        <property name="immutable" value="false"/>

        <!-- 设置一个根对象,
            如果设置了这个根对象,那么生成的 keyClass 或者 recordClass 会继承这个类;在 Table 的 rootClass 属性中可以覆盖该选项
            注意:如果在 key class 或者 record class 中有 root class 相同的属性,MBG 就不会重新生成这些属性了,包括:
                1,属性名相同,类型相同,有相同的 getter/setter 方法;
         -->
        <property name="rootClass" value="com._520it.mybatis.domain.BaseDomain"/>

        <!-- 设置是否在 getter 方法中,对 String 类型字段调用 trim() 方法 -->
        <property name="trimStrings" value="true"/>
    </javaModelGenerator>


    <!-- 生成 SQL map 的 XML 文件生成器,
        注意,在 Mybatis3 之后,我们可以使用 mapper.xml 文件 +Mapper 接口(或者不用 mapper 接口),
            或者只使用 Mapper 接口 +Annotation,所以,如果 javaClientGenerator 配置中配置了需要生成 XML 的话,这个元素就必须配置
        targetPackage/targetProject: 同 javaModelGenerator
     -->
    <sqlMapGenerator targetPackage="com._520it.mybatis.mapper" targetProject="src/main/resources">
        <!-- 在 targetPackage 的基础上,根据数据库的 schema 再生成一层 package,最终生成的类放在这个 package 下,默认为 false -->
        <property name="enableSubPackages" value="true"/>
    </sqlMapGenerator>


    <!-- 对于 mybatis 来说,即生成 Mapper 接口,注意,如果没有配置该元素,那么默认不会生成 Mapper 接口
        targetPackage/targetProject: 同 javaModelGenerator
        type:选择怎么生成 mapper 接口(在 MyBatis3/MyBatis3Simple 下):
            1,ANNOTATEDMAPPER:会生成使用 Mapper 接口 +Annotation 的方式创建(SQL 生成在 annotation 中),不会生成对应的 XML;
            2,MIXEDMAPPER:使用混合配置,会生成 Mapper 接口,并适当添加合适的 Annotation,但是 XML 会生成在 XML 中;
            3,XMLMAPPER:会生成 Mapper 接口,接口完全依赖 XML;
        注意,如果 context 是 MyBatis3Simple:只支持 ANNOTATEDMAPPER 和 XMLMAPPER
    -->
    <javaClientGenerator targetPackage="com._520it.mybatis.mapper" type="ANNOTATEDMAPPER" targetProject="src/main/java">
        <!-- 在 targetPackage 的基础上,根据数据库的 schema 再生成一层 package,最终生成的类放在这个 package 下,默认为 false -->
        <property name="enableSubPackages" value="true"/>

        <!-- 可以为所有生成的接口添加一个父接口,但是 MBG 只负责生成,不负责检查
        <property name="rootInterface" value=""/>
         -->
    </javaClientGenerator>

    <!-- 选择一个 table 来生成相关文件,可以有一个或多个 table,必须要有 table 元素
        选择的 table 会生成一下文件:
        1,SQL map 文件
        2,生成一个主键类;
        3,除了 BLOB 和主键的其他字段的类;
        4,包含 BLOB 的类;
        5,一个用户生成动态查询的条件类(selectByExample, deleteByExample),可选;
        6,Mapper 接口(可选)

        tableName(必要):要生成对象的表名;
        注意:大小写敏感问题。正常情况下,MBG 会自动的去识别数据库标识符的大小写敏感度,在一般情况下,MBG 会
            根据设置的 schema,catalog 或 tablename 去查询数据表,按照下面的流程:
            1,如果 schema,catalog 或 tablename 中有空格,那么设置的是什么格式,就精确的使用指定的大小写格式去查询;
            2,否则,如果数据库的标识符使用大写的,那么 MBG 自动把表名变成大写再查找;
            3,否则,如果数据库的标识符使用小写的,那么 MBG 自动把表名变成小写再查找;
            4,否则,使用指定的大小写格式查询;
        另外的,如果在创建表的时候,使用的""把数据库对象规定大小写,就算数据库标识符是使用的大写,在这种情况下也会使用给定的大小写来创建表名;
        这个时候,请设置 delimitIdentifiers="true"即可保留大小写格式;

        可选:
        1,schema:数据库的 schema;
        2,catalog:数据库的 catalog;
        3,alias:为数据表设置的别名,如果设置了 alias,那么生成的所有的 SELECT SQL 语句中,列名会变成:alias_actualColumnName
        4,domainObjectName:生成的 domain 类的名字,如果不设置,直接使用表名作为 domain 类的名字;可以设置为 somepck.domainName,那么会自动把 domainName 类再放到 somepck 包里面;
        5,enableInsert(默认 true):指定是否生成 insert 语句;
        6,enableSelectByPrimaryKey(默认 true):指定是否生成按照主键查询对象的语句(就是 getById 或 get);
        7,enableSelectByExample(默认 true):MyBatis3Simple 为 false,指定是否生成动态查询语句;
        8,enableUpdateByPrimaryKey(默认 true):指定是否生成按照主键修改对象的语句(即 update);
        9,enableDeleteByPrimaryKey(默认 true):指定是否生成按照主键删除对象的语句(即 delete);
        10,enableDeleteByExample(默认 true):MyBatis3Simple 为 false,指定是否生成动态删除语句;
        11,enableCountByExample(默认 true):MyBatis3Simple 为 false,指定是否生成动态查询总条数语句(用于分页的总条数查询);
        12,enableUpdateByExample(默认 true):MyBatis3Simple 为 false,指定是否生成动态修改语句(只修改对象中不为空的属性);
        13,modelType:参考 context 元素的 defaultModelType,相当于覆盖;
        14,delimitIdentifiers:参考 tableName 的解释,注意,默认的 delimitIdentifiers 是双引号,如果类似 MYSQL 这样的数据库,使用的是`(反引号,那么还需要设置 context 的 beginningDelimiter 和 endingDelimiter 属性)
        15,delimitAllColumns:设置是否所有生成的 SQL 中的列名都使用标识符引起来。默认为 false,delimitIdentifiers 参考 context 的属性

        注意,table 里面很多参数都是对 javaModelGenerator,context 等元素的默认属性的一个复写;
     -->
    <table tableName="userinfo" >

        <!-- 参考 javaModelGenerator 的 constructorBased 属性 -->
        <property name="constructorBased" value="false"/>

        <!-- 默认为 false,如果设置为 true,在生成的 SQL 中,table 名字不会加上 catalog 或 schema; -->
        <property name="ignoreQualifiersAtRuntime" value="false"/>

        <!-- 参考 javaModelGenerator 的 immutable 属性 -->
        <property name="immutable" value="false"/>

        <!-- 指定是否只生成 domain 类,如果设置为 true,只生成 domain 类,如果还配置了 sqlMapGenerator,那么在 mapper XML 文件中,只生成 resultMap 元素 -->
        <property name="modelOnly" value="false"/>

        <!-- 参考 javaModelGenerator 的 rootClass 属性
        <property name="rootClass" value=""/>
         -->

        <!-- 参考 javaClientGenerator 的  rootInterface 属性
        <property name="rootInterface" value=""/>
        -->

        <!-- 如果设置了 runtimeCatalog,那么在生成的 SQL 中,使用该指定的 catalog,而不是 table 元素上的 catalog
        <property name="runtimeCatalog" value=""/>
        -->

        <!-- 如果设置了 runtimeSchema,那么在生成的 SQL 中,使用该指定的 schema,而不是 table 元素上的 schema
        <property name="runtimeSchema" value=""/>
        -->

        <!-- 如果设置了 runtimeTableName,那么在生成的 SQL 中,使用该指定的 tablename,而不是 table 元素上的 tablename
        <property name="runtimeTableName" value=""/>
        -->

        <!-- 注意,该属性只针对 MyBatis3Simple 有用;
            如果选择的 runtime 是 MyBatis3Simple,那么会生成一个 SelectAll 方法,如果指定了 selectAllOrderByClause,那么会在该 SQL 中添加指定的这个 order 条件;
         -->
        <property name="selectAllOrderByClause" value="age desc,username asc"/>

        <!-- 如果设置为 true,生成的 model 类会直接使用 column 本身的名字,而不会再使用驼峰命名方法,比如 BORN_DATE,生成的属性名字就是 BORN_DATE, 而不会是 bornDate -->
        <property name="useActualColumnNames" value="false"/>


        <!-- generatedKey 用于生成生成主键的方法,
            如果设置了该元素,MBG 会在生成的<insert>元素中生成一条正确的<selectKey>元素,该元素可选
            column: 主键的列名;
            sqlStatement:要生成的 selectKey 语句,有以下可选项:
                Cloudscape: 相当于 selectKey 的 SQL 为: VALUES IDENTITY_VAL_LOCAL()
                DB2       : 相当于 selectKey 的 SQL 为: VALUES IDENTITY_VAL_LOCAL()
                DB2_MF    : 相当于 selectKey 的 SQL 为:SELECT IDENTITY_VAL_LOCAL() FROM SYSIBM.SYSDUMMY1
                Derby     : 相当于 selectKey 的 SQL 为:VALUES IDENTITY_VAL_LOCAL()
                HSQLDB    : 相当于 selectKey 的 SQL 为:CALL IDENTITY()
                Informix  : 相当于 selectKey 的 SQL 为:select dbinfo('sqlca.sqlerrd1') from systables where tabid=1
                MySql     : 相当于 selectKey 的 SQL 为:SELECT LAST_INSERT_ID()
                SqlServer : 相当于 selectKey 的 SQL 为:SELECT SCOPE_IDENTITY()
                SYBASE    : 相当于 selectKey 的 SQL 为:SELECT @@IDENTITY
                JDBC      : 相当于在生成的 insert 元素上添加 useGeneratedKeys="true"和 keyProperty 属性
        <generatedKey column="" sqlStatement=""/>
         -->

        <!--
            该元素会在根据表中列名计算对象属性名之前先重命名列名,非常适合用于表中的列都有公用的前缀字符串的时候,
            比如列名为:CUST_ID,CUST_NAME,CUST_EMAIL,CUST_ADDRESS 等;
            那么就可以设置 searchString 为"^CUST_",并使用空白替换,那么生成的 Customer 对象中的属性名称就不是
            custId,custName 等,而是先被替换为 ID,NAME,EMAIL, 然后变成属性:id,name,email;

            注意,MBG 是使用 java.util.regex.Matcher.replaceAll 来替换 searchString 和 replaceString 的,
            如果使用了 columnOverride 元素,该属性无效;

        <columnRenamingRule searchString="" replaceString=""/>
         -->

         <!-- 用来修改表中某个列的属性,MBG 会使用修改后的列来生成 domain 的属性;
            column: 要重新设置的列名;
            注意,一个 table 元素中可以有多个 columnOverride 元素哈~
          -->
         <columnOverride column="username">
            <!-- 使用 property 属性来指定列要生成的属性名称 -->
            <property name="property" value="userName"/>

            <!-- javaType 用于指定生成的 domain 的属性类型,使用类型的全限定名
            <property name="javaType" value=""/>
             -->

            <!-- jdbcType 用于指定该列的 JDBC 类型
            <property name="jdbcType" value=""/>
             -->

            <!-- typeHandler 用于指定该列使用到的 TypeHandler,如果要指定,配置类型处理器的全限定名
                注意,mybatis 中,不会生成到 mybatis-config.xml 中的 typeHandler
                只会生成类似:where id = #{id,jdbcType=BIGINT,typeHandler=com._520it.mybatis.MyTypeHandler}的参数描述
            <property name="jdbcType" value=""/>
            -->

            <!-- 参考 table 元素的 delimitAllColumns 配置,默认为 false
            <property name="delimitedColumnName" value=""/>
             -->
         </columnOverride>

         <!-- ignoreColumn 设置一个 MGB 忽略的列,如果设置了改列,那么在生成的 domain 中,生成的 SQL 中,都不会有该列出现
            column: 指定要忽略的列的名字;
            delimitedColumnName:参考 table 元素的 delimitAllColumns 配置,默认为 false

            注意,一个 table 元素中可以有多个 ignoreColumn 元素
         <ignoreColumn column="deptId" delimitedColumnName=""/>
         -->
    </table>
</context>
</generatorConfiguration>

reference


2014-08-27 mybatis , orm , mysql , java

电子书

最近文章

  • 使用 flexget 实现下载更新自动化 FlexGet 官网是这样描述自己的,媒体文件的多功能自动化工具。可以支持 torrents, nzbs, podcasts, comics, TV, movies, RSS, HTML, CSV, 等等作为输入。FlexGet 是 Python 编写的,所以如果想要实现更加复杂的功能,也可以自己写脚本来处理。
  • 自架的服务整理 这篇文章主要整理比较流行的可以自建的服务,按照功能分类,我并没有每一个服务都尝试,但基本上每个功能下都有一个服务在跑着。
  • 关于 BitTorrent 和 PT 你需要知道的一切 几个 bt 中经常见到的词汇 bt 其实是 BitTorrent 的缩写,后文为了描述简单统一简称为 bt.
  • NAS 上的音乐管理 NAS 上的文件已经有足够多的管理系统 了 12,而电影也有 Kodi, Emby, Plex 等等工具,图片同样 Chevereto,Lychee,电子书有 Calibre-web,但就是音乐管理工具没有找到一个比较合适的。 FileRun ↩ NextCloud ↩
  • 几个常见的 NAS 系统整理 看文章老有几个 NAS 系统被翻来覆去的提到,这里就一起看看 Wiki,看看有什么区别吧。