我如何通过获取一些不由对象管理器管理的值来避免NucleusUserException [英] How I can avoid NucleusUserException by obtaining some value not managed by an Object Manager

查看:138
本文介绍了我如何通过获取一些不由对象管理器管理的值来避免NucleusUserException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有商业逻辑,需要
$ b $ 1)做一些动作,如count或'查找顶部1项大于a的项目ID',即做一些阅读对实体A的操作。计数或查找涉及超过25个项目,因此它会影响许多实体组。
2)然后在另一个实体B上执行一些操作并坚持修改后的实体
3)现在我更改实体A的唯一对象并且想要坚持它

如果我没有在我的方法上使用Spring @Transactional,那么在调用3时,获得具有IDA @ someHash的Object由不同的Object Manager管理。根据System.out.println(NucleusJPAHelper.getObjectState(busRouteToCheck));该对象处于持久状态



如果我使用Spring @Transactional将整个方法放在一起,就会得到在单个事务中打开的实体组太多



我可以如何强制1)的结果不被对象管理器管理,最终获得一些Long值和过程3)像我第一次在我的方法中处理A一样。最后,我需要读取多个实体组的项目,并且只在交易中更新两个项目。



我试图解决的问题:1)将整个方法分成3其他2没有@Transaction,1和3有@Transaction;这里我仍然有NucleusUserException; 2)在相同的条件下,我尝试使用2个不同的事务管理器,首先调用只读调用(方法1)并使用第二个方法(方法3)写入。



是否有明确的方法来管理对象管理器?



使用的依赖项包括:

 < dependency> 
< groupId> org.datanucleus< / groupId>
< artifactId> datanucleus-api-jdo< / artifactId>
< version> 3.1.1< / version>
< /依赖关系>
< dependency>
< groupId> org.datanucleus< / groupId>
< artifactId> datanucleus-api-jpa< / artifactId>
< version> 3.1.1< / version>
< /依赖关系>
< dependency>
< groupId> com.google.appengine.orm< / groupId>
< artifactId> datanucleus-appengine< / artifactId>
< version> 2.1.2< / version>
< /依赖关系>
< dependency>
< groupId> org.datanucleus< / groupId>
< artifactId> datanucleus-core< / artifactId>
< version> 3.1.1< / version>
< /依赖关系>

和增强器插件是

 < plugin> 
< groupId> org.datanucleus< / groupId>
< artifactId> maven-datanucleus-plugin< / artifactId>
< version> 3.1.3< / version>
<配置>
<! - 确保这个路径包含你的持久化类! - >
<! - < mappingIncludes> ** / domain / *。class< / mappingIncludes> - >
<! - < persistenceUnitName> transactions - 可选< / persistenceUnitName> - >
<详细>真< /详细>
< api> JPA< / api>
<! - < mappingIncludes> com / appspot / Player.class< / mappingIncludes> - >
<! - < metadataIncludes> com / appspot / Player.class< / metadataIncludes> - >
< fork> false< / fork>
< / configuration>
<执行次数>
<执行>
<阶段>程序类< /阶段>
<目标>
< goal>增强< / goal>
< /目标>
< /执行>
< /执行次数>
<依赖关系>
<! - <依赖关系>
< groupId> asm< / groupId>
< artifactId> asm-commons< / artifactId>
< version> 3.3.1< / version>
< /依赖关系> - >
< dependency>
< groupId> org.datanucleus< / groupId>
< artifactId> datanucleus-api-jpa< / artifactId>
< version> 3.1.1< / version>
< /依赖关系>
< dependency>
< groupId> org.datanucleus< / groupId>
< artifactId> datanucleus-core< / artifactId>
< version> 3.1.1< / version>
< /依赖关系>
< dependency>
< groupId> org.datanucleus< / groupId>
< artifactId> datanucleus-enhancer< / artifactId>
< version> 3.1.1< / version>
< /依赖关系>
< /依赖关系>
< / plugin>


解决方案

我不能说我有详细的了解发生在谷歌的JPA实施深处,并获得我发布的异常。相反,我已经解决了我面临的全球性问题。如果处理例外情况,我相信你会面临同样的问题。我尝试解决在更改交易中一些次要对象数量和读取可能不需要事务的对象(由于上述异常导致事务更新失败)的限制。

这个问题在体系结构上得到了解决:1)您应该在服务层创建单独的方法来读取实体或获取计数并且不使它们成为事务性的2)在服务层获取非事务性方法的结果作为参数并更新实体;使这些方法事务3)在控制器层或控制器下方的自定义层中,但在服务之上调用这些方法!



我的错是我认为Spring的@即使在使用@Transactionl从另一个方法调用带有@Transactional的方法时,事务性注释也是有意义的。这是错误的:由于注释的Aspect性质,只有当方法从外部类对象中调用时才有意义。所以在我的例子中,我把整个调用放在唯一的事务中(具有太多的实体异常),或者在没有事务的情况下(因此使得具有id的对象...由不同的对象管理器管理)。因此,将非事务行为和事务行为分离到不同的方法并从外部调用它们是非常有帮助的。


