记账 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

H2 Database Engine

H2 is a Java SQL database, with following features:

  • fast, open source, JDBC API
  • Embedded and server modes; in-memory databases
  • Browser based console application
  • small footprint: around 1.5MB jar file size

连接方式

H2 数据库支持三种连接方式,三种模式都支持内存、持久化到文件,三种模式对同时开启的数据库数量和连接数没有限制。

嵌入式模式

本地 JDBC 连接,最方便的一种,嵌入式下,JVM 启动 H2 数据库通过 JDBC 连接。

服务器模式

通过 JDBC 或者 ODBC API 远程连接数据库,可以部署在不同的 JVM 或者不同的物理机中。数据通过 TCP/IP 协议传输,比嵌入式慢。

混合模式

第一个应用通过嵌入式打开 H2 数据库,同时数据库开启服务器模式,其他应用可以远程连接。

连接字符串

driver=org.h2.Driver
url=jdbc:h2:mem:testdb;MODE=MYSQL;DB_CLOSE_DELAY=-1
username=sa
password=

使用

控制台启动

java -jar h2*.jar

在 Spring 应用中 maven 配置

<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <version>1.x.xxx</version>
</dependency>

连接配置

driver=org.h2.Driver
url=jdbc:h2:mem:testdb;MODE=MYSQL;DB_CLOSE_DELAY=-1
username=sa
password=

reference


2014-07-28 h2 , database , in-memory-database , jdbc

国内各大音乐网站使用感受

最近几天在电脑上听歌,不由自主的在键盘上敲出了 http://music.163.com , 而在不久之前还是用 xiami.com 听歌呢,所以禁不住思考起来.

最初

最早用电脑听歌还是应该用的酷狗,酷我,多米之类的电脑端软件,那个时候经常是将歌曲下载到自己电脑上,伴随着清脆的一声”Hello kugou”,才开始听歌之旅的. 那个时候听的歌曲还往往是知道名字,知道歌手,很有针对性的去听的.那个时候的播放列表还往往是本地的自己的列表,如果换一台电脑那些列表还不一定能够同步过去.虽然后来酷狗,酷我都做了同步播放列表的功能,但是那时候的体验和感受都留在了那个时候.

后来

在大学的时候,渐渐的发现自己的播放曲库就那么几首歌,全部循环播放还是那么几首歌,所以萌生了寻找自己喜欢听的歌曲的想法,如果能有一个平台能够提供不间断播放的歌曲,能根据自己喜欢的歌曲推荐同样类似的歌曲,后来我找到了 douban.fm 这样一个平台,虽然我不知道豆瓣这个电台什么时候发布的,但它确实伴我走了多一段时间,也让我找到了很多喜欢的歌曲,我记得那时候听得最多的轻音乐电台,让我找到”班得瑞”这一系列的轻音乐.

再后来

可是用了一段时间的豆瓣 FM 就会发现出现了些问题,一是豆瓣 FM 不允许下载歌曲,虽然我的加心歌曲很多了,却一首也不允许我离线的播放.一旦离开了互联网,我就往往又回到了那几首歌的时候.这个时候如果在豆瓣 FM 找到了喜欢的歌再用酷狗,酷我,多米,百度之类的下载,也略显麻烦,况且如果喜欢的歌曲多了,还得一首一首的找并下载,这个过程太麻烦.二是我渐渐的发现有些我喜欢的歌从来不会在豆瓣 FM 中出现,并且豆瓣 FM 还经常出现某些人翻唱的歌曲.那个时候我就意识到是不是豆瓣 FM 的曲库并不是很完整,如果它本身的曲库就不是很完整,如何能推荐到那些缺失的好歌?

转到虾米

再后来就是转到了虾米,虽然知道虾米的曲库也并不是很全,但是至少感觉比豆瓣的要全一些,并且虾米至少还是一直是做音乐的嘛. 豆瓣转到虾米之后很长一段时间都是在用虾米电台在听歌,当然一些听歌习惯也留在了虾米.但后来移动大潮来临,那个时候虾米 Android 客户端还一直不错,至少在酷狗,酷我,百度等等客户端中还是值得一看和一用的.可是那个时候虾米的封闭就体现出来了.虾米因为下载需要类似积分的东西,所以在 Android 客户端中下载的音乐只有通过虾米客户端才能播放,虾米并不是直接以 mp3 保存的歌曲.那个时候还是并不是很在意这个问题,可是突然有一天我意识到,如果有一天虾米”倒闭”或者怎么样了呢?(⊙o⊙)… 那个时候开始我渐渐的将一些喜欢的歌曲下载到本地,那些歌曲列表也不怎么去贡献,只维护着自己喜欢的歌曲列表. 然后渐渐地将自己的听歌之路转到本地,那个时候还曾经找好用的PC 音乐管理软件很长一段时间.

