※当サイトの記事には、広告・プロモーションが含まれます。

GradleとJavaの開発で出てくるプロファイルとかの関係って?

f:id:ts0818:20210415202902j:plain

gigazine.net

Googleは2022年までにCookieを使った広告配信を終了させ、新たな仕組みをGoogle Chromeに導入する予定です。その仕組みとして検討中のアイデアの1つに「FLoC」と呼ばれるものがありますが、電子フロンティア財団(EFF)はFLoCについて「最悪のアイデア」「実行しないで欲しい」と述べています。

https://gigazine.net/news/20210305-googles-floc-terrible-idea/

gigazine.net

Googleはプライバシー侵害が懸念されるサードパーティーCookieを使った新しい広告の仕組みを開発中です。新たな仕組みの候補となっているAPIFLoC」は電子フロンティア財団から「最悪なものだ」と言われていますが、GoogleはFLoCの重要性を訴え続けており、2021年3月30日付けでChromeでのデベロッパーオリジントライアルを開始すると発表しました。

https://gigazine.net/news/20210331-google-testing-floc/

gigazine.net

プライバシー保護の観点からサードパーティーCookieが規制される中で、GoogleChromeサードパーティーCookieを廃止して新しい広告の仕組みを構築しようとしています。しかし、新しい仕組みとしてテスト中の「FLoC」は「最悪なもの」と酷評されるだけではなく、すでに独占禁止法違反の疑いで調査されています。FLoCがなぜユーザーやウェブサイトやブラウザにとって有害なのか、ブラウザ開発企業のBraveが解説しています。

https://gigazine.net/news/20210413-brave-disables-floc/

gigazine.net

GoogleサードパーティーCookieなしの新しい広告の仕組み「FLoC」を開発していますが、FLoCは「最悪なものだ」と電子フロンティア財団から指摘されているほか、独占禁止法違反の疑いが持たれています。プライバシー重視のブラウザを開発するVivaldiのCEOであるJon von Tetzchner氏も「FLoCはプライバシーを侵害する追跡技術」であるとして、その理由やFLoCについての考えをつづっています。

https://gigazine.net/news/20210414-google-vivaldi-floc/

⇧ まぁ、何て言うか、指摘してくれるのはありがたいんだけども、結局のところ代替案ってのはあるのかね?

というわけで、今回はJavaについてです。

レッツトライ~。

 

Gradleって?

Wikipediaさんに聞いてみた。 

GradleApache AntApache Mavenのコンセプトに基づくオープンソースビルド自動化システムであり、プロジェクト設定の宣言にはApache Mavenが利用するXML形式ではなくGroovyベース、もしくはKotlin Scriptベースのドメイン固有言語 (DSL) を採用している。

Gradle - Wikipedia

Gradleはタスクの起動順序の決定に有向非巡回グラフDirected Acyclic Graph、DAG)を利用する。

Gradle - Wikipedia

⇧ 「ソースビルド自動化システム」ですと。

「ビルド」って?

ソフトウェアビルドbuild)は、プログラミング言語で書かれたソースコードファイルや各種リソースファイルを独立したソフトウェア生成物に変換するコンピュータ上で実行されるプロセス、またはその結果を指す。ビルドの最終生成物はバイナリ形式の実行ファイルであったり、再利用可能なライブラリであったり、バイトコードあるいはそれらをまとめたアーカイブであったりすることもある。

ビルド (ソフトウェア) - Wikipedia

⇧ ってことらしい。

「ビルドの自動化」とは?

 ビルドの自動化

ビルドの自動化とは、以下のような開発作業をスクリプト化または自動化することを指す。

  • ソースコードをバイナリコードにコンパイルする。
  • バイナリコードをパッケージ化する。
  • テストを実行する。
  • 生産システムに配備する。
  • 文書やリリースノートを作成する。

ビルド (ソフトウェア) - Wikipedia

ビルドを自動化する利点は次の通り。

  • 製品品質を向上させる。
  • コンパイルとリンクの所要時間短縮
  • 冗長なタスクの排除
  • 手順ミスの排除
  • 特定のエキスパートに依存しなくて済む。
  • 履歴を保持することで、問題発生時に原因を究明しやすい。
  • 時間と金を節約できる

