1

遅延初期化に問題があります。解決策が見つかりません。

例外:

[pool-1-thread-12] ERROR:12:20:14.840 o.h.LazyInitializationException - failed to lazily initialize a collection of role: de.beeld.forges.domain.Server.applications, no session or session was closed
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: de.beeld.forges.domain.Server.applications, no session or session was closed
    at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:380)
    at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:372)
[pool-2-thread-1] ERROR:12:20:14.840 o.s.s.support.MethodInvokingRunnable - Invocation of method 'readStatusCache' on target class [class de.beeld.forges.task.annotation.ScheduledProcessor$$EnhancerByCGLIB$$ee649dc3] failed
java.util.ConcurrentModificationException: null
    at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)
    at java.util.AbstractList$Itr.next(AbstractList.java:343)

hibernate.xml

<!-- Hibernate SessionFactory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"
    p:dataSource-ref="standardDataSource" p:lobHandler-ref="defaultLobHandler">
    <property name="annotatedClasses">
        <list>
            <value>de.beeld.forges.domain.Server</value>
            <value>de.beeld.forges.domain.Application</value>
            <value>de.beeld.forges.domain.Forge</value>
        </list>
    </property>
</property>
</bean>
<bean id="defaultLobHandler" class="org.springframework.jdbc.support.lob.DefaultLobHandler" />
<!-- Read in DAOs from the hibernate package -->
<context:component-scan base-package="de.beeld.forges.dao" />
<bean id="transactionManager"
    class="org.springframework.orm.hibernate3.HibernateTransactionManager"
    p:sessionFactory-ref="sessionFactory" />

<bean id="transactionTemplate"
    class="org.springframework.transaction.support.TransactionTemplate">
    <property name="transactionManager" ref="transactionManager" />
</bean>

<tx:annotation-driven transaction-manager="transactionManager" />
    <context:component-scan base-package="de.beeld">
    <context:exclude-filter expression="org.springframework.stereotype.Controller"
        type="annotation" />
    <context:exclude-filter expression="org.springframework.stereotype.Repository"
        type="annotation" />
</context:component-scan>
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />

readStatusCache メソッド:

public void readStatusCache() {
    String execCommand = "java -jar ...";
    List<Future<Map<Long, Integer>>> list = new ArrayList<Future<Map<Long, Integer>>>();
    String serverName = null;
    for (Server server : serviceFacade.getServers()) {
        serverName = server.getName();

        Callable<Map<Long, Integer>> worker = new ApplicationStatusReader2(server.getApplications(),
                sshConnector, execCommand, serverName);
        Future<Map<Long, Integer>> submit = this.serviceFacade.getExecutor().submit(worker);
        list.add(submit);
    }

    for (Future<Map<Long, Integer>> future : list) {
        //do stuff
    }
}

サーバー.java

@Entity
@org.hibernate.annotations.Entity(dynamicUpdate = true)
public class Server implements DomainObject, Comparable<Server> {
private static final long serialVersionUID = -8920952435734596243L;

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

@Column(unique = true, nullable = false)
@NotEmpty
private String name;

@Column(nullable = false)
@NotEmpty
@Pattern(regexp = "^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])$", message = "The ip must be in format xxx.xxx.xxx.xxx")
private String ip;

@Column(nullable = false)
@NotEmpty
private String fqdn;

@OneToMany(mappedBy = "server", fetch = FetchType.LAZY)
private List<Application> applications;

@Version
private int version;

//getter and setter
}

アプリケーション.java

@Entity
public class Application implements DomainObject {
private static final long serialVersionUID = -8127137156319959239L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
private Server server;
@Column(nullable = false)
@NotEmpty
private String name;
@Column(nullable = false)
@NotEmpty
private String location;
@Column(nullable = false)
@NotEmpty
private String binDir;
private String confDir;
private boolean isContainer = false;
private String containerDir;
private String startup = "startup.sh";
private String shutdown = "shutdown.sh";
@ManyToOne(fetch = FetchType.LAZY)
@Fetch(FetchMode.JOIN)
private Forge forge;
@ManyToOne(fetch = FetchType.LAZY)
@Fetch(FetchMode.JOIN)
private Application parent;
@OneToMany(mappedBy = "parent", fetch = FetchType.LAZY)
private List<Application> offsprings;
@NotEmpty
private String blueprint;
private Integer replaceable = 0;
private Integer running = 0;
@Version
private int version;

//getter and setter
}

サーバーからアプリケーションのリストを読み取れない理由がよくわかりません

誰かがそれを助けることができれば、それは素晴らしいことです.

4

3 に答える 3

4

おそらく、アプリケーション コレクションを遅延読み込みに設定しているためです。そのため、serviceFacade.getServers() への最初の呼び出しから戻ると、サーバーのリストをフェッチするために使用されたセッションが開いていないことが推測されます。

その結果、アプリケーションを反復処理すると、セッションが閉じられ、コレクションの実際の内容を読み込めなくなります。

次の 3 つの可能性があります。

  1. セッションを開いたままにします (hibernate セッションをスレッドにバインドするための Google、または readStatusCache メソッドが Spring 管理オブジェクトにある場合は、@Transactional アノテーション、またはそれが呼び出されるエントリ ポイントを追加するだけです)。
  2. アプリケーション コレクションをイーガー ロードに変更する
  3. セッションがまだ開いている間に、dao レイヤーにアプリケーション コレクションを完全に初期化させます (Hibernate.initialize メソッドを参照)。
于 2012-06-08T15:27:25.227 に答える
0

同じ例外が発生したときの解決策は、@Transactional アノテーションをコントローラーのメソッドに追加することでした。

于 2014-06-30T11:46:28.327 に答える
0

二つのループ

   for (Server server : serviceFacade.getServers()) {
        serverName = server.getName();

        Callable<Map<Long, Integer>> worker = new ApplicationStatusReader2(server.getApplications(),
                sshConnector, execCommand, serverName);
        Future<Map<Long, Integer>> submit = this.serviceFacade.getExecutor().submit(worker);
        list.add(submit);
    }

    for (Future<Map<Long, Integer>> future : list) {
        //do stuff
    }

2 つの別々のスレッドによって同時に呼び出されています。メソッドを同期することで、これが当てはまるかどうかを確認できますreadStatusCache()。ただし、これは Spring レイヤーで行う必要があります。取引等は正しく利用できていますか?

春と休止状態のスレッドセーフの詳細については、この回答をお読みください。Webアプリで使用されるSpring-Hibernate、スレッドセーフなセッション管理の戦略は何ですか

于 2012-06-08T11:15:52.467 に答える