英文:
org.apache.geode.cache.UnsupportedOperationInTransactionException
问题
在建立多对多关系时,在更新缓存条目时遇到以下异常。
org.apache.geode.cache.UnsupportedOperationInTransactionException: 在分布式事务期间,预期目标=192.168.1.2(cacheServer2:7756)<v1>:41001的大小为1 {[/__PR/_B__User_101]},但实际得到了2 {[[], [DistTxThinEntryState: ,regionVersion=2 ,tailKey=440 ,memberID=null]]}
at org.apache.geode.internal.cache.DistTXStateProxyImplOnCoordinator.populateEntryEventMap(DistTXStateProxyImplOnCoordinator.java:576)
at org.apache.geode.internal.cache.DistTXStateProxyImplOnCoordinator.doPrecommit(DistTXStateProxyImplOnCoordinator.java:484)
at org.apache.geode.internal.cache.DistTXStateProxyImplOnCoordinator.commit(DistTXStateProxyImplOnCoordinator.java:88)
at org.apache.geode.internal.cache.TXManagerImpl.commit(TXManagerImpl.java:426)
at com.trendcore.cache.peertopeer.service.UserServiceImpl.attachRoleToUser(UserServiceImpl.java:108)
at com.trendcore.cache.peertopeer.CacheApplication.attachRoleToUser(CacheApplication.java:121)
缓存配置 -> 这是具有2个区域的点对点配置。
Properties properties = new Properties();
properties.setProperty("locators", "localhost[13489]");
properties.setProperty("mcast-address", "224.0.0.0");
properties.setProperty("mcast-port", "0");
properties.setProperty(NAME, "cacheServer1");
CacheFactory cacheFactory = new CacheFactory(this.cacheConfiguration);
cache = cacheFactory.create();
用户区域
RegionFactory<Long, User> regionFactory = this.cache.createRegionFactory(RegionShortcut.PARTITION);
userRegion = regionFactory.create(USER_REGION);
角色区域
RegionFactory<Long, Role> regionFactory = this.cache.createRegionFactory(RegionShortcut.PARTITION);
roleRegion = regionFactory.create(ROLE_REGION);
用户模型位于用户区域
public class User implements Serializable{
private Long id;
private String username;
private Map<Long,Object> roles;
//Getters , Setters
public void addRole(Long roleId) {
roles.put(roleId,null);
}
}
角色模型位于角色区域
public class Role implements Serializable {
private Long id;
private String roleName;
//getters , setters
}
用户和角色通过以下代码插入到各自的区域中。
插入用户:
public void insertUser(User user) {
CacheTransactionManager cacheTransactionManager = cache.getCacheTransactionManager();
try {
cacheTransactionManager.begin();
userRegion.put(user.getId(), user);
cacheTransactionManager.commit();
} catch (Exception e) {
cacheTransactionManager.rollback();
}
}
插入角色:
public void insertRole(Role role) {
CacheTransactionManager cacheTransactionManager = cache.getCacheTransactionManager();
try {
cacheTransactionManager.begin();
roleRegion.put(role.getId(), role);
cacheTransactionManager.commit();
} catch (Exception e) {
cacheTransactionManager.rollback();
}
}
当将任何角色ID放入现有缓存用户对象时,将抛出上述异常。
将角色附加到用户:
public void attachRoleToUser(Long userId, Long roleId) {
Region<Long, User> userRegion = cache.getRegion(USER_REGION);
Region<Long, Role> roleRegion = cache.getRegion("Role");
CacheTransactionManager cacheTransactionManager = cache.getCacheTransactionManager();
try {
cacheTransactionManager.setDistributed(true);
cacheTransactionManager.begin();
Role role = roleRegion.get(roleId);
if (role != null) {
User user = userRegion.get(userId);
user.addRole(role.getId());
userRegion.put(userId,user);
}
cacheTransactionManager.commit();
} catch (Exception e) {
try {
cacheTransactionManager.rollback();
}catch (Exception rbe){
}
throw new RuntimeException(e);
}
}
在这种情况下,任何指导将不胜感激。
英文:
Getting below exception while updating entry in the cache while establishing Many to Many relation.
org.apache.geode.cache.UnsupportedOperationInTransactionException: Expected size of 1 {[/__PR/_B__User_101]} for target=192.168.1.2(cacheServer2:7756)<v1>:41001 during a distributed transaction but got 2 {[[], [DistTxThinEntryState: ,regionVersion=2 ,tailKey=440 ,memberID=null]]}
at org.apache.geode.internal.cache.DistTXStateProxyImplOnCoordinator.populateEntryEventMap(DistTXStateProxyImplOnCoordinator.java:576)
at org.apache.geode.internal.cache.DistTXStateProxyImplOnCoordinator.doPrecommit(DistTXStateProxyImplOnCoordinator.java:484)
at org.apache.geode.internal.cache.DistTXStateProxyImplOnCoordinator.commit(DistTXStateProxyImplOnCoordinator.java:88)
at org.apache.geode.internal.cache.TXManagerImpl.commit(TXManagerImpl.java:426)
at com.trendcore.cache.peertopeer.service.UserServiceImpl.attachRoleToUser(UserServiceImpl.java:108)
at com.trendcore.cache.peertopeer.CacheApplication.attachRoleToUser(CacheApplication.java:121)
Cache Configuration -> It's Peer to Peer configration with 2 regions.
Properties properties = new Properties();
properties.setProperty("locators", "localhost[13489]");
properties.setProperty("mcast-address", "224.0.0.0");
properties.setProperty("mcast-port", "0");
properties.setProperty(NAME, "cacheServer1");
CacheFactory cacheFactory = new CacheFactory(this.cacheConfiguration);
cache = cacheFactory.create();
User Region
RegionFactory<Long, User> regionFactory = this.cache.createRegionFactory(RegionShortcut.PARTITION);
userRegion = regionFactory.create(USER_REGION);
Role Region
RegionFactory<Long, Role> regionFactory = this.cache.createRegionFactory(RegionShortcut.PARTITION);
roleRegion = regionFactory.create(ROLE_REGION);
User model resides in User region
public class User implements Serializable{
private Long id;
private String username;
private Map<Long,Object> roles;
//Getters , Setters
public void addRole(Long roleId) {
roles.put(roleId,null);
}
}
Role model resides in Role region
public class Role implements Serializable {
private Long id;
private String roleName;
//getters , setters
}
Users and roles are inserted in the respective regions using below code.
public void insertUser(User user) {
CacheTransactionManager cacheTransactionManager = cache.getCacheTransactionManager();
try {
cacheTransactionManager.begin();
userRegion.put(user.getId(), user);
cacheTransactionManager.commit();
} catch (Exception e) {
cacheTransactionManager.rollback();
}
}
public void insertRole(Role role) {
CacheTransactionManager cacheTransactionManager = cache.getCacheTransactionManager();
try {
cacheTransactionManager.begin();
roleRegion.put(role.getId(), role);
cacheTransactionManager.commit();
} catch (Exception e) {
cacheTransactionManager.rollback();
}
}
When any roleIds are put in existing cache user object then above exception is thrown.
public void attachRoleToUser(Long userId, Long roleId) {
Region<Long, User> userRegion = cache.getRegion(USER_REGION);
Region<Long, Role> roleRegion = cache.getRegion("Role");
CacheTransactionManager cacheTransactionManager = cache.getCacheTransactionManager();
try {
cacheTransactionManager.setDistributed(true);
cacheTransactionManager.begin();
Role role = roleRegion.get(roleId);
if (role != null) {
User user = userRegion.get(userId);
user.addRole(role.getId());
userRegion.put(userId,user);
}
cacheTransactionManager.commit();
} catch (Exception e) {
try {
cacheTransactionManager.rollback();
}catch (Exception rbe){
}
throw new RuntimeException(e);
}
}
Any guidance in this case will be appreciated.
答案1
得分: 1
1.) 分布式事务目前仅适用于已复制的区域。
2.) 在第二种情况下,现在事务边界只包含一个区域,因此不需要协同定位。
3.) 我认为在您的第一种情况中,您将两个分区区域作为事务的一部分,这需要这些区域进行协同定位(相关数据必须存在于节点上,因此也有可能其中一个是复制区域,另一个是分区区域)。
英文:
1.) Distributed transactions only work for Replicated Regions at this point.
2.) In the second case, only one region is now in the transaction boundary, so co-location is not needed.
3.) I think in your first case, you had two partitioned regions as part of a transaction, this requires the regions to be co-located ( the relevant data has to exist on the node, so it's also possible that one is a replicated region and the other is a partitioned)
答案2
得分: 0
已更改,将用户附加到角色的方法如下,没有异常。
Region<Long, User> userRegion = cache.getRegion(USER_REGION);
Region<Long, Role> roleRegion = cache.getRegion("Role");
CacheTransactionManager cacheTransactionManager = cache.getCacheTransactionManager();
try {
// 这是在事务边界之外获取角色信息的变化。
Role role = roleRegion.get(roleId);
cacheTransactionManager.setDistributed(true);
cacheTransactionManager.begin();
// 这一行导致下面的异常
// org.apache.geode.cache.UnsupportedOperationInTransactionException: 期望大小为 1 {[/__PR/_B__User_101]}
// Role role = roleRegion.get(roleId);
if (role != null) {
User user = userRegion.get(userId);
user.addRole(role.getId());
userRegion.put(userId, user);
}
cacheTransactionManager.commit();
} catch (Exception e) {
try {
if (cacheTransactionManager != null && cacheTransactionManager.exists())
cacheTransactionManager.rollback();
} catch (Exception rbe) {
}
throw new RuntimeException(e);
}
并且没有异常。
然而,需要更多关于以下几点的信息。
- 事务已设置为分布式。
- 在此情况下,用户和角色两个区域都参与了事务,导致事务失败,出现 UnsupportedOperationInTransactionException 异常。
- 分布式事务在多个区域上不起作用。
英文:
Changed, attach user to role method to below and there is no exception.
Region<Long, User> userRegion = cache.getRegion(USER_REGION);
Region<Long, Role> roleRegion = cache.getRegion("Role");
CacheTransactionManager cacheTransactionManager = cache.getCacheTransactionManager();
try {
//This is change fetching role information outside transaction boundry.
Role role = roleRegion.get(roleId);
cacheTransactionManager.setDistributed(true);
cacheTransactionManager.begin();
//This line is causing below exception
//org.apache.geode.cache.UnsupportedOperationInTransactionException: Expected size of 1 {[/__PR/_B__User_101]}
//Role role = roleRegion.get(roleId);
if (role != null) {
User user = userRegion.get(userId);
user.addRole(role.getId());
userRegion.put(userId,user);
}
cacheTransactionManager.commit();
} catch (Exception e) {
try {
if(cacheTransactionManager != null && cacheTransactionManager.exists())
cacheTransactionManager.rollback();
}catch (Exception rbe){
}
throw new RuntimeException(e);
}
And there is no exception.
However need more information on below points.
- Transaction was set to distributed.
- User and Role both regions were involved in this case transaction failed, with exception UnsupportedOperationInTransactionException
- Distributed transactions are not working on multiple regions.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论