转到网易云音乐

可是突然有一天网易发布了它自己的音乐播放网站和 Android 客户端,不愧是网易不鸣则已一鸣惊人,网易云音乐发布的时候就称自己跨平台,当然后来才慢慢发布了 PC 端和 Mac 端的软件,但是那个时候的 Android 应用一发布,我眼前就一亮,继承了网易新闻的操控性,美观性,并且功能强大.并且当时网易云音乐一发布曲库就很全面,我也不知道网易从哪里搞了这么多版权,总是他就是做到了. 于是开始试用最初还是觉得网易云音乐用来下载音乐很方便,成了 Android 手机上的音乐下载器,可是后来真的用了起来.有一天,我发现能导入虾米歌曲列表,能导入豆瓣 FM 加心歌曲,果断全部导入,自此以后虾米都很少打开了.

于是就出现了文章最前面出现的一幕.到现在总结下虾米和网易,虾米有一些小细节我很喜欢,但是已经不能抵挡我使用网易的大势了.不过那些小细节总结一下总还是可以提醒一下网易:

  1. 虾米能够记录所有听歌的记录,无论是哪里使用虾米,WEB 页面试听还是,在电台听的,还是在 Android 客户端听得,所有的记录都能在历史记录中看到.并且有一点和 Last.fm 相似的就是能统计出哪些歌手的歌播放了多少次,哪些歌曲播放了多少次,对于我这种没有特别钟爱谁的听众很有帮助,自动统计出了对谁谁谁的歌特别偏爱.
  2. 虾米电台是我觉得做得最好的电台了.各种各样的电台都有,如果喜欢一个歌星可以只听这个歌星的歌曲,而如果最近只喜欢轻音乐,可以只听轻音乐.
  3. 虾米能够将音乐生成嵌入式代码,在网页上共享,这点网易没有.像下面这样,

</embed>

总结

经过这一些系列的回忆,对于一个互联网产品,我总结出几点:

WEB 化

在网络渐渐发展到可以流畅在 WEB 页面听歌的时候,类似酷狗,酷我这样的播放软件便会走下坡路.虽然我不知道酷狗,酷我之类现在活得是否还好,但至少让我这样的用户离开了.如果能够在网页上直接能够听歌,为何还要下个客户端呢?WEB 是互联网的大潮.如果没有抓住这个大潮,可能就要吃亏了吧.虽然现在好像酷狗和酷我都已经可以在线播放了,可是我也已经不用了.没有什么特别理由,就是不好了吧.再其次酷狗,酷我根本没有我的播放习惯,随意就可以抛弃,换另外一个平台.这也就是我要谈的第二点—-账号系统.

账号系统

所有的音乐库应该跟随者用户,用户登陆账号即可获取到所有的歌曲库.这一点网易就很聪明,在网易刚刚发布 PC 客户端的时候,如果用户不登陆就不能使用.用户可以收藏喜欢的歌曲,新建歌曲列表,分享歌曲列表,这样网易就能学习用户的习惯,推送更多用户喜欢的歌曲.

跨平台

跨平台其实和第二点账号系统一样,账号应该跟随着用户走,对于一个产品应该是用户走到哪里,只要有个账户就能够轻易的获取到用户的所有资料,爱好,习惯.那当然,我用微软的 Windows 还好,还是用 Google 的 Android,还是 Apple 的 Mac,只要有用户在就要提供给用户获取自己产品的入口,当然网易 WEB 播放器是我见过的最好的.无论是从设计还是到操作性,都给人很亲切的感受.

UGC 用户贡献内容

