なんかJakarta NoSQLというのが出ていて素敵そうだったので試してみた。
サポートしているデータベースがこんな感じで、このあたりを統一的に扱えると便利そう。
http://www.jnosql.org/docs/supported_dbs.html
NoSQLといっても色々あって単一APIでは難しいんでは、というのはそのとおりで、Key Value、Column、Document、Graphの4分類で扱う感じっぽい。
このGetting Startedに従ってやってみる。
http://www.jnosql.org/docs/document.html
結果としては、動かなかった。
けど、準備としては必要なことをやってるはずなので、メモとして残しておいて、今後正式リリースされてちゃんと動きそうになったらまた試してみる。
MongoDBを起動する
今回はMongoDBを試すけど、Dockerで動かします。
> docker run --name testmongo -d -p 27017:27017 mongo
試しに普通にJavaから接続する
まずは普通にJavaコードで。
dependencyにこういうの追加します。
<dependency> <groupId>org.mongodb</groupId> <artifactId>mongodb-driver-sync</artifactId> <version>4.8.1</version> </dependency>
データつっこむやつ。
import com.mongodb.client.MongoClient; import com.mongodb.client.MongoClients; import org.bson.Document; public class TryInsert { public static void main(String[] args) { var uri = "mongodb://localhost"; try (MongoClient client = MongoClients.create(uri)) { var db = client.getDatabase("mydb"); var coll = db.getCollection("mycol"); var doc = Document.parse(""" { id: 123, name: "kishida", phone: ["234", "123"], } """); coll.insertOne(doc); } } }
データ読み込むやつ
import com.mongodb.client.MongoClient; import com.mongodb.client.MongoClients; public class TryRead { public static void main(String[] args){ var uri = "mongodb://localhost"; try (MongoClient client = MongoClients.create(uri)) { var db = client.getDatabase("mydb"); var coll = db.getCollection("mycol"); var ite = coll.find(); for (var d : ite) { System.out.println(d); } } } }
成功。よかった。
Document{{_id=63b68bfe6414fd518da18292, id=123, name=kishida, phone=[234, 123]}}
Jakarta NoSQLのための依存ライブラリ
ということでJNoSQLを試す。 まずはMongoDBはdocumentデータベースなので、次のようなmappingを追加
<dependency> <groupId>org.eclipse.jnosql.mapping</groupId> <artifactId>mapping-document</artifactId> <version>1.0.0-b4</version> </dependency>
そしてMongoDBのためのドライバを追加
<dependency> <groupId>org.eclipse.jnosql.communication</groupId> <artifactId>mongodb-driver</artifactId> <version>1.0.0-b4</version> </dependency>
CDIが必要なのでWeld SEを入れる
<dependency> <groupId>org.jboss.weld.se</groupId> <artifactId>weld-se-shaded</artifactId> <version>5.1.0.Final</version> </dependency> <dependency> <groupId>org.jboss.weld.se</groupId> <artifactId>weld-se</artifactId> <version>2.4.8.Final</version> </dependency>
MicroProfile Configが必要なので入れる
<dependency> <groupId>org.eclipse.microprofile.config</groupId> <artifactId>microprofile-config-api</artifactId> <version>3.0.2</version> </dependency>
あと、標準アノテーションも入れておく
<dependency> <groupId>javax.annotation</groupId> <artifactId>javax.annotation-api</artifactId> <version>1.3.2</version> </dependency>
試してみる
CDIを使うので、resources/META-INF/beans.xml
に空のファイルを作っておく。
マッピング用のクラス。JPAっぽいけど違うアノテーションを使う。共通にしてほしい。
import jakarta.nosql.mapping.Column; import jakarta.nosql.mapping.Entity; import jakarta.nosql.mapping.Id; import java.util.List; @Entity("Person") public class Person { @Id("id") long id; @Column String name; @Column("phone") List<String> phones; }
こういうDocumentCollectionManagerをとってくるためのProducerを用意。getting startedではクラス名にミスがありそう。
import jakarta.annotation.PostConstruct; import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.inject.Produces; import jakarta.nosql.Settings; import jakarta.nosql.document.DocumentCollectionManager; import jakarta.nosql.document.DocumentCollectionManagerFactory; import jakarta.nosql.document.DocumentConfiguration; import java.util.Map; import org.eclipse.jnosql.communication.mongodb.document.MongoDBDocumentConfiguration; @ApplicationScoped public class DocumentCollectionManagerProducer { private static final String COLLECTION = "mycol"; private DocumentConfiguration config; private DocumentCollectionManagerFactory manFact; @PostConstruct public void init() { config = new MongoDBDocumentConfiguration(); Map<String, Object> settings = Map.of("mongodb-server-host-1", "localhost:27017"); manFact = config.get(Settings.of(settings)); } @Produces public DocumentCollectionManager getManager() { return manFact.get(COLLECTION); } }
こんな感じらしい。
import jakarta.enterprise.inject.se.SeContainer; import jakarta.enterprise.inject.se.SeContainerInitializer; import jakarta.nosql.document.DocumentQuery; import jakarta.nosql.mapping.document.DocumentTemplate; import java.util.List; import java.util.Optional; import static jakarta.nosql.document.DocumentQuery.*; public class App { public static void main(String[] args) { try (SeContainer cont = SeContainerInitializer.newInstance().initialize()) { Person p = new Person(); p.name = "yamamoto"; p.phones = List.of("321", "543"); p.id = 918; var temp = cont.select(DocumentTemplate.class).get(); temp.insert(p); DocumentQuery q = select().from("Person").where("id").eq(918).build(); Optional<Person> result = temp.singleResult(q); System.out.println(result); } } }
では動かしてみよう。
なんかDocumentTemplateがふたつあるといって怒られた・・・
Exception in thread "main" org.jboss.weld.exceptions.AmbiguousResolutionException: WELD-001335: Ambiguous dependencies for type DocumentTemplate with qualifiers Possible dependencies: - Managed Bean [class org.eclipse.jnosql.mapping.document.DefaultDocumentTemplate] with qualifiers [@Any @Default], - Managed Bean [class org.eclipse.jnosql.mapping.document.DefaultDocumentTemplateProducer$ProducerDocumentTemplate] with qualifiers [@Any @Default]
それでは、とリポジトリ使うやつを試す。 こんな感じにインタフェース作ると実装を勝手につくってくれる。
import jakarta.inject.Named; import jakarta.nosql.mapping.Repository; import java.util.List; import java.util.stream.Stream; public interface PersonRepository extends Repository<Person, Long> { List<Person> findByName(String name); Stream<Person> findByPhones(String phone); }
そして動かす。
import jakarta.enterprise.inject.se.SeContainer; import jakarta.enterprise.inject.se.SeContainerInitializer; import java.util.List; import org.eclipse.jnosql.mapping.DatabaseQualifier; public class App { public static void main(String[] args) { try (SeContainer cont = SeContainerInitializer.newInstance().initialize()) { Person p = new Person(); p.name = "yamamoto"; p.phones = List.of("321", "543"); p.id = 918; PersonRepository repo = cont.select(PersonRepository.class) .select(DatabaseQualifier.ofDocument("mycol")).get(); repo.save(p); } } }
@Database
はQualifierではないと怒られた。
Exception in thread "main" org.jboss.weld.exceptions.IllegalArgumentException: WELD-000814: Annotation @jakarta.nosql.mapping.Database(value=DOCUMENT, provider="mycol") is not a qualifier
なんか設定でどうにかなる問題じゃなさそうなので、今日はあきらめ。
ちゃんと使えるなら使いやすそうなAPIなので、正式化は楽しみ。
しかしJava / Jakarta EEは難しい・・・