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)

休眠.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() 的初始调用返回时,我的猜测是您不再打开用于获取服务器列表的会话。

结果,当您遍历应用程序时,会话已关闭,因此无法加载集合的实际内容。

你有三种可能:

  1. 保持会话打开(谷歌用于将休眠会话绑定到线程,或者如果 readStatusCache 方法在 spring 托管对象中,只需向其添加 @Transactional 注释,或调用它的入口点)。
  2. 将应用程序集合更改为急切加载
  3. 让您的 dao 层在会话仍处于打开状态时完全初始化应用程序集合(请参阅 Hibernate.initialize 方法)。
于 2012-06-08T15:27:25.227 回答
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
    }

被两个单独的线程同时调用。readStatusCache()您可以通过同步方法来检查是否是这种情况。但这应该在 Spring 层中完成。您是否正确使用交易等?

请阅读此答案以获取有关 spring 和 hibernate 的线程安全的更多信息。在 webapp 中使用 Spring-Hibernate,线程安全会话管理的策略是什么

于 2012-06-08T11:15:52.467 回答
0

当我遇到同样的异常时,解决方案是将@Transactional注解添加到控制器中的方法中。

于 2014-06-30T11:46:28.327 回答