ビルド (ソフトウェア) - Wikipedia

⇧ ってな感じで、良いこと尽くめな感じの書きっぷりですけど、どうなんですかね?

スクリプト」で記述するような「ビルドツール」ってなると、確実に職人芸的な方向性に陥りやすくなりそうな気がしてしまうんだけど...所謂ひとつの属人化まっしぐらみたいな?

で、「ビルドツール」にも様々なものがあり、

⇧ 上記サイト様がまとまっております。 Javaがメインの開発だとこのあたりが使われてることが多いイメージなんですかね。

「Gradle」さんは「スクリプト」なんすね...

で、「Gradle」のアーキテクチャってのは、

⇧ 上図のような感じですと。

「Groovyベース」や「Kotlin Scriptベース」ってことから「JVM言語」を採用してるってことなので、「JVMJava Virtual Machine)」と「Java」が必要なんかな?

This list of JVM Languages comprises notable computer programming languages that are used to produce computer software that runs on the Java virtual machine (JVM). Some of these languages are interpreted by a Java program, and some are compiled to Java bytecode and JIT-compiled during execution as regular Java programs to improve performance.

The JVM was initially designed to support only the programming language Java. However, as time passed, even more languages were adapted or designed to run on the Java platform.

https://en.wikipedia.org/wiki/List_of_JVM_languages

⇧ ってな感じで、「List of JVM languages」とかってのがまとまってるみたいね。

Javaの生みの親の一人である「James Gosling」氏の発言がなかなか衝撃的ね...

⇧ う、う~ん...

むっちゃ爽やかな笑顔で言われましても...

JVMJava Virtual Machine)」の内部のアーキテクチャのOverviewみたいなものがいまひとつハッキリしないからな~...

 

Javaの開発で出てくるプロファイルって?

「プロファイル」って定義が見つけられなかったんですが、 

www.techscore.com

プロファイルとは、ビルド環境やリリース環境などの環境に依存する設定を記述するためのものです。環境に依存する設定には、次の二種類が考えられます。

  • リリース環境によって異なる設定(接続先データベースやログファイルの出力先)
  • ビルド環境によって異なる設定(OS の種類やアプリケーションサーバのインストール先)

6. プロファイル | TECHSCORE(テックスコア)

⇧ ここで言う「プロファイル」ってのは、上記サイト様で仰っているものとします。

何か、ネットの情報を検索してみたんだけど、

⇧ ってな情報しかヒットしなくて、「プロファイル」ってものが何なのかってのを定義してる文書が見つからないんだな、これが...

「TECHSCORE」さんの記事が一番イメージに近いかと。

プロファイルによって設定を変更するアプローチは二つあります。

  • profile/properties 要素でのプロパティ定義とフィルタ機能を組み合わせる方法
  • 環境の数だけ設定ファイルを用意し、それを有効化されたプロファイルによって変更する方法

前者の「profile/properties 要素でのプロパティ定義とフィルタ機能を組み合わせる方法」とは、環境による設定ファイルの差異が限定的な場合に有効なアプローチです。例として、log4j でのログの出力レベルを、本番環境では警告レベル以上、開発時は全てをログに出力する場合を考えます。プロファイルでは次のようにログの出力レベルを表すプロパティ(ここでは「log.level」)を定義します。

<!-- 開発環境用プロファイル -->
<profile>
  <id>development</id>
  <properties>
    <log.level>ALL</log.level>
  </properties>
</profile>

<!-- 本番環境用プロファイル -->
<profile>
  <id>production</id>
  <properties>
    <log.level>WARN</log.level>
  </properties>
</profile>

そして、log4j の設定ファイル log4j.properties には次のように記述します。

log4j.rootLogger=${log.level}, ...
...

このように設定ファイルの一部だけを変更すれば良い場合は、フィルタ機能を利用するアプローチが簡単です。

6. プロファイル | TECHSCORE(テックスコア)

⇧ ってあるように、環境ごとに設定を変えれるんですと。

