Intellijのgoogle-java-format plugin を外した.
本家はこちら
ちょっと思うところがあって、google-java-format plugin を外した。
このプラグインがあると、結構強制力が強くて、indent4 にしたいときにできなかったり、import文を変えたかったりしたときにできなかったりとか・・・あったので、外しました...
ただそれだけ...
https://plugins.jetbrains.com/plugin/8527-google-java-format
Java8の@FunctionalInterfaceを使う
本家はこちら
関数インターフェースのPredicateとかFunctionがあるのであんまり使わないけど、引数とか3つ以上のものはないのでつくる必要がある。
基本的に抽象メソッドを1つしかもっていなければOK。defaultメソッドはいくつもっていてもOKです。(ラムダ式のときに何を使うかわからなくなっちゃうからかなと)
@FunctionalInterface
interface SampleInterface {
boolean filter(String a);
}
こんな感じでカンタンに作れる
使うときはこんな感じでカンタンに使える。
SampleInterfacle sampleFilter = s -> "a".equals(s);
sampleFilter.filter("a");
なんかもうカンタン過ぎますね
ちなみに引数3つは、こんな感じ
@FunctionalInterface
interface SampleInterface {
boolean filter(String a, String b, String c);
}
SampleInterfacle sampleFilter = (s, t , u) -> "a".equals(s);
sampleFilter.filter("a","b","c");
こんな感じで使える。なんかもうカンタン過ぎますね。みんなもっと使いましょう!
Javaの関数インターフェース再入門
本家はこちら
Javaのよく使ってる関数インターフェース群をまとめようかとおもう。
現場ごとに説明のためのドキュメントを書くのがしんどくなってきたからというのが本音かも。
predicate
断言するって意味。戻り値はBoolean。 引数1つとって
Predicate<String> matchA = s -> s.matches(".*a.*"); // 'a'があればtrue
Predicate<String> matchB = s -> s.matches(".*b.*"); // 'b'があればtrue
Predicate<String> noA = matchA.negate(); // 'a'があったらfalse
// 合成
Predicate<String> ab = matchA.and(matchB); // 'a'と'b'があったらtrue
Predicate<String> ab = matchA.or(matchB); // 'a'または'b'があったらtrue
実行はtest(T)
でできる。カンタン。streamのfilterとかで使える。テストもカンタン。
matchA.test("a");
これで実行できる。
ちなみに2つ引数とることもできる
BiPredicate<String,String> matchAB = (s,t) -> s.matches(".*a.*") && t.matches(".*a.*");
suppplier
供給するって意味
引数なし、戻り値あり。引数ないけど、それ単体で何かが発生する。 なにかと組み合わせてデータ流す感じかな
Supplier<String> supplier = () -> {
SecureRandom random = new SecureRandom();
return String.valueOf(random.nextInt());
};
ランダムintを返却する
supplier.get()
consumer
消費するって意味。 実際に引数とって、そのあと処理する。戻り値なし。
下記のような感じ
Consumer<String> show = s -> System.out.println(s);
下記のように使う
s.accept("s");
2つ引数とることも可能
BiConsumer<String,Integer> biShow = (s,i) -> {
System.out.println(s);
System.out.println(i);
};
Function
機能として使える関数インターフェース
引数と戻り値を持てる。 引数2つまで持てるものもある。(BiFunction)
下記のように定義できる
Function<Integer,String> exchangeString = t -> String.valueOf(t);
BiFunction<Integer,Integer,String> biExchange = (t,u) -> String.valueOf(t + u);
下記のように使える
exchangeString.apply(1);
biExchange.apply(1,2);
springboot devtools のauto restart を疑似高速化する
きっかけ
springbootとintellijなどIDE使ってると、コードの補完はめちゃされるし、Javaって便利だなーとか先人の方たちありがとう!って気持ちでコード書いてるんですけど、コード変更時に変更内容がHotswapで反映されるならいいんですけど、そうじゃないとrestartがかかって、プロジェクトが少し大きくなってくると15秒くらいまたされるのでもっと短縮できないかなーって思いました。
やったこと
DIの対象になるクラスを全部遅延ロード(lazyload)してしまえばいいかと思い、それを実装してみました。 本番環境でやるのはリスキーなので、local環境のみで行うようにしています。
@Profile("local")
@Configuration
public class LazyInitBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
for (String beanName : beanFactory.getBeanDefinitionNames()) {
beanFactory.getBeanDefinition(beanName).setLazyInit(true);
}
}
}
これで15秒から5秒後半くらいになりました!最高
Started WebApplication in 14.565 seconds (JVM running for 16.236)
↓
Started WebApplication in 5.759 seconds (JVM running for 6.871)
リスク
初期化が遅らせているので、初期化順でなにかを行う処理を挟み込んでたりしたら影響がありますが、今日そんなコード書いてる人なんてあんまりいないだろうし、local環境だけなんでまぁ影響ないかなと。
spring-context-indexerと組み合わせているとちょっと動かないケースがあってハマることがあるので、オフにできるならオフにすること。 まだなんでかはわかってないです。
まとめ
これでサクサク開発できるので、しばらく試してみようかと思います
springboot devtools のauto restart を疑似高速化する
きっかけ
springbootとintellijなどIDE使ってると、コードの補完はめちゃされるし、Javaって便利だなーとか先人の方たちありがとう!って気持ちでコード書いてるんですけど、コード変更時に変更内容がHotswapで反映されるならいいんですけど、そうじゃないとrestartがかかって、プロジェクトが少し大きくなってくると15秒くらいまたされるのでもっと短縮できないかなーって思いました。
やったこと
DIの対象になるクラスを全部遅延ロード(lazyload)してしまえばいいかと思い、それを実装してみました。 本番環境でやるのはリスキーなので、local環境のみで行うようにしています。
@Profile("local")
@Configuration
public class LazyInitBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
for (String beanName : beanFactory.getBeanDefinitionNames()) {
beanFactory.getBeanDefinition(beanName).setLazyInit(true);
}
}
}
これで15秒から5秒後半くらいになりました!最高
Started WebApplication in 14.565 seconds (JVM running for 16.236)
↓
Started WebApplication in 5.759 seconds (JVM running for 6.871)
リスク
初期化が遅らせているので、初期化順でなにかを行う処理を挟み込んでたりしたら影響がありますが、今日そんなコード書いてる人なんてあんまりいないだろうし、local環境だけなんでまぁ影響ないかなと。
spring-context-indexerと組み合わせているとちょっと動かないケースがあってハマることがあるので、オフにできるならオフにすること。 まだなんでかはわかってないです。
まとめ
これでサクサク開発できるので、しばらく試してみようかと思います
mybatisでカスタムクエリをxmlで書くのは辛いので、freemarker templateにする
本家はこちら
mybatisでカスタムでクエリ書くときに、標準だとxml形式で書かなきゃいけなくて、結構しんどい。
カンタンに書くと下のような感じ
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="jp.sample.MapperCustom">
<delete id="deleteAll" parameterType="map">
delete from ${table}
</delete>
<insert id="bulkInsert" parameterType="map">
insert into ${table}
(code)
values
<foreach item="v" collection="list" separator=",">
(#{v})
</foreach>
</insert>
</mapper>
つらいポイント - xml形式なので、余計なものが先頭に来てつらい - 繰り返しがつらい
なんかたくさんあるかと思いきや、あんまり挙げられなかったのだが、とにかくXMLというのが辛い。不等号もxml形式なので、CDATA
を利用してかかないければならないのとか、そうしないなら、エスケープしないといけないのが辛かった。
Groovyとかkotlinだとmulti line strings が使用できる話だが、Groovyだと大きいJarを入れないとだし、kotlinだとnull値が。。。みたいな問題に悩まされるんじゃないかという気がしたので、mybatis freemarker template
を使う方法を選択した。
使い方
ライブラリの追加
gradleのdependencies
に下記を追加
compile("org.mybatis.scripting:mybatis-freemarker:$mybatisFreemakerVersion")
freemarkerテンプレートを置き場指定
src/main/resources 直下にmybatis-freemarker.properties
のファイルを設置する
内容は、mybatis-freemarkerを使う際にどのディレクトリを参照するかなので、classpath内の任意のディレクトリパスを記述する。
basePackage=mybatis/sql
freemarker templateにクエリを書く
src/main/resources/mybatis/sql/sample.ftl
select
name
from
sample
where
id in (${ids?join(", ")})
and
name = <@p name="n">
(${ids?join(", ")})
とか<@p name="n">
とかのfreemarker templateでかけるのは嬉しい。xml形式でない分可読性も高くなると思うし、使い勝手がよくなる。
mapperインターフェース内にfreemarker templateの呼び出しを書く
@Lang(FreeMarkerLanguageDriver.class)
@Select("sample.ftl")
List<Name> findNamesByIds(@Param("n") String name,@Param("ids") List<Integer> ids);
以上のように書けば、実行できる。なんかかなりスッキリしたよい感じになる。デメリットとしては、1
mybatisでカスタムクエリをxmlで書くのは辛いので、freemarker templateにする
本家はこちら
mybatisでカスタムでクエリ書くときに、標準だとxml形式で書かなきゃいけなくて、結構しんどい。
カンタンに書くと下のような感じ
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="jp.sample.MapperCustom">
<delete id="deleteAll" parameterType="map">
delete from ${table}
</delete>
<insert id="bulkInsert" parameterType="map">
insert into ${table}
(code)
values
<foreach item="v" collection="list" separator=",">
(#{v})
</foreach>
</insert>
</mapper>
つらいポイント - xml形式なので、余計なものが先頭に来てつらい - 繰り返しがつらい
なんかたくさんあるかと思いきや、あんまり挙げられなかったのだが、とにかくXMLというのが辛い。不等号もxml形式なので、CDATA
を利用してかかないければならないのとか、そうしないなら、エスケープしないといけないのが辛かった。
Groovyとかkotlinだとmulti line strings が使用できる話だが、Groovyだと大きいJarを入れないとだし、kotlinだとnull値が。。。みたいな問題に悩まされるんじゃないかという気がしたので、mybatis freemarker template
を使う方法を選択した。
使い方
ライブラリの追加
gradleのdependencies
に下記を追加
compile("org.mybatis.scripting:mybatis-freemarker:$mybatisFreemakerVersion")
freemarkerテンプレートを置き場指定
src/main/resources 直下にmybatis-freemarker.properties
のファイルを設置する
内容は、mybatis-freemarkerを使う際にどのディレクトリを参照するかなので、classpath内の任意のディレクトリパスを記述する。
basePackage=mybatis/sql
freemarker templateにクエリを書く
src/main/resources/mybatis/sql/sample.ftl
select
name
from
sample
where
id in (${ids?join(", ")})
and
name = <@p name="n">
mapperインターフェース内にfreemarker templateの呼び出しを書く
@Lang(FreeMarkerLanguageDriver.class)
@Select("sample.ftl")
List<Name> findNamesByIds(@Param("n") String name,@Param("ids") List<Integer> ids);
以上のように書けば、実行できる。なんかかなりスッキリしたよい感じになる。デメリットとしては、1SQLで1ファイル使うので結構ファイルの数は増える。ディレクトリ等を使えば、スッキリはすると思うので、大したデメリットにはならないと思う。