- Java レコードのサポート
- 検索オプション FindOption の追加
- @EntityResult でロックモードを指定可能に
- order-by 式での nulls first と nulls last サポート
- スタティックメタモデルに EntityType を追加
- スタティックメタモデルに名前付き定数の追加
- EntityManager.getReference(detachedEntity) の追加
- persistence.xml レス EntityManagerFactory 生成
- DDL 生成でオプション文字を追加可能に
- SchemaManager API の追加
- jakarta.persistence.schema-generation.database.action に validate が追加
- JavaSE 環境におけるJPAトランザクション操作
- JDBC 操作手段の提供
- EntityManagerFactory から Persistence Unit 名を取得可能に
- @Convert アノテーションの raw types を改善
- CriteriaQuery.subquery(EntityType) の追加
- 生成IDを @PrePersist 時に参照可能とする
- Query.getSingleResultOrNull() の追加
- @Table や @Column アノテーションでチェック制約とコメントが定義可能となった
- Entity/Embeddable classes/primary key classes の制限改定
- エンティティローカルな@SequenceGenerator/@TableGenerator
- @EnumeratedValueによるenum値のカスタムマッピング
- @Version プロパティのサポート型の追加
- java.time.Instant と java.time.Year のマッピングサポート追加
- equalTo() / notEqualTo() 式の追加
- PersistenceUnitUtil への初期化メソッド追加
- エンティティ名から EntityType を取得可能に
- エンティティのバージョン値取得
- 可変長の concat() 追加
- @NamedNativeQuery の結果セット定義
- 各種プロパティの定数化
- 述語のリストを引数に取るオーバーロードを追加
- 数値リテラル型の明確化
- JPQL演算/関数の追加
- その他の細かな変更
Jakarta Persistence 3.1 -> 3.2 の変更は Github Project で管理されている。
マイナーバージョンアップになっているが、数多くの変更点があるので、ここにまとめる(2023年11月現在)。
Java レコードのサポート
#400 allow Java records as embeddable types
Java レコードが @IdClass
と @Embeddable
として利用可能となった。
検索オプション FindOption の追加
#383 typesafe way to pass options and an EntityGraph to find() #65 Need another property to make lazy loading of attributes easy with entity graphs
FindOption
(これ自体は単なるマーカーインターフェース) が追加され、検索オプションなどを指定可能となった。
以下のようなオプションを
public enum CacheRetrieveMode implements FindOption { ... } public enum CacheStoreMode implements FindOption, RefreshOption { ... } public enum LockModeType implements FindOption, RefreshOption { ... } public enum PessimisticLockScope implements FindOption, RefreshOption, LockOption { ... } public class Timeout implements FindOption, RefreshOption, LockOption { ... }
以下の追加されたメソッドで指定可能。
public interface EntityManager extends AutoCloseable { <T> T find(Class<T> entityClass, Object primaryKey, FindOption... options); <T> T find(EntityGraph<T> entityGraph, Object primaryKey, FindOption... options); void lock(Object entity, LockModeType lockMode, LockOption... options); void refresh(Object entity, RefreshOption... options); }
これにより、以下のようにオプションを指定したクエリが可能となる。
Book book = em.find(Book.class, bookId, PESSIMISTIC_WRITE, CacheStoreMode.BYPASS, Timeout.ms(200));
@EntityResult でロックモードを指定可能に
#472 add lockMode to @EntityResult
EntityResult
に以下の属性が追加され、ロックモードを指定可能となった。
@Target({}) @Retention(RUNTIME) public @interface EntityResult { LockModeType lockMode() default LockModeType.OPTIMISTIC; }
order-by 式での nulls first と nulls last サポート
#76 Allow specification for null handling in order-by expressions (JPQL and Criteria API)
CriteriaBuilder
に以下が追加され、nulls first と nulls last を指定可能となった。
public interface CriteriaBuilder { Order asc(Expression<?> expression, Nulls nullPrecedence); Order desc(Expression<?> expression, Nulls nullPrecedence); }
Nulls
は以下の enum 値。
public enum Nulls { NONE, FIRST, LAST }
JPQL では、NULLS FIRST
/ NULLS LAST
を指定可能。
スタティックメタモデルに EntityType を追加
#475 add reference to ManagedType to static metamodel
スタティックメタモデルに以下のような EntityType
(ManagedType
) が追加されるようになり、Metamodel を介さずに直接取得可能となった。
EntityType<Book> bookType = Book_.class_;
Hibernate 実装からのポート。
スタティックメタモデルに名前付き定数の追加
#459 named queries, entity graphs, and result set mappings in static metamodel generation
スタティックメタモデルに名前付きクエリやエンティティグラフ、リザルトセットマッピングの定数が追加されるようになり、以下のように利用可能となった。
em.createQuery(Book_.QUERY_ALL_BOOKS).getResultList();
EntityManager.getReference(detachedEntity) の追加
#489 Add getReference(detachedEntity) to EntityManager
EntityManager
に参照取得の簡易メソッドが追加された。
public interface EntityManager extends AutoCloseable { public <T> T getReference(T entity); }
以下のコードのショートカットとして利用できる。
em.getReference(entity.getClass(),entity.getId())
persistence.xml レス EntityManagerFactory 生成
#358 Add XML-less config to replace persistence.xml and orm.xml #149 Simplify programmatic bootstrapping of an EntityManagerFactory #114 Allow full configuration of EntityManagerFactory without persistence.xml
PersistenceConfiguration
が追加され、以下のように persistence.xml
無しで EntityManagerFactory
の構築が可能となった。
DataSource datasource = (DataSource) new InitialContext().lookup("java:global/jdbc/MyOrderDB"); EntityManagerFactory emf = new PersistenceConfiguration() .name("OrderManagement") .jtaDataSource(datasource) .mappingFile("ormap.xml") .managedClass(Order.class) .managedClass(Customer.class) .createEntityManagerFactory();
DDL 生成でオプション文字を追加可能に
#353 support for conditional index
DDL 生成のアノテーションでオプション文字を指定可能となった。 例えば条件付きインデックスを以下のように指定。
@Index(name = "orders_unbilled_index ", columnList = "order_nr", options = "where billed is not true")
Table
Column
などの多くのアノテーションに options
属性が追加された。
SchemaManager API の追加
#399 SchemaManager #53 Schema generation with existing EMF
テスト時などにプログラムよりスキーマを管理できる SchemaManager
が追加された。
SchemaManager
は EntityManagerFactory
から取得できる。
public interface EntityManagerFactory extends AutoCloseable { SchemaManager getSchemaManager(); }
SchemaManager
では以下の操作が可能。
public interface SchemaManager { void create(boolean createSchemas); void drop(boolean dropSchemas); void validate() throws SchemaValidationException; void truncate(); }
jakarta.persistence.schema-generation.database.action に validate が追加
#68 update and/or validate javax.persistence.schema-generation.database.action
jakarta.persistence.schema-generation.database.action
へ validate
を追加(永続化ユニットに属するエンティティによってマッピングされたデータベースオブジェクトが、期待される定義を持っていることを検証)(この動作はプロバイダ固有)。
指定可能な値は、none
create
drop-and-create
drop
validate
となる。
JavaSE 環境におけるJPAトランザクション操作
#410 add methods for managing Session/Transaction lifecycle to SessionFactory #204 Consider adding convenience methods for wrapping transactions in Java SE environments
JavaSE 環境で JPAによるトランザクション操作を行う場合、以下のようなボイラープレートコードが必要であった。
var entityManager = factory.createEntityManager(); var transaction = entityManager.getTransaction(); try { transaction.begin(); // do some work... transaction.commit(); } catch (Exception e) { if (transaction.isActive()) { try { transaction.rollback(); } catch (Exception x) { e.addSuppressed(x); } } throw e; } finally { entityManager.close(); }
EntityManagerFactory
に以下のメソッドが追加され、
public interface EntityManagerFactory extends AutoCloseable { public void runInTransaction(Consumer<EntityManager> work); public <R> R callInTransaction(Function<EntityManager,R> work); }
以下のようにトランザクション操作が可能となった。
entityManagerFactory.runInTransaction(entityManager -> { User user = em.createQuery ("SELECT u FROM User u WHERE u.name=:name AND u.pass=:pass", User.class) .setParameter("name", args[0]) .setParameter("pass", args[1]) .getSingleResult(); user.setPassword(args[2]); })
JDBC 操作手段の提供
#432 easy access to the JDBC connection associated with the EM #483 javax.sql dependence
JPA の transaction/connection に関連付けてJDBCコードを実行する手段がなかったため、EntityManager
にアクセス手段を追加。
public interface EntityManager extends AutoCloseable { public <C> void runWithConnection(ConnectionConsumer<C> action); public <C, T> T callWithConnection(ConnectionFunction<C, T> function); }
以下のインターフェースを経由してコネクションに対する操作が可能となる。
public interface ConnectionConsumer<C> { void accept(C connection) throws Exception; }
public interface ConnectionFunction<C, T> { T apply(C connection) throws Exception; }
EntityManagerFactory から Persistence Unit 名を取得可能に
#530 Add accessor for PU name to EntityManagerFactory
以下のメソッドが追加され、Persistence Unit 名を取得できるようになった。
public interface EntityManagerFactory extends AutoCloseable { String getName(); }
これは、主にフレームワーク開発者やテスト、またはロギングでの使用を想定したもの。
@Convert アノテーションの raw types を改善
#56 @Convert annotation's converter property should be ...
以下の rawタイプを修正
@Repeatable(Converts.class) @Target({METHOD, FIELD, TYPE}) @Retention(RUNTIME) public @interface Convert { Class converter() default void.class; }
Class<? extends AttributeConverter> converter() default AttributeConverter.class;
この変更に合わせて、その他多くの rawタイプ使用箇所が修正された。
CriteriaQuery.subquery(EntityType) の追加
#71 Add subquery(EntityType) to javax.persistence.criteria.CriteriaQuery
EntityMode.MAP
などを使った動的なエンティティに対するサブクエリを作成する方法が無かったため、以下のメソッドが追加された。
public interface CommonAbstractCriteria { <U> Subquery<U> subquery(EntityType<U> type); }
生成IDを @PrePersist 時に参照可能とする
#133 Make TABLE-generated IDs available on PrePersist
生成されたID値を @PrePersist
メソッド内で利用可能となった(EclipseLinkでは従来より可能)。
利用可能なIDは、GenerationType.SEQUENCE
GenerationType.TABLE
GenerationType.UUID
で定義されたケースであり、GenerationType.IDENTITY
の場合は対象外。
これにより、以下のように生成されたID値を利用できる。
public class MyEntity { @PrePersist private void onPrePersist() { // generate a unique and unchangable value from *available* id. derived = String.format("%1$016x", id); } @GeneratedValue(..., strategy = GenerationType.TABLE) @Id private Long id; @Basic(optional = false) @Colum(..., nullable = false, updatable = false) @NotNull private String derived; }
Query.getSingleResultOrNull() の追加
#298 Add Query.getOptionalResult() or Query.getSingleResultOrNull()
Query.getSingleResult()
は結果が見つからない場合に NoResultException
を返すため、クライアントは、フロー制御のために例外処理の使用が強制されていたため、null
を返すメソッドが追加された。
public interface Query { Object getSingleResultOrNull(); }
TypedQuery
と StoredProcedureQuery
についても同様に追加。
なお、null
ではなく Optional
を返すべきかどうかは # Provide API returning Optional as an alternative to methods allowed to return null で議論が継続中。
@Table や @Column アノテーションでチェック制約とコメントが定義可能となった
#381 add comment and check to @Table and @Column #382 add check + comment to @Table + @Column
以下の属性が追加され、DDL用にチェック制約とコメントが定義可能となった。
@Target({METHOD, FIELD}) @Retention(RUNTIME) public @interface Column { CheckConstraint[] check() default {}; String comment() default ""; }
@Column
@JoinColumn
@JoinTable
@SecondaryTable
@Table
に対して追加された。
Entity/Embeddable classes/primary key classes の制限改定
#380 revisit restrictions on entity, embeddable, and primary key classes
@Entity
クラス- static inner クラスを許容
@Embeddable
クラス- static inner クラスを許容
- primary key クラス
- public であり serializable である必要が無くなった
- Java レコード可
エンティティローカルな@SequenceGenerator/@TableGenerator
#406 "entity local" @SequenceGenerator/@TableGenerator #511 fallback id generator
ID値を生成する際の @SequenceGenerator
と @TableGenerator
アノテーションは name
属性が必須であり、この名前は永続化ユニット全体に対してグローバルであった。
@Entity
クラスや @Id
に対して直接個別に @SequenceGenerator
や @TableGenerator
を指定することを考慮し、name
属性が任意化された。name
属性を省略した場合、IDジェネレータは対象のエンティティに対してローカルで定義されたものとして扱われるようになった。
これに関連し、@SequenceGenerator
などはパッケージに対して付与可能()となり、その場合、パッケージローカルなジェネレータを定義したものとして扱われる。
@EnumeratedValueによるenum値のカスタムマッピング
#47 custom value mappings for @Enumerated
@EnumeratedValue
アノテーションにてenumのマッピング値をカスタマイズ可能となった
enum Status { OPEN(0), CLOSED(1), CANCELLED(-1); @EnumeratedValue final int intValue; Status(int intValue) { this.intValue = intValue; } }
@EnumeratedValue
はマーカーアノテーションで、付与したフィールド値がマッピングに利用される。
@Version プロパティのサポート型の追加
#81 @Version Support for Temporal Types
@Version
プロパティとして使用可能な型に LocalDateTime
と Instant
が追加された。
int
, Integer
, short
, Short
, long
, Long
, LocalDateTime
, Instant
, Timestamp
java.time.Instant と java.time.Year のマッピングサポート追加
#163 Support for java.time.Instant
java.time.Instant
と java.time.Year
を JDBC基本マッピングへ追加
equalTo() / notEqualTo() 式の追加
#438 add Expression.equalTo() and Expression.notEqualTo()
以下が追加された。
public interface Expression<T> extends Selection<T> { Predicate equalTo(Expression<?> value); Predicate equalTo(Object value); Predicate notEqualTo(Expression<?> value); Predicate notEqualTo(Object value); }
PersistenceUnitUtil への初期化メソッド追加
#104 Enhance PersistenceUtil to allow initialization
以下のメソッド(initialize and unproxy)が追加された
public interface PersistenceUnitUtil extends PersistenceUtil { public <E> boolean isLoaded(E entity, Attribute<? super E,?> attribute); public void load(Object entity, String attributeName); public <E> void load(E entity, Attribute<? super E,?> attribute); public void load(Object entity); public boolean isInstance(Object entity, Class<?> entityClass); public <T> Class<? extends T> getClass(T entity); }
エンティティ名から EntityType を取得可能に
#85 Add methods in Metamodel interface to get entity by jpa name
Metamodel
に以下のメソッドが追加され、エンティティ名から EntityType を取得可能となった(を取得し、Metamodel
は EntityManager
から取得可能)。
public interface Metamodel { EntityType<?> entity(String entityName); }
以下の EntityType を、名前 car
にて取得することができる。
@Entity(name = "car") public class Car { ... }
エンティティのバージョン値取得
JAX-RSやサーブレットは任意のエンティティに対してETagヘッダをクライアントに送信したいが、サーブレットはそのエンティティのクラスを知らない(クラス名と主キー値がHTTPリクエストによって提供される場合のように)。このようなケースで利用するバージョン取得メソッドが PersistenceUnitUtil
に追加された。
public interface PersistenceUnitUtil extends PersistenceUtil { public Object getVersion(Object entity); }
可変長の concat() 追加
#408 concat() is a variadic function, but declared binary by CriteriaBuilder
可変長引数を受ける文字列連結 concat()
が追加された
public interface CriteriaBuilder { Expression<String> concat(List<Expression<String>> expressions); }
@NamedNativeQuery の結果セット定義
#471 allow nested result set mappings in @NamedNativeQuery
@NamedNativeQuery
でクエリを定義する場合、結果セットのマッピングは、@SqlResultSetMapping
にて別途定義する必要があり、かなり煩わしいため、@NamedNatiiveQuery
に直接マッピングを定義可能となった。
@NamedNativeQuery(name = “someQuery", query = "select TABLE_NAME as t_name, CURRENT_TIME as t_time from ALL_TABLES where TABLE_NAME = 'AUDIT_ACTIONS'“, entities = @EntityResult( entityClass = AllTables.class, fields = { @FieldResult(name = "tableName", column = "t_name"), @FieldResult(name = "daysOld", column = "t_time") }))
追加された属性は以下。
@Repeatable(NamedNativeQueries.class) @Target({TYPE}) @Retention(RUNTIME) public @interface NamedNativeQuery { Class<?> resultClass() default void.class; EntityResult[] entities() default {}; ConstructorResult[] classes() default {}; ColumnResult[] columns() default {}; }
@Target({}) @Retention(RUNTIME) public @interface EntityResult { Class<?> entityClass(); }
各種プロパティの定数化
#139 Provide constants for properties
各種のプロパティを PersistenceConfiguration
に定数として定義。
public class PersistenceConfiguration { /** Fully qualified name of the JDBC driver class. */ public static final String JDBC_DRIVER = "jakarta.persistence.jdbc.driver"; /** JDBC URL. */ public static final String JDBC_URL = "jakarta.persistence.jdbc.url"; ...
述語のリストを引数に取るオーバーロードを追加
#137 API improvements - pass List to where
可変長引数を取るメソッドに加え、以下のメソッドが追加された。
CriteriaBuilder.and(List<Predicate> restrictions); CriteriaBuilder.or(List<Predicate> restrictions); CriteriaQuery.where(List<Predicate> restrictions); CriteriaQuery.having(List<Predicate> restrictions);
数値リテラル型の明確化
#423 nail down semantics of arithmetic expressions and numeric literals
select 1.23 from Entity
のような結果のリテラル型を明確化。
L
(long)、D
(double)、F
(float) に加え、BI
(BigInteger) 、BD
(BigDecimal) を接尾辞に付けることでリテラルの型を指定可能となった。
JPQL演算/関数の追加
- 文字列連結
- #397 JPQL || operator for string concatenation
- JPQL にて
||
による文字列連結演算(concat()
)が可能となった
- cast() 関数
- #395 JPQL cast() function
- JPQL にて
cast(product.price as String)
のようなキャスト操作が可能となった
left()
right()
関数- #396 JPQL left() and right() functions
substring()
に加え、文字列切り出しにleft()
right()
が追加された
replace()
関数- #318 JPQL replace() function
- 文字列の置き換えに
replace()
が追加された
union
/union all
、intersect
/intersect all
、except
/except all
その他の細かな変更
- javax.annotation.processing.Generated への置き換え
- #501 Define usage of javax.annotation.processing.Generated
- Java SE 11 で
javax.annotation.Generated
が削除されたため、StaticMetamodel では、これに代わるjavax.annotation.processing.Generated
を利用可能とする変更
- spi.PersistenceUnitTransactionType の非推奨化
- #477 deprecate PersistenceUnitTransactionType
PersistenceConfiguration
導入に伴いjakarta.persistence.spi.PersistenceUnitTransactionType
を非推奨化。同名のjakarta.persistence.PersistenceUnitTransactionType
を利用
- エンティティ・リスナのコールバックメソッド仕様の明確化
- #464 tiny clarification for entity listeners
- エンティティ・リスナのコールバックメソッドが、
void <METHOD>(Object)
のようにオブジェクトを引数に取るよう記載されていた。エンティティ・タイプE
を引数に取るvoid <METHOD>(E)
に、記載が修正された
- 入力パラメータに対する仕様のリライト
- #103 Lift input parameter restrictions
- JPA仕様では、入力パラメータはWHERE句とHAVING句、または更新時のSET句でのみ利用可能となっている。これは広範囲なRDMSをサポートするための制限であるが、これはプロバイダーがサポートする必要のある仕様であり、サポートできる内容を制限するものではない。このことを仕様上明確に記載した という変更
- 8章 Entity Packaging の整形
- #469 aesthetic cleanups to chapter 8
- 8章 Entity Packaging の仕様が読みにくいため整形
- 各
GenerationType
に対応する型の明確化 - PersistenceConfiguration のクリーンアップ
- #481 Cleanup compile-time warnings introduced through recent additions
- コンストラクタの追加や、コンパイル時警告コードの改善
- enum Bindable.BindableType の JavaDoc 追加
- JPQL 内での大文字/小文字利用ルールを明確化
- Path.get() の誤った下限型境界を修正(MappedSuperclass)
java.util.Date
java.util.Calendar
などを非推奨化(java.time
系を推奨)- #402 deprecate support for Calendar, Date, Time, Timestamp
MapKeyTemporal
Temporal
TemporalType
も非推奨化
- EntityGraph と Subgraph の誤ったジェネリックシグネチャの修正
- getParameters() メソッドを CriteriaQuery から CommonAbstractCriteriaへ移動