小不的笔记

时间之外的往事

eclipse必备插件

通用

Properties Editor properties文件编辑器,可以自动的转换中文为properties文件支持的 unicode 编码。 https://marketplace.eclipse.org/content/properties-editor Path Tools 可以方便的复制项目文件路径。还顺带在文件管理器中打开,在命令行中打开,在外部编辑器打开,自定义命令等一系列功能。 http://marketplace.eclipse.org/content/path-tools Java Source Attacher 一键为开源 jar 包附加源码。 https://marketplace.eclipse.org/content/java-source-attacher Eclipse Jetty 开发环境替换 tomcat,Maven 项目必备,标准 eclipse 项目也可以用。终于可以远离 tomcat 的双 clean问题。 https://marketplace.eclipse.org/content/eclipse-jetty

macOS only

OS X Eclipse Launcher 可以在 macOS 下启动多个 eclipse。可以使eclipse 在不同的 workspace 下自由切换。 http://marketplace.eclipse.org/content/osx-eclipse-launcher

OS X 找回SourceTree gitflow 按钮

SourceTree 2.2.2,界面简约明快,但也把我最常用的 Git Flow 工具栏按钮简约掉了。 Git Flow 功能还在,只不过默认是隐藏的。 1. 右击工具栏空白处,在弹出的菜单内选择『Customize Toolbar..』。 2. 把 「Git Flow」按钮拖至工具栏,就可以了。 menu drag

String.replaceAll 反斜杠StringIndexOutOfBoundsException String index out of range

尝试使用String.replaceAll把斜杠(/)替换成反斜杠()时,一直抛StringIndexOutOfBoundsException异常。 后来意识到写法错误,原代码如下:”xobo/org”.replaceAll(“/“, “\“) 正确的写法是: “xobo/org”.replaceAll(“/“, Matcher.quoteReplacement(“\“)) 等价的写法是:”xobo/org”.replaceAll(“/“, “\\“) Java字符串”\\“组成了一个正则表达式”\“,而正则表达式”\“代表着纯文本””。 所以四个反斜杠才能真正表达一个反斜杆的含义。 java.util.regex.Matcher.quoteReplacement(String) 这个方法就是专门消除””及”$”特殊含义的方法。 在使用String.replace的时候就没这个烦恼,两个就好了”\“,因为在replace方法内对replacement参数调用了Matcher.quoteReplacement方法。

NoClassDefFoundError:org.apache.juli.logging.LogFactory Jetty

