カスタム変換
次の Spring Converter
実装の例は、String
からカスタム Email
値オブジェクトに変換します。
@ReadingConverter
public class EmailReadConverter implements Converter<String, Email> {
public Email convert(String source) {
return Email.valueOf(source);
}
}
ソースとターゲットの型がネイティブ型である Converter
を記述した場合、それを読み取りコンバーターと見なすか、書き込みコンバーターと見なすべきかを判断できません。コンバーターインスタンスを両方として登録すると、望ましくない結果が生じる可能性があります。例: Converter<String, Long>
があいまいですが、書き込み時にすべての String
インスタンスを Long
インスタンスに変換しようとしても意味がありません。インフラストラクチャーにコンバーターを一方向にのみ登録させるために、コンバーターの実装で使用される @ReadingConverter
および @WritingConverter
アノテーションを提供します。
インスタンスはクラスパスまたはコンテナースキャンから取得されないため、コンバーターは明示的な登録の対象となります。変換サービスへの不要な登録と、そのような登録に起因する副作用を回避するためです。コンバーターは、ソースおよびターゲットの型に基づいて、登録されたコンバーターの登録および照会を可能にする中央機能として CustomConversions
に登録されます。
CustomConversions
には、事前に定義された一連のコンバーター登録が付属しています。
java.time
、java.util.Date
、String
型間の変換用の JSR-310 コンバーター。
ローカルテンポラル型(LocalDateTime から java.util.Date など)のデフォルトコンバーターは、システムデフォルトのタイムゾーン設定に依存して、これらの型間で変換します。独自のコンバーターを登録することにより、デフォルトのコンバーターをオーバーライドできます。 |
コンバーターの明確化
一般に、Converter
の実装は、変換元と変換先のソース型とターゲット型をインスペクションします。これらの 1 つが、基になるデータアクセス API がネイティブに処理できる型かどうかに応じて、コンバーターインスタンスを読み取りまたは書き込みコンバーターとして登録します。次の例は、書き込みコンバーターと読み取りコンバーターを示しています(違いは Converter
の修飾子の順序にあることに注意してください)。
// Write converter as only the target type is one that can be handled natively
class MyConverter implements Converter<Person, String> { … }
// Read converter as only the source type is one that can be handled natively
class MyConverter implements Converter<String, Person> { … }
型ベースのコンバーター
マッピング結果に影響を与える最も簡単なメソッドは、@Field
アノテーションを介して目的のネイティブ MongoDB ターゲット型を指定することです。これにより、値をネイティブ org.bson.types.Decimal128
形式で保持しながら、ドメインモデルで BigDecimal
などの非 MongoDB 型を操作できるようになります。
public class Payment {
@Id String id; (1)
@Field(targetType = FieldType.DECIMAL128) (2)
BigDecimal value;
Date date; (3)
}
{
"_id" : ObjectId("5ca4a34fa264a01503b36af8"), (1)
"value" : NumberDecimal(2.099), (2)
"date" : ISODate("2019-04-03T12:11:01.870Z") (3)
}
1 | 有効な ObjectId を表す文字列 ID 値は自動的に変換されます。詳細については、_id フィールドがマッピング層でどのように処理されるかを参照してください。 |
2 | 目的のターゲット型は Decimal128 として明示的に定義されており、これは NumberDecimal に変換されます。それ以外の場合、BigDecimal 値は String に切り詰められます。 |
3 | Date 値は MongoDB ドライバー自体によって処理され、ISODate として保存されます。 |
上記のスニペットは、単純な型のヒントを提供するのに便利です。マッピングプロセスをよりきめ細かく制御するには、Spring コンバーターを MappingMongoConverter
などの MongoConverter
実装に登録できます。
MappingMongoConverter
は、オブジェクト自体のマップを試みる前に、Spring コンバーターが特定のクラスを処理できるかどうかを確認します。パフォーマンスの向上やその他のカスタムマッピングのニーズのために、MappingMongoConverter
の通常のマッピング戦略を「ハイジャック」するには、まず Spring Converter
インターフェースの実装を作成し、それを MappingConverter
に登録する必要があります。
Spring 型変換サービスの詳細については、こちらのリファレンスドキュメントを参照してください。 |
ライティングコンバーター
次の例は、Person
オブジェクトから org.bson.Document
に変換する Converter
の実装を示しています。
import org.springframework.core.convert.converter.Converter;
import org.bson.Document;
public class PersonWriteConverter implements Converter<Person, Document> {
public Document convert(Person source) {
Document document = new Document();
document.put("_id", source.getId());
document.put("name", source.getFirstName());
document.put("age", source.getAge());
return document;
}
}
読み取りコンバーター
次の例は、Document
オブジェクトから Person
オブジェクトに変換する Converter
の実装を示しています。
public class PersonReadConverter implements Converter<Document, Person> {
public Person convert(Document source) {
Person p = new Person((ObjectId) source.get("_id"), (String) source.get("name"));
p.setAge((Integer) source.get("age"));
return p;
}
}
コンバーターの登録
class MyMongoConfiguration extends AbstractMongoClientConfiguration {
@Override
public String getDatabaseName() {
return "database";
}
@Override
protected void configureConverters(MongoConverterConfigurationAdapter adapter) {
adapter.registerConverter(new com.example.PersonReadConverter());
adapter.registerConverter(new com.example.PersonWriteConverter());
}
}