通常はUnsupportedOperationException
を目にすることはほとんど無い。変更不可能なコレクションに対してうっかりadd
やremove
をした場合、な程度と思われる。
なのだが、JPAでUnsupportedOperationException
に遭遇してしばらくハマったのでメモを残しておく。
やりたい事としては、1:Nのエンティティを永続化したあと、そのエンティティに対して子コレクションを削除する、というもの。
@Transactional
@Override
public void run(String... args) throws Exception {
Parent parent = new Parent(5L, "name", List.of(
new Child(new ChildId(101L, 1L), "aaa", null),
new Child(new ChildId(102L, 1L), "bbb", null)
));
em.persist(parent);
Parent parent2 = pr.getOne(5L);
System.out.println(parent == parent2); // true
List<Child> children = parent2.getChildren();
parent2.getChildren().clear();
em.persist(parent2);
}
Caused by: java.lang.UnsupportedOperationException: null
at java.base/java.util.ImmutableCollections.uoe(ImmutableCollections.java:71) ~[na:na]
at java.base/java.util.ImmutableCollections$AbstractImmutableCollection.clear(ImmutableCollections.java:77) ~[na:na]
at org.hibernate.collection.internal.PersistentBag.clear(PersistentBag.java:495) ~[hibernate-core-5.4.20.Final.jar:5.4.20.Final]
上記コードだとparent
とparent2
は同一インスタンスが返る。そうするとgetChildren
はList.of
の変更不可能コレクションが返されるため、clear
するとUnsupportedOperationException
になる。
実際のコードは永続化コンテキストに入れて取り出す部分が離れていたため、同一インスタンスが返ることにすぐ気付けなかった。永続化コンテキストに入れて取り出せばArrayList
とかの変更可能コレクションに詰めなおされる、と無意識に思い込んでいたので、上記のようなコードだと同一インスタンスが返される、てことになかなか気付けずハマってしまった。