当然虾米和网易都可以由用户生成音乐列表,而最近看到新闻说豆瓣 FM 也支持用户贡献音乐列表了.UGC 是 WEB2.0 的特征,虾米雇再多的虾小编生成的内容也不会有用户多.所以干脆直接把内容编辑交给用户得了.当然现在发现好歌的途径又多了一点,不仅可以听自己喜欢的电台,还能关注兴趣相投的好友,看他分享的音乐列表.这些列表里是用户整理好的好听歌曲,去循环播放去啦.

当然如果你没有使用过网易云音乐,那么就请你试试吧:http://music.163.com/,如果你觉得我的歌曲品味和你的相似,也同样欢迎你提供更好的音乐.


2014-07-20 music , knowledge , music-library , music-management , music-platform

适用于编程 Coding 的字体

之前的一篇文章就曾经提到字体的历史,这篇文章着重在推荐几款我个人认为非常适合编程这个环境的字体。

在选择一款字体之前,先要了解几个术语

  • monospace font 等宽字体,每一个字符宽度占用都是一样的
  • Sans-serif font 无衬线字体
  • Serif font 衬线字体
  • font weight 字重,字体的粗细程度,常见的字重有 Light, Regular, Medium, Bold 等等

在选择一款编程字体的时候我会考虑以下几个点:

  • 能否区分,数字 0 以及大小写 oO
  • 能否区分,数字 1 以及大写字母 I 以及小写字母 l
  • 个人喜欢等宽的字体,并且可以兼容终端,IDE 和各种操作系统

综合上面的考虑,我个人使用 Fira Code 作为终端,IntelliJ IDEA,VSCode 的编程字体已经很多年了。

另外 JetBrains 推出的 JetBrains Mono 字体也是一个不错的选择。

推荐一个盲测字体对比的网站

通过两两对比,最后选出你最喜欢的编程字体。

Azeret Mono

通过上面的对比,最后选择出来的我个人喜欢的字体。

Source Code Pro

Source Code Pro 是由 Adobe 公司设计的开源字体,使用很长一段时间的字体,中规中矩,字体很容易识别,非常适合日常编码使用。

source code pro

Noto Sans

Noto 字体是 Google 开发的一款开源字体,使用场景非常广泛的一个字体,当然用来做 Coding 也不是不行,不过也一样,比较中规中矩。

noto sans

Ubuntu Mono

又一个等宽字体,在 Ubuntu 上看久了 Ubuntu Mono ,真实对比一下其他字体之后发现 Ubuntu Mono 字体胖胖的,所以字间距看起来很舒服。

Inconsolata

DescriptionInconsolata is an open-source font created by Raph Levien and released under the SIL Open Font License. It is a humanist monospaced font designed for source code listing, terminal emulators, and similar uses.

inconsolata

Fira Code

个人使用的编程字体 Fira Code,用了很多年了。

为 Programming 设计的等宽字体。该字体为 Programming 做了非常多的特殊设计,比如大于等于,不等于等等。

这款字体区别与其他字体的另一个典型特点就是 @, &r 的区别。

fira code font

Nerd Fonts

Hasklig

Fantasque Sans Mono

更多编程字体预览:

  • https://coding-fonts.netlify.app/
  • https://www.programmingfonts.org/#pt
  • https://github.com/subframe7536/Maple-font
  • https://rubjo.github.io/victor-mono/
  • https://github.com/TakWolf/fusion-pixel-font
  • https://www.ibm.com/plex/
  • https://github.com/be5invis/Sarasa-Gothic

reference


2014-06-20 fonts , font , coding , programming , style

优化 SQL 语句

CHAR vs VARCHAR

在设计数据库字段时经常需要保存字符,MySQL 中有两个容易混淆的字段 CHAR 和 VARCHAR。

  • VARCHAR 是可变长度,仅使用必要的空间,需要额外使用 1 个或者 2 个字节来记录字符串长度,最大长度小于等于 255 字节,只需要额外使用一个字节,否则需要 2 个字节
  • CHAR 是固定长度,MySQL 在存储 CAHR 时会删除所有末尾空格,适合存储很短的字符串,或者所有值都接近同一个长度

VARCHAR(10) 需要 11 个字节存储空间,VARCHAR(1000) 列需要 1002 字节存储,2 个字节用来存储长度信息。

