本文介绍了UnsupportedOperationException合并 - 与hibernate和JPA保存多对多关系的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 29岁程序员,3月因学历无情被辞! 我已经建立了一个简单的多对多关系帐户:Hibernate的角色,但是当我尝试在单元测试中保存一个帐户并添加角色后,我得到一个UnsupportedOperationException: java.lang.UnsupportedOperationException $ b $ java.util.AbstractList.remove(AbstractList.java:144) at java。 util.AbstractList $ Itr.remove(AbstractList.java:360)$ b $在java.util.AbstractList.removeRange(AbstractList.java:559)在java.util.AbstractList.clear(AbstractList.java: at org.hibernate.type.CollectionType.replaceElements(CollectionType.java:502) at org.hibernate.type.CollectionType.replace(CollectionType.java:582) at org.hibernate.type.CollectionType.replaceElements .hibernate.type.TypeHelper.replace(TypeHelper.java:178) at org.hibernate.event.def.DefaultMergeEventListener.copyValues(DefaultMergeEventListener.java:563) at org.hibernate.event.def .DefaultMergeEventListener.entityIsPersistent(DefaultMergeEventListener.java:288) at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:261) at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:84) at org.hibernate.impl.SessionImpl.fireMerge(SessionImpl.java:867) at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:851) at org.hibernate.impl.SessionImpl .merge(SessionImpl.java:855) at org.hibernate.ejb.AbstractEntityManagerImpl.merge(AbstractEntityManagerImpl.java:686) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)在sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)在sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)在java.lang.reflect.Method.invoke(方法.java:597) at org.springframework.orm.jpa.SharedEntityManagerCreator $ SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:240) $ Proxy33.merge(Unknown Source) at org.springframework.data.jpa.repository.support.SimpleJpaRepository.save(SimpleJpaRepository.java:360) at .... JpaProvider.save(JpaProvider .java:161) at .... DataModelTest.testAccountRole(DataModelTest.java:47) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl .invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.junit.runners.model.FrameworkMethod $ 1.runReflectiveCall(FrameworkMethod.java:44) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)在org.jun it.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)在org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)。在org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:82)在org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)。在org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:240)在org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)。在org.junit.runners.ParentRunner $ 3.run(ParentRunner.java:193) org.junit.runners.ParentRunner $ 1.schedule(ParentRunner.java:52) org.junit.runners。 ParentRunner.runChildren(ParentRunner.java:191) org.junit.runners.ParentRunner.access $ 000(ParentRunner.java:42) org.junit.runners.P arentRunner $ 2.evaluate(ParentRunner.java:184)在org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)在org.springframework.test.context .junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) at org.junit.runners.ParentRunner.run(ParentRunner.java:236) at org.springframework.test.context.junit4 .SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:180)在org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)在org.eclipse.jdt.internal .junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) at org.eclipse .jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) 这里出了什么问题?我的实体设置是否有问题,或者这是休眠或JPA限制,迫使我将m:m关系拆分为3:1关系建模m:n关系表(我想避免它,因为它没有任何关系附加信息)。我在我的原型中建模了其他1:n实体,并且目前看起来效果很好...... 以下是我的设置,是否可能有问题受到赞赏。 实体(简体): @Entity @Table(name =account) public class Account extends AbstractPersistable< Long> { private static final long serialVersionUID = 627519641892468240L; 私人字符串用户名; @ManyToMany @JoinTable(name =account_roles, joinColumns = {@JoinColumn(name =account_id)}, inverseJoinColumns = {@ JoinColumn(name =role_id)}) private List< Role>角色; 公共列表< Role> getRoles(){返回角色; } public void setRoles(List< Role> roles){ this.roles = roles; $ b @Entity @Table(name =role) public class Role extends AbstractPersistable< Long> { private static final long serialVersionUID = 8127092070228048914L; 私人字符串名称; @ManyToMany @JoinTable(name =account_roles, joinColumns = {@ JoinColumn(name =role_id)}, inverseJoinColumns = {@ JoinColumn (name =account_id)}) private List< Account>账户; 公共列表<帐户> getAccounts(){返回帐户; } public void setAccounts(List< Account> accounts){ this.accounts = accounts; 单元测试: @TransactionConfiguration @ContextConfiguration({classpath:dw-security-context-test.xml}) @Transactional @RunWith(SpringJUnit4ClassRunner .class) public class DataModelTest { @Inject private AccountProvider accountProvider; @Inject 私人RoleProvider roleProvider; @Before public void mockAccountRolePermission(){ Account account = MockAccount.getSavedInstance(accountProvider); 角色角色= MockRole.getSavedInstance(roleProvider); } @Test public void testAccountRole(){ Account returnedac​​count = accountProvider.findAll()。get(0); returnedAccount.setRoles(Arrays.asList(roleProvider.findAll()。get(0))); accountProvider.save(returnedAccount); $ b code $ b MockAccount(与MockRole相同): public class MockAccount { public static Account getInstance(){ Account account =新账户(); account.setUsername(RandomData.rndStr(userName-,5)); 回报帐户; } public static Account getSavedInstance(AccountProvider accountProvider){ Account account = getInstance(); accountProvider.save(account); 回报帐户; } } 最后提供者: p> @Repository 公共类AccountProvider扩展了JpaProvider< Account,Long> {JP $ { $ b} JPAProvider只是包装了很多JPARepository方法至少在这种情况下它至关重要): public abstract class JpaProvider< T extends Object,ID extends Serializable>实现JpaRepository< T,ID> ;, JpaSpecificationExecutor< T>,QueryDslPredicateExecutor< T> { ... } 一个UnsupportedOperation? 解决方案这是因为你的 Arrays.asList(roleProvider.findAll()。get(0)) 一个不可修改的列表(实际上是一个不可调整的列表)。 Hibernate似乎期待一个可修改的列表。请尝试使用它: public void testAccountRole(){ Account returnedac​​count = accountProvider.findAll()。get 0); 列表< Role> list = new ArrayList< Role>(); list.add(roleProvider.findAll()。get(0)); returnedAccount.setRoles(list); accountProvider.save(returnedAccount); $ / code> 这个解决方案并不能解释为什么你得到另一个异常(可能是记录在Hibernate文档中),但它可能是一个有效的解决方法。 I've set up a simple many-to-many relationship account : role with Hibernate but when I try to save an account in a unit test after it has had its role added I get an UnsupportedOperationException:java.lang.UnsupportedOperationException at java.util.AbstractList.remove(AbstractList.java:144) at java.util.AbstractList$Itr.remove(AbstractList.java:360) at java.util.AbstractList.removeRange(AbstractList.java:559) at java.util.AbstractList.clear(AbstractList.java:217) at org.hibernate.type.CollectionType.replaceElements(CollectionType.java:502) at org.hibernate.type.CollectionType.replace(CollectionType.java:582) at org.hibernate.type.TypeHelper.replace(TypeHelper.java:178) at org.hibernate.event.def.DefaultMergeEventListener.copyValues(DefaultMergeEventListener.java:563) at org.hibernate.event.def.DefaultMergeEventListener.entityIsPersistent(DefaultMergeEventListener.java:288) at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:261) at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:84) at org.hibernate.impl.SessionImpl.fireMerge(SessionImpl.java:867) at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:851) at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:855) at org.hibernate.ejb.AbstractEntityManagerImpl.merge(AbstractEntityManagerImpl.java:686) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:240) at $Proxy33.merge(Unknown Source) at org.springframework.data.jpa.repository.support.SimpleJpaRepository.save(SimpleJpaRepository.java:360) at ....JpaProvider.save(JpaProvider.java:161) at ....DataModelTest.testAccountRole(DataModelTest.java:47) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20) at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28) at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74) at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:82) at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:240) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184) at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) at org.junit.runners.ParentRunner.run(ParentRunner.java:236) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:180) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)What's going wrong here? Is my entity setup faulty or is this a hibernate or JPA limitation forcing me to split apart my m:m relationship into 3 1:n relations modeling the m:n relationship table as well (which I wanted to avoid since it does not have any additional information). I've modeled other 1:n entities in my prototype and that seemed to work out nicely so far...Here's my setup, any thoughts whether it might be faulty are appreciated.Entities (simplified):@Entity@Table(name="account")public class Account extends AbstractPersistable<Long> { private static final long serialVersionUID = 627519641892468240L; private String username; @ManyToMany @JoinTable( name = "account_roles", joinColumns = { @JoinColumn(name = "account_id")}, inverseJoinColumns={@JoinColumn(name="role_id")}) private List<Role> roles; public List<Role> getRoles() { return roles; } public void setRoles(List<Role> roles) { this.roles = roles; } @Entity @Table(name="role") public class Role extends AbstractPersistable<Long> { private static final long serialVersionUID = 8127092070228048914L; private String name; @ManyToMany @JoinTable( name = "account_roles", joinColumns={@JoinColumn(name="role_id")}, inverseJoinColumns={@JoinColumn(name="account_id")}) private List<Account> accounts; public List<Account> getAccounts() { return accounts; } public void setAccounts(List<Account> accounts) { this.accounts = accounts; }Unit Test:@TransactionConfiguration@ContextConfiguration({"classpath:dw-security-context-test.xml"})@Transactional@RunWith(SpringJUnit4ClassRunner.class)public class DataModelTest { @Inject private AccountProvider accountProvider; @Inject private RoleProvider roleProvider; @Before public void mockAccountRolePermission(){ Account account = MockAccount.getSavedInstance(accountProvider); Role role = MockRole.getSavedInstance(roleProvider); } @Test public void testAccountRole(){ Account returnedAccount = accountProvider.findAll().get(0); returnedAccount.setRoles(Arrays.asList(roleProvider.findAll().get(0))); accountProvider.save(returnedAccount); }}MockAccount (same for MockRole):public class MockAccount { public static Account getInstance(){ Account account = new Account(); account.setUsername(RandomData.rndStr("userName-", 5)); return account; } public static Account getSavedInstance(AccountProvider accountProvider){ Account account = getInstance(); accountProvider.save(account); return account; }}And finally the Provider:@Repositorypublic class AccountProvider extends JpaProvider<Account, Long> {}where JPAProvider just wraps a lot of JPARepository methods (at least as far as it is important in this case):public abstract class JpaProvider<T extends Object, ID extends Serializable> implements JpaRepository<T, ID>, JpaSpecificationExecutor<T>, QueryDslPredicateExecutor<T> {...}Any Ideas on why the save might be an UnsupportedOperation? 解决方案 It is because of yourArrays.asList(roleProvider.findAll().get(0))This creates an unmodifiable list (in fact, a non-resizable list). Hibernate seems to expect a modifiable list. Try using this instead:public void testAccountRole(){ Account returnedAccount = accountProvider.findAll().get(0); List<Role> list = new ArrayList<Role>(); list.add(roleProvider.findAll().get(0)); returnedAccount.setRoles(list); accountProvider.save(returnedAccount);}This solution won't explain why exactly you got the other exception (might be documented in the Hibernate docs), but it might be a valid workaround. 这篇关于UnsupportedOperationException合并 - 与hibernate和JPA保存多对多关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云!
07-23 08:41