0

我必须在负载平衡架构中放置两个 tomcat 服务器(tcat01 和 tcat02)。

我正在使用 tomcat 6.x 并在 tomcat tcat01 上编辑了 conf/server.xml :

<Engine name="Catalina" defaultHost="localhost" jvmRoute="tcat01">
     <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" channelSendOptions="6"/>
      ....

在 tcat02 conf/server.xml 上是这样的:

 <Engine name="Catalina" defaultHost="localhost" jvmRoute="tcat02">
     <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" channelSendOptions="6"/>
      ....

我启动了 tcat01,然后是 tcat02,il catalina.out 似乎 tcat01 与 tcat02 通信良好。

然后我用互联网导航器连接到 webapp,然后每次我在 webapp 中做某事(我的意思是当我导航时)都会出现这个异常:

  Nov 24, 2011 12:00:13 AM org.apache.catalina.core.ContainerBase backgroundProcess
WARNING: Exception processing manager org.apache.catalina.ha.session.DeltaManager@278c4835 background process
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.mycompany.myproject.model.authentification.Authority.groups, no session or session was closed
    at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:383)
    at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:375)
    at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:368)
    at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:111)
    at org.hibernate.collection.PersistentSet.toString(PersistentSet.java:332)
    at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
    at java.io.ObjectOutputStream.writeObject0(Unknown Source)
    at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
    at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
    at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)

这里是不能sezialized类的代码(即堆栈跟踪中提到的java bean):

import static javax.persistence.GenerationType.IDENTITY;

import java.util.HashSet;
import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.PrePersist;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;

@Entity
@Table(name = "authority", uniqueConstraints = @UniqueConstraint(columnNames = "name"))
public class Authority implements java.io.Serializable {

/**
 * 
 */
private static final long serialVersionUID = -7436593455923433675L;

//SYSTEM ROLE CONSTANT
public static final String MANAGER_SYSTEM_ROLE = "ROLE_MANAGER";
public static final String CLIENT_SYSTEM_ROLE = "ROLE_CLIENT";
public static final String PEDAGO_ADMIN_SYSTEM_ROLE = "ROLE_PEDAGO_ADMIN";

private Integer id;
@Size(min=1)
@Pattern(regexp="^ROLE[_a-zA-Z]+$", message="{authority.name.pattern.error}")
private String name;
@Size(max=65535)
private String description;


private Boolean isSystem;

private Set<Group> groups = new HashSet<Group>(0);

public Authority() {
    this.isSystem = false;
}

public Authority(String name) {
    this.name = name;
    this.isSystem = false;
}

public Authority(String name, String description, Set<Group> groups) {
    this.name = name;
    this.description = description;
    this.groups = groups;
    this.isSystem = false;
}

@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "id", unique = true, nullable = false)
public Integer getId() {
    return this.id;
}

public void setId(Integer id) {
    this.id = id;
}

@Column(name = "name", unique = true, nullable = false, length = 45)
public String getName() {
    return this.name;
}

public void setName(String name) {
    this.name = name;
}

@Column(name = "description")
public String getDescription() {
    return this.description;
}

public void setDescription(String description) {
    this.description = description;
}

public void setIsSystem(Boolean isSystem) {
    this.isSystem = isSystem;
}

@Column(name = "system")
public Boolean getIsSystem() {
    return isSystem;
}

@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "group_authorities", joinColumns = { @JoinColumn(name = "authority_id", nullable = false, updatable = true) }, inverseJoinColumns = { @JoinColumn(name = "group_id", nullable = false, updatable = true) })
public Set<Group> getGroups() {
    return this.groups;
}

public void setGroups(Set<Group> groups) {
    this.groups = groups;
}

@PrePersist
protected void updateSystemField() {
    if(isSystem == null)
        isSystem = false;
}
}

这里是 java bean Group 的代码(因为我们在 Groups 集合上有一个延迟初始化异常):

import static javax.persistence.GenerationType.IDENTITY;

import java.util.HashSet;
import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.PrePersist;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;


@Entity
@Table(name = "groups", uniqueConstraints = @UniqueConstraint(columnNames = "name"))
public class Group implements java.io.Serializable {

/**
 * 
 */
private static final long serialVersionUID = 7380068327050752558L;

private Integer id;
@NotNull
@Size(min=1)
private String name;
private String description;

private Boolean isSystem;

private Set<Authority> authorities = new HashSet<Authority>(0);
private Set<User> users = new HashSet<User>(0);

public Group() {
    this.isSystem = false;
}

public Group(String name) {
    this.name = name;
    this.isSystem = false;
}

public Group(String name, String description, Set<Authority> authorities, Set<User> users) {
    this.name = name;
    this.description = description;
    this.isSystem = false;
    this.authorities = authorities;
    this.users = users;
}

@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "id", unique = true, nullable = false)
public Integer getId() {
    return this.id;
}

public void setId(Integer id) {
    this.id = id;
}

@Column(name = "name", unique = true, nullable = false, length = 45)
public String getName() {
    return this.name;
}

public void setName(String name) {
    this.name = name;
}

@Column(name = "description")
public String getDescription() {
    return this.description;
}

public void setDescription(String description) {
    this.description = description;
}

public void setIsSystem(Boolean isSystem) {
    this.isSystem = isSystem;
}

@Column(name = "system")
public Boolean getIsSystem() {
    return isSystem;
}

@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "group_authorities", joinColumns = { @JoinColumn(name = "group_id", nullable = false, updatable = true) }, inverseJoinColumns = { @JoinColumn(name = "authority_id", nullable = false, updatable = true) })
public Set<Authority> getAuthorities() {
    return this.authorities;
}

public void setAuthorities(Set<Authority> authorities) {
    this.authorities = authorities;
}

@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "group_users", joinColumns = { @JoinColumn(name = "group_id", nullable = false, updatable = true) }, inverseJoinColumns = { @JoinColumn(name = "user_id", nullable = false, updatable = true) })
public Set<User> getUsers() {
    return this.users;
}

public void setUsers(Set<User> users) {
    this.users = users;
}

public void addAuthority(Authority authority) {
    if(authorities == null)
        authorities = new HashSet<Authority>(0);
    authorities.add(authority);
}

public boolean removeAuthority(Authority authority) {
    return authorities == null || authorities.remove(authority);
}

public void addUser(User user) {
    if(users == null)
        users = new HashSet<User>(0);
    users.add(user);
}

public boolean removeUser(User user) {
    return users == null || users.remove(user);
}

@PrePersist
protected void updateSystemField() {
    if(isSystem == null)
        isSystem = false;
}
}

谢谢你的帮助

4

1 回答 1

0

You're getting the lazy instantiation exception since you have authority groups mapped as lazy. By the time the session is replicated, you're outside of an active session so it can't be hydrated. To remedy this, you have a few options:

  1. Change your mapping so the association is fetched eagerly
  2. Change your DAO to step into that collection (or use hibernate.initialize) to force the lazy load to occur before the session is closed
  3. Detach the object from the session and then explicitly set the groups to null on the object before it is put into session to replace the hibernate proxy that is there.

For this particuar case, options 1 or 2 are probably the cleanest.

于 2011-11-30T17:31:23.767 回答