20211015のJavaに関する記事は7件です。

[java tips] lombok @Builderを使ったクラスでもjson fixtureを使いたい

前提 Java Spring boot Jacksonを利用してobject <-> json変換 junitで単体テストを書く lombokを利用している 概要 Javaでunittestを書くとき、テストで使うデータを用意するのはわりとめんどくさい。 var hoge = new Hoge("hogeId", "hogeName", new Fuga("fugaId", "fugaName", ...)); というわけで、一般的には外部にjsonファイルを用意し、これを読み込ませてテストに使う。 hoge.json { "id": "hogeId", "name": "hogeName", "fuga": { "id": "fugaId", "name": "fugaName", ... } } しかし、一部のオブジェクト(たとえばドメインモデル)は「不変オブジェクト(immutable object)」にしないといけない。そういうコーディングルールはよくある。 @Builder @Getter public class Hoge { private final String id; private final String name; private final Fuga fuga; } これをObjectMapperを使って読み込むことができるか? 実装 もちろん可能。 @JsonDeserialize(builder=Hoge.HogeBuilder.class) @Builder @Getter public class Hoge { private final String id; private final String name; private final Fuga fuga; @JsonPOJOBuilder(withPrefix="") public static class HogeBuilder {} } これで、 @Test public void testHoge() throws IOException { var fixture = getClass().getResource("./hoge.json"); var hoge = mapper.readValue(fixture, Hoge.class); ... } いつも通りjson fixtureを使ったテストができる。 参照 テストのためにモデルにアノテーションを付与することがコーディングルール上許されるか?の問題は残るが・・・。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Java初心者が簡単な性格診断アプリを作る