适用场景:

  • 字符串 COLUMN 的最大长度比平均长度大很多,列很少更新,不容易产生碎片
  • 如果预测到要保存的内容是固定长度,可以使用 CHAR,比如保存 MD5 值,保存性别代号等等;对于经常需要更新的数据 CHAR 也比 VARCHAR 更好,定长 CHAR 不容易产生碎片

与 CHAR 和 VARCHAR 类似的类型还有 BINARY 和 VARBINARY,存储的是二进制字符串。二进制字符串存储的是字节码而不是字符,填充也不一样,MySQL 填充 BINARY 采用的是 \0 零字节,而不是空格,检索时也不会去掉填充值。

当存储二进制,并且希望 MySQL 使用字节码而不是字符进行比较时,这些类型比较有用。MySQL 比较 BINARY 字符串时,每次按一个字节,并且根据该字节的数值比较。因此,二进制比较比字符比较简单很多,也就更快。

合并语句

把对同一个表的修改合并为一个 alter 语句,避免多次拷贝,提高改表效率

合并

altertable t1 addcolumn a int;
altertable t1 addcolumn b int;

合并后

altertable t1 addcolumn a int, add column b int;

更新语句

执行更新语句时尽量将同一张表的内容合并到一行。

UPDATE tablename SET column1 = "value1", column2 = "value2" ....

主键

自增主键设置为 unsigned 类型, MySQL 表只能有一个主键,但是可以有多个唯一键,可以尝试将自增 ID 作为主键,实际有意义的字段作为唯一键。

冗余索引

假如有 idx1(a,b) 和 idx2(a) 时,idx2 是没有必要的,当查询语句是 where a=xx 时会使用 idx1


2014-06-04 mysql , sql , optimize , slow-query , database

毕设相关

##Word目录自动生成 如果想要目录自动生成,就必须事先对文章标题进行格式化,我使用的方式是在大纲视图中对章节标题进行一级二级三级格式化。另外的方法是通过格式中标题去给每一个标题添加样式。网上的教程太多了,我就做一个备忘吧,以后说不定在其他论文中也要生成目录。在格式化标题之后,导航窗口基本上就能显示一个简单的目录了,此时再自动生成目录一般不会出现太大的问题。

##Word页眉页脚 有些页需要重新从1页开始编号,则要在该页之前插入分节符。如需生成第1页 共XX页这种格式的页码,最好不要手工输入总共的页码,因为可能需要修改论文内容,而如果手工修改可能最后不会自动更新,会造成很大的问题。最好是在文档部件->域->编号里面插入总页数。

##MP4转gif 项目因为在Android手机上,需要录制视频展示,Android(API level 19) 开发工具中提供了录制视频的方法:

adb shell screenrecord /sdcard/demo.mp4

在PC下连接手机,运行以上命令即可录制手机屏幕,视频格式为MP4,存放在手机SD卡,默认录制时间180s. 该命令还有其他一些参数,运行:

adb shell screenrecord --help

可以查看所有参数。几个可能会使用到的参数是:

  • --time-limit 10 录制时长
  • --size 1280*720 录制分辨率大小
  • --bit-rate 6000000 比特率

官方文档: http://developer.android.com/tools/help/adb.html#screenrecord 中文参考: http://blog.csdn.net/wirelessqa/article/details/22725581

录制完视频之后面临的一个问题是,怎么转成gif供PPT或者演示使用。最初想到的方法是使用Photoshop,也找到了一些方法能够将MP4视频转成Web使用gif,但是因为Photoshop将视频每一帧都保存,消耗内存太大,之后适当的调整了几次效果都不是很好,生成的文件也比较大。所以后来就直接使用了迅雷看看的gif生成了,不过缺点很明显,分辨率被调到很小,图像变得不清晰了。


2014-05-31 skills

每天学习一个命令:dd 读取转换输出数据

dd 命令可以复制文件并对原文件内容进行转换和格式处理。dd 命令经常被用来备份设备。

比如创建一个空文件:

dd if=/dev/zero of=test.txt bs=1M count=1

解释:

  • if 输入文件,不指定从 stdin
  • of 输出文件,不指定默认 stdout 作为默认输出
  • bs 字节为单位的块大小
  • count 表示被复制的块

几个设备:

  • /dev/null 向其输入任何内容都会被吞掉
  • /dev/zero 输入设备,用来初始化文件,提供无穷的 0.