よく、「Spring Boot」なんかのプロジェクトとかで、

  • application.properties
  • application.yml

みたいなファイルが出てくることあるあるだと思うんだけど、「プロファイル」に記述しといた値を読み込んだりできるみたいね。

「プロパティファイル」って言うみたいね、拡張子が「.yml」とかでも「プロパティファイル」って言ってるあたりが、個人的にモヤモヤ感が半端ないんだが...

「Spring Boot」とかであれば、

blog.tagbangers.co.jp

⇧ なんか読み込み方法がバリエーションに富んでるみたいね...

これが、素のJavaの場合だと、

qiita.com

⇧ できることは限られてくるってことですかね?

Javaって、このあたりが結構混乱するんですよね、いろんな選択肢があるのは良いのですが、結局のところ、それぞれでどういったことができるかが見え辛い...

あと、ディレクトリ構成とかね、どこにファイルを配置すれば良いかが不透明過ぎるから本当に困る...

 

Gradleの場合のプロファイルって?

で、更に、「ビルドツール」によっても「プロパティファイル」の扱いが変わってくるっぽい...

その前に、何故にこんなことを調べてたかと言うと、「データベース」の接続情報をべた書きでコーディングするんじゃなくて、外出ししたいな~って思ったんですよ、「Gradleプロジェクト」で。

ところが調べてみると、まぁ、猫も杓子も「Spring Boot」+「Gradle」って組み合わせの例が多くて、「Gradleプロジェクト」のみの場合での情報がほぼ無いというね...

toriaezu-engineer.hatenablog.com

jappy.hatenablog.com

maku77.github.io

⇧ 上記サイト様ぐらいですかね、「Spring Boot」に染まってない情報は。

ズバリ、「build.gradle」で読み込んであげれば良さ気のようです。

ちなみに「Gradle」のビルドに必要な情報については、

⇧ 上記サイト様が詳しいです。

「様々なインプット」に対して 「Gradleのスクリプト」を実行することで、「ビルド」されるってことみたいですね。

で、この「プロパティファイル」の配置場所がハッキリせんよね...

とありあえず、「ビルドツール」が「Gradle」の場合で、「プロパティファイル」が準備できたとして、「プロパティファイル」に記載した値を取り込むアプローチとしては、

  1. Javaでプロパティファイルの値を読み込む
  2. Gradleでプロパティファイルの値を読み込む

のどっちかになるんじゃないかと。

「Spring Boot」とかは「Javaでプロパティファイルを読み込む」ってアプローチになるんかな(「アノテーション」とか使ってるっぽいから、内部的にどう処理されてるのかがよく分からんけど...)、最終的には「Gradle」でビルドされることになるのは変わらんと思われますが。

最終的には「JVMJava Virtual Machine)」で「.class」ファイルが実行されないことには、Javaのプロジェクトは動かないわけだから、「.class」ファイルになってる時点で「プロパティファイルの値(今回だと『データベースの接続情報』を想定)」が連携されてる必要があるってことですかね。

今回は「1.Javaでプロパティファイルの値を読み込む」って感じになるのかな。

qiita.com

www.atmarkit.co.jp

  

というわけで、試してみる

「プロパティファイル」の読み込みを試してみようということで、今回、「ORM(Object Relational Mapping)」ライブラリである「Hibernate ORM」の「プロパティファイル」を読み込んでみようかと。

「ORM(Object Relational Mapping)」ライブラリの種類などについては、

⇧ 上記サイト様が詳しいです。

ちなみに、「ORM(Object Relational Mapping)」は、

オブジェクト関係マッピングObject-relational mappingO/RMORM)とは、データベースオブジェクト指向プログラミング言語の間の非互換なデータを変換するプログラミング技法である。オブジェクト関連マッピングとも呼ぶ。実際には、オブジェクト指向言語から使える「仮想」オブジェクトデータベースを構築する手法である。オブジェクト関係マッピングを行うソフトウェアパッケージは商用のものもフリーなものもあるが、場合によっては独自に開発することもある。

オブジェクト関係マッピング - Wikipedia

⇧ 上記のような説明となってますね。

Javaの例だと、