使用Jetty启动项目的时候会报NoClassDefFoundError:org.apache.juli.logging.LogFactory异常,而Tomcat可以正常启动,这种情况是因为tomcat的包配置不正确引起的 移除掉tomcat的Library就可以了 具体步骤: 右键项目 -> Build Path -> Configure Build Path… -> Libraries 移除掉tomcat。 ![移除Apache Tomcat Library](http://7xj1gb.com1.z0.glb.clouddn.com/remove library.png) 参考自:http://www.oschina.net/question/170972_218538

OS X Yosemite IMAP邮箱迁移小记

操作系统:Yosemite 10.10.3 邮件客户端:系统自带的Mail Version 8.2 (2098) 配置好所有的邮件帐号,在Mail里,选中任一Mailboxes里选中邮件都可以随意的Move To或者Copy To其它Mailboxes。 如果想迁移邮件的话,只需要把旧的邮箱里的邮件Copy To新邮箱的对应位置就好了。Mail客户端会通过IMAP协议自动的把邮件上传到新的邮件服务器。Nice & Easy。 注意事项: 千万不要直接把旧帐号直接改成新帐号。 千万不要直接把旧帐号直接改成新帐号。 千万不要直接把旧帐号直接改成新帐号。 我就是这么干的,Mail愉快地把我旧账号的千余封邮件删除了然后换成了新账号的的几封邮件。 如果你也这么干了,用Time Machine恢复 ~/Library/Mail 目录就可以了。

Deprecated 过时的 MySQL5InnoDBDialect

什么是Hibernate方言?

Hibernate方言是用来告诉Hibernte如何对指定的数据库生成相应的SQL语句。 尽管做了很多尝试去使SQL语句标准化,但是不同的数据库支持的SQL语句还是有很多不同的地方。 所以Hibernate使用方言来辅助生成正确的SQL语句。

MySQL5Dialect与MySQL5InnoDBDialect有什么区别?

他们最大的区别是,在使用Hibernate创建表时MySQL5InnoDBDialect会在生成的建表SQL语句最后加上”ENGINE=InnoDB”。 InnoDB是一种MySQL数据库引擎.MySQL5.5及之后使用它做为默认引擎。它提供了ACID兼容的事务(Transaction)功能,并提供外键支持。

MySQLDialect与MySQL5Dialect有什么区别?

MySQLDialect是针对MySQL5之前的版本。主要变化还是在于建表SQL语句。 MySQL由于4到5还是有不小的变化。比如varchar在4及之前版本最大长度限制为255,5及之后版本最大长度限制为65535。 MySQLInnoDBDialect会在生成的建表SQL语句最后加上”TYPE=InnoDB”。

MySQL5InnoDBDialect过时了

升级到 Hibernate 5 的时候,就会发现 MySQL5InnoDBDialect,被标注@Deprecated也就是过时了。不仅仅是 MySQL5InnoDBDialect 过时了,所有带InnoDB的 Dialect 都被标注过时了@Deprecated;在标注有 InnoDBDialect 过时的同时 新加了 MySQL55Dialect 及 MySQL57Dialect。 如果查看源码就会发现 MySQL55Dialect 与 MySQL5InnoDBDialect 源码一模一样。 毕竟 MySQL 从 5.5 开始就默认使用 InnoDB 引擎,MySQL 8 已经移除了 MyISAM 引擎。Hibernate 的作者认为Dialect分为两类就没有什么必要了。

1
2
org.hibernate.dialect.MySQL55Dialect
org.hibernate.dialect.MySQL57Dialect

后记

Hibernate 作者最坑的地方是标注了@Deprecated之时,补了一个注释“Use “hibernate.dialect.storage_engine=innodb” environment variable or JVM system property instead.”,导致我以为是通过配置的方式来指定引擎。我在 Spring Boot 中各种拼配置都没成功,后来发现这个配置是要写在 classpath 下的 hibernate.properties 内。

COUNT()的作用

COUNT()是一个特殊的函数, 有两种非常不同的作用: 它可以统计某个列值的数量,也可以统计行数。 在统计列值时要求列值是非空的(不统计NULL)。 如果在COUNT()的括号中指定了列或者列的表达式, 则统计的就是这个表达式有值的结果数。 因为很多人对NULL理解有可题, 所以这里很容易产生误解。 如果想了解更多关于SQL语句中 NULL 的含义, 建议阅读一些关于SQL语句基础的书籍. (关于这个话题, 互联网上的一些信息息是不够精确的。) COUNT()的另一个作用是统计结果集的行数。当MySQL确认括号内的表达式值不可能为空时,实际上就是在统计行数. 最简单的就是当我们使用COUNT(*)的时候,这种情况下通配符*并不会像我们猜想的另那样扩展成所有的列, 实际上它会忽略所有的列而直接统计所有的行数。 我们发现一个最常见的错误就是, 在括号内指定了一个列却希望统计结果集的行数。 如果希望知道的是结果集的行数, 最好使用 COUNT(*),这样写意义清晰,性能也会很好。 摘自 《高性能MYSQL》第三版 6.7.1 优化COUNT()查询。

使用PreparedStatement插入Date类型数据

使用PreparedStatement插入Date类型数据

  1. 类型转换

    java.util.Date nowDate = new java.util.Date(); // Thu Sep 25 00:05:22 CST 2014
    java.sql.Time time = new java.sql.Time(nowDate.getTime()); // 00:05:22
    java.sql.Date date = new java.sql.Date(nowDate.getTime()); // 2014-09-25
    java.sql.Timestamp timestamp = new java.sql.Timestamp(nowDate.getTime()); //2014-09-25 00:05:22.913

  2. 类型关系

PreparedStatement提供了三种日期类型对应JDBC中的三种日期类型(TIME, DATE,TIMESTAMP):

  • java.sql.Time 只保存时间;时分秒,没有任何日期信息。
  • java.sql.Date 只保存日期;年月日,没有任何时间信息。
  • java.sql.Timestamp 保存日期及时间;日期+时间+微秒
    1. 所有的日期都可以通过毫秒(从1970.1.1 0h0m0s已经过去的毫秒数)来构造, 如:

      • Timestamp timestamp = new java.sql.Timestamp((new java.util.Date()).getTime());
    2. 都继承自java.util.Date;

    3. 虽然java.util.Date也保存时期及时间但是没有保存微秒(nanosecond)​。

Hibernate dynamic-update dynamic-insert 作用及影响

dynamic-update 可选 默认false UPDATE SQL会在运行时生成且只包括值发生变化的列

dynamic-insert 可选 默认false INSERT SQL会在运行时生成且只包括值不为null的列1

配置方式:

Hibernate3:

@org.hibernate.annotations.Entity(
dynamicUpdate = true,
dynamicInsert = true
)

Hibernate4:

@DynamicUpdate(value=true)
@DynamicInsert(value=true)

性能影响:

Hibernate会为每一个entity缓存它的INSERT/SELECT/UPDATE SQL语句。这样我们在保存、查找、更新entity时,不需要再去动态的计算这些SQL。

然而,当我们使用dynamic-insert、dynamic-update时, Hibernate都要重新计算一次相应的SQL语句,在Hibernate层面会有性能损耗。

所以我们需要在数据库及Hibernate的开销上做权衡。

在我看来,只有表中有庞大的blog列或者有超多的列,dynamic insert、 dynamic update才有意义;否则我不认为它们会带来性能提升。2

使用效果

仅仅提供使用效果,但我不认同其作者对性能影响的评价。

Dynamic-insert

Dynamic-update

  1. http://docs.jboss.org/hibernate/orm/3.6/reference/en-US/html/mapping.html
  2. http://stackoverflow.com/questions/3404630/hibernate-dynamic-update-dynamic-insert-performance-effects