I have the business logic that requires

1) do some action like count or 'find id of top 1 item with field greater than a', i.e do some reading actions over entity A. The count or find involves more than 25 items, so it makes many Entity groups be affected. 2) then do some action on another entity B and persist the changed entity 3) now I change the only object for entity A and want to persist it

If I don't use Spring @Transactional on my method I got Object with id "A@someHash" is managed by a different Object Manager when calling 3). Ассording to System.out.println(NucleusJPAHelper.getObjectState(busRouteToCheck)); the object is in persistent state

If I use Spring @Transactional put over the whole method, I got "too many Entity groups opened in the single transaction"

How I can force results of 1) not be managed by Object Manager, to obtain finally some Long value and process 3) like I deal with A the first time in my method. Finally I need items of multiple entity groups be read and only two be updated within the transaction.

What I have tried to work around: 1) dividing use the whole method into 3 others where 2 is without @Transaction, 1 and 3 are having @Transaction; here I still got NucleusUserException; 2) with the same condition I tried to use of 2 different transaction managers with first making calls for read-only calls (method 1) and writing with the second (method 3).

Is there any explicit way to govern the Object Manager?

Dependenciies used are:

   <dependency>
            <groupId>org.datanucleus</groupId>
            <artifactId>datanucleus-api-jdo</artifactId>
            <version>3.1.1</version>
        </dependency>
        <dependency>
            <groupId>org.datanucleus</groupId>
            <artifactId>datanucleus-api-jpa</artifactId>
            <version>3.1.1</version>
        </dependency>
        <dependency>
            <groupId>com.google.appengine.orm</groupId>
            <artifactId>datanucleus-appengine</artifactId>
            <version>2.1.2</version>
        </dependency>
        <dependency>
            <groupId>org.datanucleus</groupId>
            <artifactId>datanucleus-core</artifactId>
            <version>3.1.1</version>
        </dependency>

and enhancer plugin is

  <plugin>
                <groupId>org.datanucleus</groupId>
                <artifactId>maven-datanucleus-plugin</artifactId>
                <version>3.1.3</version>
                <configuration>
                    <!-- Make sure this path contains your persistent classes! -->
                    <!--<mappingIncludes>**/domain/*.class</mappingIncludes>-->
                    <!--<persistenceUnitName>transactions-optional</persistenceUnitName>-->
                    <verbose>true</verbose>
                    <api>JPA</api>
                    <!--<mappingIncludes>com/appspot/Player.class</mappingIncludes>-->
                    <!--<metadataIncludes>com/appspot/Player.class</metadataIncludes>-->
                    <fork>false</fork>
                </configuration>
                <executions>
                    <execution>
                        <phase>process-classes</phase>
                        <goals>
                            <goal>enhance</goal>
                        </goals>
                    </execution>
                </executions>
                <dependencies>
                    <!--<dependency>
                        <groupId>asm</groupId>
                        <artifactId>asm-commons</artifactId>
                        <version>3.3.1</version>
                    </dependency>-->
                    <dependency>
                        <groupId>org.datanucleus</groupId>
                        <artifactId>datanucleus-api-jpa</artifactId>
                        <version>3.1.1</version>
                    </dependency>
                    <dependency>
                        <groupId>org.datanucleus</groupId>
                        <artifactId>datanucleus-core</artifactId>
                        <version>3.1.1</version>
                    </dependency>
                    <dependency>
                        <groupId>org.datanucleus</groupId>
                        <artifactId>datanucleus-enhancer</artifactId>
                        <version>3.1.1</version>
                    </dependency>
                </dependencies>
            </plugin>

解决方案

I can't say I got the detailed understanding of something occurring deep into google's JPA implementation and obtaining the exception I have posted. Instead I have resolved the global problem I have faced with. I believe you are facing the same problem if dealing with the exception. I tried to work around the limitations on changing some minor number of Objects within transactions and reading of may objects, where transactions are not needed (since not transactional update is failing due to exceptions said above).

The problem is solved architecturally: 1) you should create separate methods in service layer for reading the entities or obtaining counts and NOT making them transactional 2) create separate methods in the service layers obtaining the results of non-transactional methods as parameters and updating the entities; make those methods transactional 3) in controller layer or in your custom layer below the controller but above the service call those methods separately!

My fault was that I supposed that Spring's @Transactional annotation makes sense even when the method with @Transactional is called from another method withot @Transactionl. That is wrong: due to Aspect nature of the annotation, they make sense only if the methods are called from outside class object. So in my examples I got the whole call being within the only transaction (with too many entities exception) or within none transaction (thus getting the Object with id ... is managed by a different Object Manager). So separating non-transactional behaviour and transactional behaviour to the different methods and calling them from outside helped me.

这篇关于我如何通过获取一些不由对象管理器管理的值来避免NucleusUserException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