⇧ みたいな感じで、「プログラミング言語」と「データベース」で「データ」が異なるために、橋渡しするために「ORM(Object Relational Mapping)」が必要となってくるみたいね。

脱線しましたが、「Hibernate ORM」のアーキテクチャは、

docs.jboss.org

⇧ みたいな感じで、「JDBC」を隠蔽してくれるので、「JDBC」の面倒くさい操作を利用者は意識することなく、「データベース」を操作できるよ~ん、ってことらしいんですが、本当かいな...

JDBC」はと言うと、

www.atmarkit.co.jp

 JDBCは、一言でいってしまうなら「リレーショナル・データベース(および、ほとんどすべての表形式のデータ)にアクセスするための、標準Java API」です。JDBCは「Java Database Connectivity」の省略だといわれています(が、実はJDBC仕様には明記されていません)。

JDBCとは何か?:Javaデータアクセスの基礎(1) - @IT

⇧ ってな感じで、「データベース」を操作できるJavaAPIってことですね。

Hibernate ORM」は「JDBC API」をラッパーしてる感じなんすかね?

ちなみに、「Hibernate ORM」は「Hibernate」が管理してるプロジェクトの一部で、

hibernate.org

⇧ 上記サイト様を見た感じ、

って種類のプロジェクトがあるみたいね。「Hibernate Validator」については、

ts0818.hatenablog.com

⇧ 上記の記事で扱いました。

脱線しましたが、「Hibernate ORM」で「プロパティ」を渡す方法について、 

docs.jboss.org

Hibernate に設定プロパティを渡す方法は1つではありません。さまざまなオプションを用意しています:

  1. java.util.Properties インスタンスを Configuration.setProperties() に渡します。

  2. hibernate.properties をクラスパスのルートディレクトリに置きます。

  3. System プロパティが java -Dproperty=value を使うように設定します。

  4. <property> 要素を hibernate.cfg.xml (後述)に設定します。

If you want to get started quicklyhibernate.properties is the easiest approach.

org.hibernate.cfg.Configuration は、起動時にだけあるオブジェクトであり、一度 SessionFactory を生成した後は、破棄されることを意図しています。

https://docs.jboss.org/hibernate/orm/3.6/reference/ja-JP/html/session-configuration.html

⇧ 上記のドキュメントに記載がありました。ただ、バージョンが旧いんですが、新しいバージョンのドキュメントで、このあたりの記載が見当たらなかったんですよね...

で話を戻すと、今回は「プロパティ」を渡す方法として「hibernate.properties」っていうファイルから読み込むようにしたいと思います。

今回は、「Java SE」環境で「依存性注入(DI:Dependency Injection)」を可能にできるライブラリ「Weld」ってのも使っていきたいと思います。

weld.cdi-spec.org

Weld is the reference implementation of CDI: Contexts and Dependency Injection for the Java EE Platform - a JCP standard for dependency injection and contextual lifecycle management and one of the most important and popular parts of the Java EE. Weld is integrated into many Java EE application servers such as WildFlyJBoss Enterprise Application PlatformGlassFishOracle WebLogic ServerWebSphere Application Server and others. Weld can also be used in plain servlet containers (Tomcat, Jetty) or Java SE.

https://weld.cdi-spec.org/

⇧ というか、「Java SE」の標準APIには「依存性注入(DI:Dependency Injection)」が実現できるようなライブラリって無いんですね。

脱線しまくりましたが、以下のようなディレクトリ構成になりました。

f:id:ts0818:20210414221425p:plain

⇧ 今回、関係あるのは、水色で選択されてる部分ですかね。

あと、なんか、ドキュメントには特に記載がなかったんだけど、「src/main/resources/META-INF/beans.xml」ってファイルを配置してあげないと「Hibernate ORM」が機能してくれないという...

ちなみに「beans.xml」でエラーになってるのは、「beans.xml」に何も記載していない空ファイルの状態だからなんですが、その状態で正常に処理されます...大丈夫なんか「Hibernate ORM」~。

qiita.com

/[project-root]/src/main/resources/META-INF/beans.xml