使用实例

注意: 运行 dd 命令需要非常小心,如下命令如果不清楚其含义请千万不要轻易尝试。

测试硬盘读写速度

可以使用如下的命令来测试磁盘的读写速度:

dd if=/dev/zero bs=1024 count=1 of=/tmp/test.file
dd if=/dev/zero bs=1G count=1 of=/tmp/1Gb.file

说明:

  • if input file
  • of output file
  • bs block size 表示同时读入/输出的块大小
  • count number of blocks ,拷贝的块个数
  • oflag synchronization I/O for data

最后读写的文件大小是 bs 乘以 count 数。

备份整块磁盘

将整块磁盘 /dev/sda 备份到 /dev/sdb,注意 sdb 上的数据将会被覆盖!!!

dd if=/dev/sda of=/dev/sdb bs=4M

创建空文件

创建一个 512M 大小的空文件

dd if=/dev/zero of=/path/to/file count=1024 bs=500000

销毁磁盘数据

利用随机数据填充磁盘,用以销毁数据

dd if=/dev/urandom of=/dev/sda1

全盘数据备份与恢复

备份

dd if=/dev/sda of=/root/sda.img

恢复镜像到指定盘

dd if=/root/sda.img of=/dev/sda

使用 gzip 压缩备份

dd if=/dev/sda | gzip > /root/image.gz

将压缩文件恢复

gzip -dc /root/image.gz | dd of=/dev/sda

对比

dd bs=64k count=4k if=/dev/zero of=test
dd bs=64k count=4k if=/dev/zero of=test; sync
dd bs=64k count=4k if=/dev/zero of=test conv=fdatasync
dd bs=64k count=4k if=/dev/zero of=test oflag=dsync

dd 命令的区别在于写缓存的处理方式。

  • 第一条,不包括 sync,dd 命令完成之前并没有让系统把文件写入磁盘,只是把数据读入内存缓存中。dd 命令完成之后系统才会往磁盘写数据,所以这个速度不是真实速度
  • 第二条,使用独立的 sync 命令,但是在 sync 命令执行之前 dd 就已经把速度打印出来了,所以也不是真正的速度
  • 第三条命令使用 conv=fdatasync 执行之后,会执行一次同步操作
  • 第四条命令 oflag=dsync 在执行每次都会进行同步写入操作,这是最慢的一种很是,基本没有用到写缓存

2014-05-26 dd , linux , command

电子书

本站提供服务

最近文章

  • Glance 个人自定义 Dashboard Glance 是一个可以自行架设的个人 Dashboard 以及 RSS 订阅信息面板。
  • Fileball 一款 iOS tvOS 上的媒体播放器及文件管理器 Fileball 是一款 iOS,tvOS 上的本地文件管理器,本地音乐播放器,本地视频播放器,以及文本编辑器,Fileball 可以在 iPhone,iPad,Apple TV 上使用。Fileball 可以连接网络共享,支持 SMB,FTP,SFTP,Synology,NFS,WebDAV 等,支持 Emby,Jellyfin 等,还可以连接百度网盘,Box,Dropbox,Google Drive,OneDrive,pCloud 等,可以作为 [[Infuse]] ,[[VidHub]] 等播放器的平替,高级版本价格也比较合适。Fileball 也支持 [[IPTV]]。
  • 在日本申请入台证材料及在线提交注意事项 本文记录入台证办理的材料及提交手续,以及在使用线上提交系统的时候需要注意的点。入台证是中华民国台湾地区出入境许可证的俗称,所有进入台湾的人都需要申请此许可证。
  • 从 Buffer 消费图学习 CCPM 项目管理方法 CCPM(Critical Chain Project Management)中文叫做关键链项目管理方法,是 Eliyahu M. Goldratt 在其著作 Critical Chain 中踢出来的项目管理方法,它侧重于项目执行所需要的资源,通过识别和管理项目关键链的方法来有效的监控项目工期,以及提高项目交付率。
  • AI Shell 让 AI 在命令行下提供 Shell 命令 AI Shell 是一款在命令行下的 AI 自动补全工具,当你想要实现一个功能,敲一大段命令又记不住的时候,使用自然语言让 AI 给你生成一个可执行的命令,然后确认之后执行。