Spring - hibernate: отдельная сущность передана для сохранения - PullRequest
2 голосов
/ 04 июля 2011

У меня есть следующий объект:

public class Constraint {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
int id;

String name;
String description;
String path;
int level;

@ManyToOne
@JoinColumn(name="parent_id")
Constraint parent;

@OneToMany
@JoinColumn(name="parent_id")
Set<Constraint> children;

@ManyToOne
@JoinColumn(name="type_id")
ConstraintType type; }

Как видите, эта таблица представляет собой древовидную структуру.Имея функции:

public List<Constraint> getAllDescendantsOfConstraint(Integer id) {
    StringBuilder sb = new StringBuilder(); 
    sb.append("WITH RECURSIVE tree as "); 
    sb.append("( "); 
    sb.append(" select * from constraints where id = :id "); 
    sb.append(" union all "); 
    sb.append(" select a.* from constraints a, tree b where a.parent_id = b.id "); 
    sb.append(") "); 
    sb.append("select * from tree where id <> :id ");

    Query q = entityManager.createNativeQuery(sb.toString(), Constraint.class);
    q.setParameter("id", id);
    return (List<Constraint>) q.getResultList();
}
@Transactional
public void setupPaths() {
    Query q = entityManager.createQuery("from Constraint", Constraint.class);
    @SuppressWarnings("unchecked")
    List<Constraint> constraints = (List<Constraint>) q.getResultList();

    for(Constraint c : constraints) {
        List<Constraint> descendants = getAllDescendantsOfConstraint(c.getId());
        for(Constraint d : descendants) {
            String tpath;
            if((tpath = d.getPath()) == null || d.getPath().equals(""))
                tpath = String.valueOf(c.getId());
            else
                tpath = d.getPath() + "." + String.valueOf(c.getId());
            d.setPath(tpath);
            entityManager.persist(d);
        }
    }
}

Если при вызове setupPaths я получаю «отдельную сущность, переданную для сохранения исключения».Если вместо entityManager.persist(d); я делаю:

d = entityManager.merge(d);
            d.setPath(tpath);

Ничего не происходит (данные не сохраняются в БД).Если вызов сброшен, я получаю отдельную сущность, переданную для сохранения исключения.Я подозреваю, что это как-то связано с тем, что я не загружаю родителей или детей?

edit: После дальнейшего тестирования, поскольку вышеприведенное кажется действительно подозрительным, кажется, что каждая сущность, которую я получаю от entityManager, независимо от того, как я получаюон (либо с em.find (MyObject.class, id, либо с любым видом запросов) отключается сразу после извлечения! Я вижу, что от вызова

em.contains(myObject)

, который всегда возвращает false. Проблема в том, что яиспользуйте ту же самую настройку в других проектах Spring с тем же сервером базы данных, и все работает нормально.

1 Ответ

3 голосов
/ 04 июля 2011

После (наконец) включения отладочной информации для Hibernate я увидел, что EntityManager закрывал сессию сразу после выборки, что было неправильно, поскольку я использовал аннотацию @Transactional. Наконец, кажется, что была проблема с STS (springsource toolsuite) и конфигурацией Spring, в частности:

<tx:annotation-driven mode="aspectj" transaction-manager="transactionManager"/>

Это предположительно с правильной настройкой maven

<plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>aspectj-maven-plugin</artifactId>
            <version>1.3.1</version>
            <dependencies>
                <dependency>
                    <groupId>org.aspectj</groupId>
                    <artifactId>aspectjrt</artifactId>
                    <version>${org.aspectj-version}</version>
                </dependency>
                <dependency>
                    <groupId>org.aspectj</groupId>
                    <artifactId>aspectjtools</artifactId>
                    <version>${org.aspectj-version}</version>
                </dependency>
            </dependencies>
            <executions>
                <execution>
                    <id>compile</id>
                    <configuration>
                        <source>${java-version}</source>
                        <target>${java-version}</target>
                        <verbose>false</verbose>
                        <outxml>true</outxml>
                        <aspectLibraries>
                            <aspectLibrary>
                                <groupId>org.springframework</groupId>
                                <artifactId>spring-aspects</artifactId>
                            </aspectLibrary>
                        </aspectLibraries>
                    </configuration>
                    <goals>
                        <goal>compile</goal>
                    </goals>
                    </execution>
            </executions>
            <configuration>
                <outxml>true</outxml>
                <source>${java-version}</source>
                <target>${java-version}</target>
            </configuration>
        </plugin>

должен позаботиться о ткачестве во время компиляции, но что-то пошло не так. Я использовал плагин 1.2, когда я изменил его на 1.3.1, он волшебным образом работал.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...