ファイルの存在有無しかみていないらしく、0byteファイルでも有効化されました。
ですが、本来は妥当なXMLにしておくべきだと思います。

CDIをJava SE環境で動かす - Weld SE - Qiita

⇧ 上記サイト様でも仰っておられますが、実際には「beans.xml」はちゃんと記載したほうが良さ気ですね。

事前に、「PostgreSQL」をインストールして、データベースを作成しておきます。(今回は「PostgreSQL」を使ってますが、他の「RDBMS(Relational Database Management System)」でもOK)

では、PostgreSQLがインストールされ「java_one_hundred」っていうデータベースが作成されてるという前提で話を進めます。

-- データベースの指定
\c java_one_hundred;

-- テーブル作成
CREATE TABLE IF NOT EXISTS item (
    id bigserial primary key,
    name varchar(50) NOT NULL,
    description text
)

⇧ ってなSQLファイルを用意しておいて、「PostgreSQL」に接続して実行します。

psql -U [ユーザー名] -d [データベース名] -h [ホスト名]    
 \l 
\conninfo 
\c [データベース名]
\i 'sqlファイルまでのパス'

f:id:ts0818:20210415195348p:plain

 \q 

⇧ ちなみに、SQLファイルを実行する際のファイルパスについて、Windowsの場合は、ファイルのパスの区切りを「\」でエスケープするか「/」に置き換える必要があるみたいです。

zeema.hatenablog.com

⇧ 上記サイト様が詳しいです。

残りのソースコードは以下のような感じにしてみました。 

2021年4月22日(黙)追記:↓ ここから

hibernate.properties」の内容を載せるの忘れてましたんで追加。「[接続するデータベース名]」「[データベース名に接続するユーザー名]」「[データベース名に接続するユーザー名のパスワード]」の部分は、ご自身の環境のものに合わせてください。

今回、「PostgreSQL」を使ってるので、デフォルトであれば「ポート番号」は「5432」が解放されるかと。

hibernate.diarect=org.hibernate.dialect.PostgreSQLDialect
hibernate.connection.driver_class=org.postgresql.Driver
hibernate.connection.url=jdbc:postgresql://localhost:5432/[接続するデータベース名]
hibernate.connection.username=[データベースに接続するユーザー名]
hibernate.connection.password=[データベースに接続するユーザー名のパスワード] 

2021年4月22日(黙)追記:↑ ここまで

 

/*
 * This file was generated by the Gradle 'init' task.
 *
 * This generated file contains a sample Java Library project to get you started.
 * For more details take a look at the Java Libraries chapter in the Gradle
 * User Manual available at https://docs.gradle.org/6.3/userguide/java_library_plugin.html
 */

plugins {
    // Apply the java-library plugin to add support for Java Library
    id 'java-library'
    id 'application'
}

repositories {
    // Use jcenter for resolving dependencies.
    // You can declare any Maven/Ivy/file repository here.
    jcenter()
    //mavenCentral()
}

