У меня есть бизнес-логика, которая требует

1) выполните некоторые действия, такие как подсчет или «найти идентификатор первого элемента с полем больше, чем a», то есть выполните некоторые действия для чтения над объектом A. Подсчет или поиск включает более 25 элементов, поэтому это влияет на многие группы сущностей. 2) затем выполните некоторые действия с другим объектом B и сохраните измененный объект 3) теперь я изменяю единственный объект для объекта A и хочу его сохранить

Если я не использую Spring @Transactional в своем методе, я получил объект с идентификатором «A @ someHash», управляемый другим диспетчером объектов при вызове 3). Согласно 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>
        <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>

И плагин улучшения

  <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>
0
Ilya Yevlampiev 13 Ноя 2017 в 00:47

1 ответ

Лучший ответ

Я не могу сказать, что получил подробное представление о том, что происходит глубоко в реализации Google JPA и получил опубликованное мной исключение. Вместо этого я решил глобальную проблему, с которой столкнулся. Я считаю, что вы сталкиваетесь с той же проблемой, если имеете дело с исключением. Я попытался обойти ограничения на изменение некоторого незначительного количества объектов в транзакциях и чтение некоторых объектов, где транзакции не нужны (поскольку не транзакционное обновление не выполняется из-за исключений, указанных выше).

Проблема решена архитектурно: 1) вы должны создать отдельные методы на уровне обслуживания для чтения сущностей или получения счетчиков и НЕ делать их транзакционными 2) создать отдельные методы на уровнях обслуживания, получая результаты нетранзакционных методов в качестве параметров и обновляя сущности; сделайте эти методы транзакционными 3) на уровне контроллера или на вашем настраиваемом уровне ниже контроллера, но выше службы, вызывайте эти методы отдельно!

Моя ошибка заключалась в том, что я предполагал, что аннотация Spring @Transactional имеет смысл, даже когда метод с @Transactional вызывается из другого метода с @Transactionl. Это неправильно: из-за Аспектной природы аннотации они имеют смысл только в том случае, если методы вызываются из внешнего объекта класса. Таким образом, в моих примерах я получил весь вызов в рамках единственной транзакции (за исключением слишком большого количества сущностей) или ни в одной транзакции (таким образом, получение объекта с идентификатором ... управляется другим диспетчером объектов). Так что разделение нетранзакционного поведения и транзакционного поведения на разные методы и их вызов извне помогло мне.

1
Ilya Yevlampiev 19 Ноя 2017 в 13:50