はじめに 職業訓練校5か月目、授業内容はC言語を使った組み込みから、Java言語での開発に移り変わりました。 今回は授業で制作した性格診断アプリを紹介していきます。 なお、作成するにあたってこちらのサイト様を参考にさせて頂きました。 チェックボックスのチェック状態を設定, 取得する 完成品がこちら 授業で作った画面遷移を使った性格診断アプリ pic.twitter.com/wgbK13sMRy— バキオ (@Bakio202076) September 12, 2021 かいつまんで説明すると、チェック一つでカウンターが(いい人度)プラス1されていき、診断開始ボタンを押すと何個チェックしたか(いい人度)結果が表示されるようになっています。 開発環境 Windows10 AndroidStudio(Java言語) プログラム MainActivity package com.example.diagnosis; import androidx.appcompat.app.AppCompatActivity; import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.CheckBox; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void bt_Start(View view) { int cnt = 0; CheckBox checkBox; boolean isChecked; Intent intent = new Intent(MainActivity.this, SubActivity.class); checkBox = (CheckBox) findViewById(R.id.cd1);//チェックボックス1を取得 isChecked = checkBox.isChecked();//チェックボックスにペケが入っていたらisCheckedにtrue if(isChecked){ cnt++;//画面遷移後に表示する数値 checkBox.setChecked(false);//チェックボックスのペケを外し初期化する } checkBox = (CheckBox) findViewById(R.id.cd2); isChecked = checkBox.isChecked(); if(isChecked){ cnt++; checkBox.setChecked(false); } checkBox = (CheckBox) findViewById(R.id.cd3); isChecked = checkBox.isChecked(); if(isChecked){ cnt++; checkBox.setChecked(false); } checkBox = (CheckBox) findViewById(R.id.cd4); isChecked = checkBox.isChecked(); if(isChecked){ cnt++; checkBox.setChecked(false); } checkBox = (CheckBox) findViewById(R.id.cd5); isChecked = checkBox.isChecked(); if(isChecked){ cnt++; checkBox.setChecked(false); } checkBox = (CheckBox) findViewById(R.id.cd6); isChecked = checkBox.isChecked(); if(isChecked){ cnt++; checkBox.setChecked(false); } checkBox = (CheckBox) findViewById(R.id.cd7); isChecked = checkBox.isChecked(); if(isChecked){ cnt++; checkBox.setChecked(false); } checkBox = (CheckBox) findViewById(R.id.cd8); isChecked = checkBox.isChecked(); if(isChecked){ cnt++; checkBox.setChecked(false); } checkBox = (CheckBox) findViewById(R.id.cd9); isChecked = checkBox.isChecked(); if(isChecked){ cnt++; checkBox.setChecked(false); } checkBox = (CheckBox) findViewById(R.id.cd10); isChecked = checkBox.isChecked(); if(isChecked){ cnt++; checkBox.setChecked(false); } intent.putExtra("point" , cnt); cnt = 0;//intentにcntは渡したので初期化 startActivity(intent); } } SubActivity package com.example.diagnosis; import androidx.appcompat.app.AppCompatActivity; import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.TextView; public class SubActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_sub); Intent intent = getIntent(); int point = intent.getIntExtra("point" , -1); TextView textView = (TextView) this.findViewById(R.id.subText); textView.setText(point * 10 + "%"); } public void bt_End(View view){ finish(); } } さいごに 画面遷移、これを使うとぐっとアプリらしくなる。 チェックボックス、ラジオボタン、etc...どのボタンを使えば使いやすいアプリになるか、そのあたりも初期の段階で考えないといけないと思いました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Java - How to Set Difference Configuration Files for Log4j2

import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.core.LoggerContext; if (env.equals("DEV")) { setLog4j2ConfigFile("log4j2-dev.xml"); } private void setLog4j2ConfigFile(String log4j2ConfigFile) throws URISyntaxException { LoggerContext context = (LoggerContext) LogManager.getContext(false); context.setConfigLocation(getClass().getResource(log4j2ConfigFile).toURI()); }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

SpringBootの始め方

はじめに 普段Javaのエンジニアですが、らしいことを全然かけてないなと思い。SpringBootでAPIを作るまでの簡単な流れを記事にしてみようと思いました。 やり方はこの方法でなくてもあると思いますので一例としてみていただければと思います。 前提 eclipseはすでに持っていることを前提としているため必要な方はeclipseを取得してから後続の作業を行ってください。 https://mergedoc.osdn.jp/ spring initializr 以下のリンクからspring initializrを開いて諸々記載が終わったら「GENERATE」ボタンを押してください。 https://start.spring.io/ 特に何を作るという目的もないので、buildツールをGradleにだけ変えています。 パッケージ名やJavaのバージョン等にこだわりがあればそこは適宜読み替えていただければと思います。 「GENERATE」ボタンを押すとzipがダウンロードできると思いますのでよき場所にダウンロードしたzipを解凍しておいてください。 Eclipseでのインポート インポートリンクを押下 人によってこのあたりの表示は違うと思いますが、プロジェクトのインポートを押してください。 Gradleから既存のGradleプロジェクトを選択 ダウンロードしたファイルを参照して「完了」 これでプロジェクトのインポートが終わります。 Gradleの設定を修正 build.gradleにAPIとして実行可能となるようにorg.springframework.boot:spring-boot-starter-webを追加します build.gradle plugins { id 'org.springframework.boot' version '2.5.5' id 'io.spring.dependency-management' version '1.0.11.RELEASE' id 'java' } group = 'com.example' version = '0.0.1-SNAPSHOT' sourceCompatibility = '11' repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter' // RestControllerを使えるようにするために追加 implementation 'org.springframework.boot:spring-boot-starter-web' testImplementation 'org.springframework.boot:spring-boot-starter-test' } test { useJUnitPlatform() } コントローラーを作成 下記の通りコントローラを作成する パッケージは適当にcom.example.demo.app.controllerとしました。 TestController.java package com.example.demo.app.controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class TestController { @GetMapping("/test") public String test() { return "Hello World"; } } 起動 プロジェクトで右クリック 実行にカーソルを合わせ「Spring Boot アプリケーション」を押下 コンソールを確認 起動が成功していたら下記のようにコンソールが表示されます。 APIを確認 下記にアクセスしてみてください。 http://localhost:8080/test 無事にAPIが呼べていることが確認できました。 終わりに SpringBootを始めるのは難しいイメージがあるかもしれませんが、意外と簡単です。 是非是非導入を検討してみてはどうでしょうか?
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Couchbase Lite機能解説:クエリ① 概要、インデックス、SELECT句

概要 Couchbase Liteは、例1に示されている形式のクエリを使用します。 例1.クエリ形式 SELECT ____ FROM 'database' WHERE ____, JOIN ____ GROUP BY ____ ORDER BY ____ SQL経験者には不要でしょうが、それぞれのキーワードの解説は以下の通りです。 SELECTステートメントが結果セットに返されるドキュメントプロパティを指定します FROMは、ドキュメントを照会するデータベースを指定します WHEREステートメントはクエリ基準を指定します。 クエリ基準に一致するドキュメントの SELECTされたプロパティが結果セットに返されます JOINステートメントは、複数のドキュメントを結合するための基準を指定します GROUP BYステートメントは、結果セット内の返されたアイテムをグループ化するために使用される基準を指定します ORDER BYステートメントは、結果セット内のアイテムの順序付けに使用される基準を指定します このように、クエリ形式の構造とセマンティクスは、SQLに基づきます。さらに、上記には含まれていませんが、JSONデータの操作に関係する部分では、Couchbase ServerのN1QLクエリ言語に基づいています。 ただし、モバイルアプリケーションという性格上、クエリは文字列で表現するのではなく、オブジェクトとして構築します。 クエリの構築には、ビルダークラス(QueryBuilder)を使用します。 一般に、クエリが文字列として扱われる場合には、文字列を解析して実行するための機能を持つか、プログラミング言語のコンパイラーがソースコードを解析する前に、クエリ文字列をプログラム言語に書き換える(プリコンパイルする)必要があります。モバイルアプリが前者の機能をカバーすることは、フットプリント(アプリのサイズ)を考えると不適切であることがわかります。後者の機能は、提供されていません。 Couchbase Lite 2.0のクエリインターフェイスには、以下の機能が含まれています パターンマッチング 正規表現マッチング 数学関数 文字列操作関数 集計関数 グループ化 結合(単一のデータベース内) 並べ替え NilOrMissing(未定義値)プロパティ インデックス作成 ドキュメントのクエリを開始する前に、クエリインデックスを持つことの重要性について説明します。 クエリは、調査するドキュメントのセットを絞り込むために検索できる既存のデータベースインデックスがある場合に高速になります。インデックスの作成方法を示す例2を参照してください。 例2.新しいインデックスの作成 この例では、示されているデータ形式のプロパティtypeとnameプロパティの新しいインデックスを作成します。 データ形式 [ { "id": "hotel123", "type": "hotel", "name": "Hotel Ghia" }, { "id": "hotel456", "type": "hotel", "name": "Hotel Deluxe", } ] インデックスを作成するコード database.createIndex( "TypeNameIndex", IndexBuilder.valueIndex( ValueIndexItem.property("type"), ValueIndexItem.property("name"))); ドキュメントが更新されるたびにすべてのインデックスを更新する必要があるため、インデックスが多すぎるとデータ更新時のパフォーマンスが低下する可能性があります。 したがって、アプリケーションのパフォーマンスのバランスを取るために、適切なインデックスを設計・作成することが重要です。 SELECTステートメント SELECTステートメントを使用して、クエリされたドキュメントから返すプロパティを指定します。ドキュメント全体を取得するか、必要な特定のプロパティのみを取得するかを選択できます。 すべてのプロパティを返す このSelectResult.all()メソッドを使用して、選択したドキュメントのすべてのプロパティを返します。 例3を参照してください。 例3.SELECTを使用してすべてのプロパティを取得する このクエリは、データベース内(の特定の種類のドキュメント)からすべてのプロパティを取得する方法を示しています。 Query query = QueryBuilder .select(SelectResult.all()) .from(DataSource.database(database)) .where(Expression.property("type").equalTo(Expression.string("hotel"))); query.executeステートメントは、結果をディクショナリとして返します。キーはデータベース名です。例4を参照してください。 例4.SelectResult.all()が返すデータ形式の例 [ { "travel-sample": { "callsign": "MILE-AIR", "country": "United States", "iata": "Q5", "icao": "MLA", "id": 10, "name": "40-Mile Air", "type": "airline" } }, { "travel-sample": { "callsign": "ALASKAN-AIR", "country": "United States", "iata": "AA", "icao": "AAA", "id": 10, "name": "Alaskan Airways", "type": "airline" } } ] 選択したプロパティを返す 特定のプロパティのみにアクセスするには、クエリのselectステートメントで、プロパティごとに1つずつ、カンマで区切られたアイテム(SelectResult.property("<プロパティ名>"))のリストを指定します。 例5を参照してください。 例5.SELECTを使用して特定のプロパティを取得する このクエリは、データベース内(の特定の種類のドキュメント)から特定のプロパティを取得する方法を示しています。 Query query = QueryBuilder.select( SelectResult.property("id"), SelectResult.property("type"), SelectResult.property("name")) .from(DataSource.database(database)) .where(Expression.property("type").equalTo(Expression.string("hotel"))); 上記のqueryオブジェクトを用いたquery.execute()コールは、プロパティ名をキーとして、SelectResult式ごとに1つずつ、キーと値のペアを返します。例6を参照してください。 例6.結果形式の選択 [ { "id": "hotel123", "type": "hotel", "name": "Hotel Ghia" }, { "id": "hotel456", "type": "hotel", "name": "Hotel Deluxe", } ] 参考情報
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【SpringBoot】NamedParameterJdbcTemplateで実行されるSQL文をログ出力する

備考(※読み飛ばし推奨) 業務で役立ったので備忘録として残すことにした。 log4jdbcで実装すべきだが、Gradle(Maven)を書き換えるのが面倒な人向け。 NamedParameterではないJdbcTemplate使用時はString.replaceFirstで?を置換すればいけそうな気がするが、パラメータの順番担保はどうなるのか未確認。log4jdbcを使うべき。 サンプルコード package sample.repository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Repository; import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.jdbc.core.namedparam.SqlParameterSource; import org.springframework.beans.factory.annotation.Autowired; import java.util.Map; @Repository public class SampleRepositoryImpl implements SampleRepository { @Autowired NamedParameterJdbcTemplate namedParameterJdbcTemplate; @Override public void update(String sql, MapSqlParameterSource params) { // SQL実行直前にログに吐き出す。 sqlPrint(sql,params); namedParameterJdbcTemplate.update(sql, params); } /** * SQL文を標準出力する * @param sql SQLクエリ文字列 * @param params パラメータ */ private void sqlPrint(String sql, MapSqlParameterSource params) { Map<String, Object> param = params.getValues(); for(String key : param.keySet()) { result = result.replaceAll(":" + key, "'" + param.get(key).toString() + "'"); } System.out.println(result); } }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

try-with-resources文の書き方

動機 try-with-resourcesがイマイチ使いこなせていない。 Java7で導入され、Java9で一部仕様変更があった。 この際、しっかりと使いこなせるように整理したい。 参考にした資料 The Java® Language Specification Java SE 11 Edition 検索キーワード java spec 構文規則 TryWithResourcesStatement: try ResourceSpecification Block [Catches] [Finally] ResourceSpecification: ( ResourceList [;] ) ResourceList: Resource {; Resource} Resource: {VariableModifier} LocalVariableType Identifier = Expression VariableAccess VariableAccess: ExpressionName FieldAccess VariableModifier: Annotation final LocalVariableType: UnannType var
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む