dependencies {
    // This dependency is exported to consumers, that is to say found on their compile classpath.
    //api 'org.apache.commons:commons-math3:3.6.1'

    // This dependency is used internally, and not exposed to consumers on their own compile classpath.
    //implementation 'com.google.guava:guava:28.2-jre'

    // https://mvnrepository.com/artifact/javax.validation/validation-api
    //implementation group: 'javax.validation', name: 'validation-api', version: '2.0.1.Final'
    compile group: 'javax.validation', name: 'validation-api', version: '2.0.1.Final'

    // https://mvnrepository.com/artifact/commons-beanutils/commons-beanutils
    implementation group: 'commons-beanutils', name: 'commons-beanutils', version: '1.9.4'

    // https://mvnrepository.com/artifact/org.hibernate/hibernate-validator
    //implementation 'org.hibernate.validator:hibernate-validator:7.0.1.Final'
    //runtimeOnly 'org.hibernate.validator:hibernate-validator:6.0.17.Final'
    runtimeOnly 'org.hibernate.validator:hibernate-validator:7.0.1.Final'
    //compile 'javax.el:javax.el-api:2.2.4'
    //implementation group: 'org.glassfish.web', name: 'javax.el', version: '2.2.4'
    // runtimeOnly 'org.glassfish:javax.el:3.0.1-b11'

    // https://mvnrepository.com/artifact/org.glassfish/jakarta.el
    runtimeOnly group: 'org.glassfish', name: 'jakarta.el', version: '4.0.1'

    // https://mvnrepository.com/artifact/org.hibernate/hibernate-validator-cdi
    runtimeOnly group: 'org.hibernate', name: 'hibernate-validator-cdi', version: '7.0.1.Final'

    // https://mvnrepository.com/artifact/org.hibernate/hibernate-validator-annotation-processor
    //runtimeOnly group: 'org.hibernate', name: 'hibernate-validator-annotation-processor', version: '7.0.1.Final'

    // https://mvnrepository.com/artifact/org.hibernate/hibernate-core
    implementation group: 'org.hibernate', name: 'hibernate-core', version: '5.4.30.Final'

    // https://mvnrepository.com/artifact/org.postgresql/postgresql
    implementation group: 'org.postgresql', name: 'postgresql', version: '42.2.19'

    // https://mvnrepository.com/artifact/org.jboss.weld.se/weld-se-core
    implementation group: 'org.jboss.weld.se', name: 'weld-se-core', version: '4.0.1.Final'

    // Use JUnit test framework
    testImplementation 'junit:junit:4.12'
}

application {
    mainClassName = 'Java_one_hundred_knock_comp.*';
}

⇧ 「dependencies」については、塗りつぶしてある「54、57、60」行目のだけあれば大丈夫かと。「Hibernate Validator」の時のファイルが同居してるせいで、自分は上記のように「Hibernate ORM」や「Weld」に関係ないライブラリも読み込んでます。

■/Java_one_hundred_knock_comp/src/main/java/Java_one_hundred_knock_comp/eightytwo/entity/Item.java

package Java_one_hundred_knock_comp.eightytwo.entity;

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "Item")
public class Item {
	@Id
	private long id;
	private String name;
	private String description;

	public long getId() {
		return id;
	}

	public void setId(long id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}
}

■/Java_one_hundred_knock_comp/src/main/java/Java_one_hundred_knock_comp/eightytwo/repository/DatabaseConfig.java

package Java_one_hundred_knock_comp.eightytwo.repository;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Properties;

import org.hibernate.cfg.Configuration;

public class DatabaseConfig {

	private static final String HIBERNATE_PROPERTIES_FILE_PATH = "hibernate.properties";
	private Properties properties;

	private void initProperties() {
		this.properties = new Properties();
	}

	/**
	 * Hibernate ORMにプロパティ(データベース接続情報など)を渡す
	 * @return Hibernate ORMの処理に必要なプロパティ
	 */
	public Configuration createDatabaseConfig() {
		initProperties();
		try {
			properties.load(Files.newBufferedReader(Paths.get(HIBERNATE_PROPERTIES_FILE_PATH), StandardCharsets.UTF_8));
		} catch (IOException e) {
			// TODO 自動生成された catch ブロック
			e.printStackTrace();
		}
		Configuration cfg = new Configuration();
		cfg.setProperties(this.properties);
		setUpEntityClass(cfg);
		return cfg;

	}

	/**
	 * Entityを登録して、Hibernate ORMで認識できるようにする
	 * (hibernate.cfg.xml で登録する場合は不要)
	 * @param cfg
	 */
	private void setUpEntityClass(Configuration cfg) {
		cfg.addAnnotatedClass(Java_one_hundred_knock_comp.eightytwo.entity.Item.class);
	}
}

■/Java_one_hundred_knock_comp/src/main/java/Java_one_hundred_knock_comp/eightytwo/repository/DatabaseConnection.java

package Java_one_hundred_knock_comp.eightytwo.repository;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

import jakarta.inject.Inject;

public class DatabaseConnection {

	@Inject
	private DatabaseConfig databaseConfig;

	protected Session connectSession() {

		Configuration configuration = databaseConfig.createDatabaseConfig();
		SessionFactory sessionFactory = configuration.buildSessionFactory();

		Session session = sessionFactory.openSession();
		return session;
	}
}    

■/Java_one_hundred_knock_comp/src/main/java/Java_one_hundred_knock_comp/eightytwo/repository/ItemRepository.java

package Java_one_hundred_knock_comp.eightytwo.repository;

import org.hibernate.Session;
import org.hibernate.Transaction;

import Java_one_hundred_knock_comp.eightytwo.entity.Item;

public class ItemRepository extends DatabaseConnection {

	public void save(Item item) {
		Session session = connectSession();
		try {
			Transaction transaction = session.beginTransaction();
			session.saveOrUpdate(item);
			transaction.commit();
		} catch (Exception e) {
			// TODO 自動生成された catch ブロック
			session.getTransaction().rollback();
			e.printStackTrace();
		} finally {
		    session.close();
		}
	}
	
	public void delete(Item item) {
		Session session = connectSession();
		try {
			Transaction transaction = session.beginTransaction();
			session.delete(item);
			transaction.commit();
		} catch (Exception e) {
			// TODO 自動生成された catch ブロック
			session.getTransaction().rollback();
			e.printStackTrace();
		} finally {
		    session.close();
		}
	}
}

■/Java_one_hundred_knock_comp/src/main/java/Java_one_hundred_knock_comp/eightytwo/service/ItemService.java

package Java_one_hundred_knock_comp.eightytwo.service;

import Java_one_hundred_knock_comp.eightytwo.entity.Item;
import Java_one_hundred_knock_comp.eightytwo.repository.ItemRepository;
import jakarta.inject.Inject;

public class ItemService {

	@Inject
	private ItemRepository itemRepository;

	public void save(Item item) {
		itemRepository.save(item);
	}

	public void delete(Item item) {
		itemRepository.delete(item);
	}
}

■/Java_one_hundred_knock_comp/src/main/java/Java_one_hundred_knock_comp/eightytwo/KnockHibernateOrm.java

package Java_one_hundred_knock_comp.eightytwo;

import java.util.ArrayList;
import java.util.List;

import org.jboss.weld.environment.se.Weld;
import org.jboss.weld.environment.se.WeldContainer;

import Java_one_hundred_knock_comp.eightytwo.entity.Item;
import Java_one_hundred_knock_comp.eightytwo.service.ItemService;
import jakarta.inject.Inject;

public class KnockHibernateOrm {
	@Inject
	private ItemService ItemService;

	public static void main(String[] args) {
		// TODO 自動生成されたメソッド・スタブ
		Object[][] item2dArr = {
				{1L, "Sponge Bob", "『スポンジ・ボブ』は、ニコロデオン他で放送されているアメリカ合衆国のテレビアニメ。また、その主人公の名前。"},
				{2L, "Tom & Jerry", "トムとジェリー(英語: Tom and Jerry)は、アメリカ合衆国の映画会社メトロ・ゴールドウィン・メイヤー(MGM)に所属していたウィリアム・ハンナとジョセフ・バーベラが創作した1940年から続く短編アニメーション映画シリーズおよびテレビアニメ、カートゥーン、ギャグアニメである。"},
				{3L, "The SimpSons", "『ザ・シンプソンズ』は、マット・グレイニング創作のアメリカのテレビアニメシリーズ。 アメリカ・FOXテレビで、1989年に放送開始した、アメリカアニメ史上最長寿番組。現在は60か国以上で20か国語に翻訳され、全世界で毎週6000万人以上が視聴している。エミー賞、ピーボディ賞受賞作品。"},
				{4L, "South Park", "『サウスパーク』は、アメリカのコメディ中心のケーブルテレビチャンネル、コメディ・セントラルで放送されている切り絵によるストップモーション・アニメ、及びその舞台。初回放送は1997年8月13日。総話数はシーズン24までで309話。また、1999年に映画版が公開されている。シーズン23まででエミー賞を5回受賞。"},
				{5L, "Popeye", "ポパイ(Popeye)は、アメリカ合衆国の漫画家エルジー・クリスラー・シーガーによるコミック・ストリップ、カートゥーン作品、及びその代表的な登場キャラクターの1人で、架空の人物である。職業は作品によって水兵であったり船乗りであったりする。漫画を原作として映画、テレビアニメ化などもされている。"},
				{6L, "We Bare Bears", "『ぼくらベアベアーズ』(原題:We Bare Bears)は、アメリカ合衆国のテレビアニメシリーズ。本作は、3匹の熊たちの視点を通じて、現代っ子たちの生活や心理を描いたコメディアニメである。"},
				{7L, "Teenage Mutant Ninja Turtles", "『ティーンエイジ・ミュータント・ニンジャ・タートルズ』Teenage Mutant Ninja Turtles) は1984年にミラージュ・スタジオから出版されたアメコミを原作とするアニメシリーズ、および作中に登場するグループの名称である。略称は「TMNT」もしくは「忍者タートルズ」、「ミュータント・タートルズ」。"},
				{8L, "Happy Tree Friends", "『Happy Tree Friends』は、アメリカ、Mondo Media製作によるフラッシュアニメ作品。1999年に公開された「Banjo Frenzy」という話がルーツになっている。作品は一見コミカルで可愛らしいが、残虐でグロテスクな表現がほぼ毎回ある。略称は「HTF」「ハピツリ」。PG-12指定。"},
				{9L, "The Powerpuff Girls", "『パワーパフガールズ』は、クレイグ・マクラッケン原作の漫画、テレビアニメ作品。テレビ東京系列・カートゥーン ネットワークでアニメシリーズが放送され、漫画版がIDWパブリッシングから刊行されている。"},
				{10L, "Batman: The Animated Series", "『バットマン』 は、DCコミックスが刊行するアメコミ『バットマン』を原作とした1990年代にアメリカで製作・放送されたテレビアニメシリーズ。同一の世界観のクロスオーバー作品群として扱う「DCアニメイテッド・ユニバース」でもある。"},
				{11L, "The Pink Panther", "ピンク・パンサー(The Pink Panther)は、1963年のアメリカ映画『ピンクの豹』を第1作とする映画シリーズ。「クルーゾー警部(英語版)」、「アニメキャラクターのピンクパンサー」、テーマ曲「ピンク・パンサーのテーマ(英語版)」の3大ヒットを生み出した、20世紀後半を代表するコメディ映画の大ヒットシリーズである。"},
		};

		List<Item> itemList = new ArrayList<>();
		for (Object[] itemArr: item2dArr) {
			Item item = new Item();
			item.setId((long)itemArr[0]);
			item.setName((String)itemArr[1]);
			item.setDescription((String)itemArr[2]);
			itemList.add(item);
		}

		Weld weld = new Weld();
		WeldContainer container = weld.initialize();
		container.select(KnockHibernateOrm.class).get().doneSaveItems(itemList);
		container.shutdown();
		//		KnockHibernateOrm knockHibernateOrm = new KnockHibernateOrm();
		//		knockHibernateOrm.doneSaveItem(item);
	}

	public void doneSaveItems(List<Item> items) {
		items.forEach(item -> {
			doneSaveItem(item);
		});
	}

	public void doneDeleteItems(List<Item> items) {
		items.forEach(item -> {
			doneDeleteItem(item);
		});
	}

	public void doneSaveItem(Item item) {
		ItemService.save(item);
	}

	public void doneDeleteItem(Item item) {
		ItemService.delete(item);
	}
}

⇧ ってな感じで保存して、実行してみます。

f:id:ts0818:20210414231654p:plain

「beans.xml」がエラー出てる状態なので、以下のダイアログが出るけど「続行(P)」を押下すると、

f:id:ts0818:20210414231732p:plain

無事、処理が実行され、

f:id:ts0818:20210415172026p:plain

PostgreSQLのテーブルを確認すると、

f:id:ts0818:20210414232053p:plain

データが登録されています!

f:id:ts0818:20210415172051p:plain


という感じで、「Hibernate ORM」は個人的には何か使い辛い感じですかね...

Spring Framework」とかであれば「プロパティファイル」の値を強引に取得するようなコーディングとかしなくても済むんかな?

まぁ、毎度モヤモヤ感が半端ないですが...

今回はこのへんで。