首页 \ 问答 \ 避免Hibernate LazyInitializationExceptions的体系结构(Architecture to avoid Hibernate LazyInitializationExceptions)

避免Hibernate LazyInitializationExceptions的体系结构(Architecture to avoid Hibernate LazyInitializationExceptions)

我正处于项目的开始阶段。 所以我试图设计一个避免Hibernate LazyInitializationExceptions的架构。 到目前为止,我的applicationContext.xml具有:

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="configLocation">
        <value>/WEB-INF/hibernate.cfg.xml</value>
    </property>
    <property name="configurationClass">
        <value>org.hibernate.cfg.AnnotationConfiguration</value>
    </property>        
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">${hibernate.dialect}</prop>        
            <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>     
        </props>
    </property>
    <property name="eventListeners">
        <map>
            <entry key="merge">
                <bean class="org.springframework.orm.hibernate3.support.IdTransferringMergeEventListener"/>
            </entry>
        </map>
    </property>
</bean>

<bean id="dao" class="info.ems.hibernate.HibernateEMSDao" init-method="createSchema">
    <property name="hibernateTemplate">
        <bean class="org.springframework.orm.hibernate3.HibernateTemplate">
            <property name="sessionFactory" ref="sessionFactory"/>
            <property name="flushMode">
                <bean id="org.springframework.orm.hibernate3.HibernateAccessor.FLUSH_COMMIT" class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean"/>                    
            </property>
        </bean>
    </property>        
    <property name="schemaHelper">
        <bean class="info.ems.hibernate.SchemaHelper">                                
            <property name="driverClassName" value="${database.driver}"/>
            <property name="url" value="${database.url}"/>
            <property name="username" value="${database.username}"/>
            <property name="password" value="${database.password}"/>
            <property name="hibernateDialect" value="${hibernate.dialect}"/>   
            <property name="dataSourceJndiName" value="${database.datasource.jndiname}"/>
        </bean>                
    </property>
</bean>       

hibernate.cfg.xml:

<hibernate-configuration>
    <session-factory>       
        <mapping class="info.ems.models.User" />
        <mapping class="info.ems.models.Role" />
    </session-factory>
</hibernate-configuration>

Role.java:

@Entity
@Table(name="ROLE")
@Access(AccessType.FIELD)
public class Role implements Serializable {

    private static final long serialVersionUID = 3L;

    @Id
    @Column(name="ROLE_ID", updatable=false, nullable=false)
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private long id;

    @Column(name="USERNAME")
    private String username;

    @Column(name="ROLE")
    private String role;

    public long getId() {
        return id;
    }

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

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getRole() {
        return role;
    }

    public void setRole(String role) {
        this.role = role;
    }
}

而User.java:

@Entity
@Table(name = "USER")
@Access(AccessType.FIELD)
public class User implements UserDetails, Serializable {

    private static final long serialVersionUID = 2L;

    @Id
    @Column(name = "USER_ID", updatable=false, nullable=false)
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    @Column(name = "USERNAME")
    private String username;

    @Column(name = "PASSWORD")
    private String password;

    @Column(name = "NAME")
    private String name;

    @Column(name = "EMAIL")
    private String email;

    @Column(name = "LOCKED")
    private boolean locked;

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, targetEntity = Role.class)
    @JoinTable(name = "USER_ROLE", joinColumns = { @JoinColumn(name = "USER_ID") }, inverseJoinColumns = { @JoinColumn(name = "ROLE_ID") })
    private Set<Role> roles;

    @Override
    public GrantedAuthority[] getAuthorities() {
        List<GrantedAuthorityImpl> list = new ArrayList<GrantedAuthorityImpl>(0);
        for (Role role : roles) {
            list.add(new GrantedAuthorityImpl(role.getRole()));
        }
        return (GrantedAuthority[]) list.toArray(new GrantedAuthority[list.size()]);
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return !isLocked();
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }

    public long getId() {
        return id;
    }

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

    @Override
    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    @Override
    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getName() {
        return name;
    }

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

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public boolean isLocked() {
        return locked;
    }

    public void setLocked(boolean locked) {
        this.locked = locked;
    }

    public Set<Role> getRoles() {
        return roles;
    }

    public void setRoles(Set<Role> roles) {
        this.roles = roles;
    }
}

HibernateEMSDao有两种方法可以从数据库中保存和加载User:

public void saveUser(final User user) {     
    getHibernateTemplate().execute(new HibernateCallback() {

        @Override
        public Object doInHibernate(Session session) throws HibernateException, SQLException {
            session.flush();
            session.setCacheMode(CacheMode.IGNORE);
            session.save(user);
            session.flush();
            return null;
        }
    });     
}

public User getUser(final Long id) {
    return (User) getHibernateTemplate().execute(new HibernateCallback() {

        @Override
        public Object doInHibernate(Session session) throws HibernateException, SQLException {
            return session.get(User.class, id);
        }
    });
}

现在我测试了如果我将HibernateEMSDao#getUser实现为:

public User getUser(final Long id) {
    getHibernateTemplate().load(User.class, id);        
}

我得到了LazyInitializationExcaption - 会话已关闭。 但第一种方法是工作正常。 所以我需要建议在不久的将来避免这种异常。 任何一小部分信息都是可观的。

感谢致敬。

注意:重新启动服务器后出现错误。

编辑:添加的代码:

public void saveUser(final User user) {     
    Session session = getSession();
    Transaction transaction = session.beginTransaction();
    session.save(user);
    transaction.commit();
    session.close();
}
public User getUser(final Long id) {
    Session session = getSession();
    session.enableFetchProfile("USER-ROLE-PROFILE");
    User user = (User) session.get(User.class, id);
    session.disableFetchProfile("USER-ROLE-PROFILE");
    session.close();
    return user;
}

I am in the beginning of my project. So I am trying to design an architecture which avoid Hibernate LazyInitializationExceptions. So far my applicationContext.xml has:

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="configLocation">
        <value>/WEB-INF/hibernate.cfg.xml</value>
    </property>
    <property name="configurationClass">
        <value>org.hibernate.cfg.AnnotationConfiguration</value>
    </property>        
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">${hibernate.dialect}</prop>        
            <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>     
        </props>
    </property>
    <property name="eventListeners">
        <map>
            <entry key="merge">
                <bean class="org.springframework.orm.hibernate3.support.IdTransferringMergeEventListener"/>
            </entry>
        </map>
    </property>
</bean>

<bean id="dao" class="info.ems.hibernate.HibernateEMSDao" init-method="createSchema">
    <property name="hibernateTemplate">
        <bean class="org.springframework.orm.hibernate3.HibernateTemplate">
            <property name="sessionFactory" ref="sessionFactory"/>
            <property name="flushMode">
                <bean id="org.springframework.orm.hibernate3.HibernateAccessor.FLUSH_COMMIT" class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean"/>                    
            </property>
        </bean>
    </property>        
    <property name="schemaHelper">
        <bean class="info.ems.hibernate.SchemaHelper">                                
            <property name="driverClassName" value="${database.driver}"/>
            <property name="url" value="${database.url}"/>
            <property name="username" value="${database.username}"/>
            <property name="password" value="${database.password}"/>
            <property name="hibernateDialect" value="${hibernate.dialect}"/>   
            <property name="dataSourceJndiName" value="${database.datasource.jndiname}"/>
        </bean>                
    </property>
</bean>       

The hibernate.cfg.xml:

<hibernate-configuration>
    <session-factory>       
        <mapping class="info.ems.models.User" />
        <mapping class="info.ems.models.Role" />
    </session-factory>
</hibernate-configuration>

The Role.java:

@Entity
@Table(name="ROLE")
@Access(AccessType.FIELD)
public class Role implements Serializable {

    private static final long serialVersionUID = 3L;

    @Id
    @Column(name="ROLE_ID", updatable=false, nullable=false)
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private long id;

    @Column(name="USERNAME")
    private String username;

    @Column(name="ROLE")
    private String role;

    public long getId() {
        return id;
    }

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

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getRole() {
        return role;
    }

    public void setRole(String role) {
        this.role = role;
    }
}

And the User.java:

@Entity
@Table(name = "USER")
@Access(AccessType.FIELD)
public class User implements UserDetails, Serializable {

    private static final long serialVersionUID = 2L;

    @Id
    @Column(name = "USER_ID", updatable=false, nullable=false)
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    @Column(name = "USERNAME")
    private String username;

    @Column(name = "PASSWORD")
    private String password;

    @Column(name = "NAME")
    private String name;

    @Column(name = "EMAIL")
    private String email;

    @Column(name = "LOCKED")
    private boolean locked;

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, targetEntity = Role.class)
    @JoinTable(name = "USER_ROLE", joinColumns = { @JoinColumn(name = "USER_ID") }, inverseJoinColumns = { @JoinColumn(name = "ROLE_ID") })
    private Set<Role> roles;

    @Override
    public GrantedAuthority[] getAuthorities() {
        List<GrantedAuthorityImpl> list = new ArrayList<GrantedAuthorityImpl>(0);
        for (Role role : roles) {
            list.add(new GrantedAuthorityImpl(role.getRole()));
        }
        return (GrantedAuthority[]) list.toArray(new GrantedAuthority[list.size()]);
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return !isLocked();
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }

    public long getId() {
        return id;
    }

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

    @Override
    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    @Override
    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getName() {
        return name;
    }

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

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public boolean isLocked() {
        return locked;
    }

    public void setLocked(boolean locked) {
        this.locked = locked;
    }

    public Set<Role> getRoles() {
        return roles;
    }

    public void setRoles(Set<Role> roles) {
        this.roles = roles;
    }
}

The HibernateEMSDao has two methods for saving and loading User from database:

public void saveUser(final User user) {     
    getHibernateTemplate().execute(new HibernateCallback() {

        @Override
        public Object doInHibernate(Session session) throws HibernateException, SQLException {
            session.flush();
            session.setCacheMode(CacheMode.IGNORE);
            session.save(user);
            session.flush();
            return null;
        }
    });     
}

public User getUser(final Long id) {
    return (User) getHibernateTemplate().execute(new HibernateCallback() {

        @Override
        public Object doInHibernate(Session session) throws HibernateException, SQLException {
            return session.get(User.class, id);
        }
    });
}

Now I tested that if I implement HibernateEMSDao#getUser as:

public User getUser(final Long id) {
    getHibernateTemplate().load(User.class, id);        
}

I am getting LazyInitializationExcaption - session is closed. But the first way is working fine. So I need suggestion to avoid this exception in near future. Any small piece of information is appreciable.

Thanks and regards.

Note: I got that error after restarting my server.

Edit: code added:

public void saveUser(final User user) {     
    Session session = getSession();
    Transaction transaction = session.beginTransaction();
    session.save(user);
    transaction.commit();
    session.close();
}
public User getUser(final Long id) {
    Session session = getSession();
    session.enableFetchProfile("USER-ROLE-PROFILE");
    User user = (User) session.get(User.class, id);
    session.disableFetchProfile("USER-ROLE-PROFILE");
    session.close();
    return user;
}

原文:https://stackoverflow.com/questions/6167889
更新时间:2023-04-06 14:04

最满意答案

如果len(activeGames)> = limit,则必须至少有一个活动游戏,因此getBestActiveGameStat()不能返回None。 那么,我应该检查一下吗?

有时我们会犯错误。 你现在可能有一个程序错误 - 或者有人可以稍后创建一个程序错误。

这些错误可能导致异常或单元测试失败。 但调试很昂贵; 有多种方法来检测错误很有用。

快速编写的断言语句可以表达对人类读者的预期不变量。 在调试时,失败的断言可以快速查明错误。

Sutter和Alexandrescu在“C ++编码标准”中解决了这个问题。 尽管有标题,但他们的论点和指导方针与语言无关。

自由断言以记录内部假设和不变量...使用断言或等效的自由来记录模块内部的假设......必须始终为真,否则表示编程错误。

例如,如果switch语句中的default大小写不能发生,请使用assert(false)添加大小写。


If len(activeGames) >= limit, then there must be at least one active game, so getBestActiveGameStat() can't return None. So, should I even check for it?

Sometimes we make mistakes. You could have a program error now -- or someone could create one later.

Those errors might result in exceptions or failed unit tests. But debugging is expensive; it's useful to have multiple ways to detect errors.

A quickly written assert statement can express an expected invariant to human readers. And when debugging, a failed assertion can pinpoint an error quickly.

Sutter and Alexandrescu address this issue in "C++ Coding Standards." Despite the title, their arguments and guidelines are are language agnostic.

Assert liberally to document internal assumptions and invariants ... Use assert or an equivalent liberally to document assumptions internal to a module ... that must always be true and otherwise represent programming errors.

For example, if the default case in a switch statement cannot occur, add the case with assert(false).

相关问答

更多
  • 当然,这种情况经常发生。 代码通常也包含数据。 像内联字符串或表一样,就像为switch语句生成的那种。 一个跳转表,包含地址而不是代码。 反汇编程序往往会严重违反这些代码。 他们通常可以发现第一个表项是一个地址,但不知道该表有多长。 但这通常只会产生损坏的汇编代码,典型的处理器没有那么多不可能的指令。 它们倾向于将任何字节值映射到指令。 因人而异。 Sure, this happens quite often. Code often contains data as well. Like inline s ...
  • 如果len(activeGames)> = limit,则必须至少有一个活动游戏,因此getBestActiveGameStat()不能返回None。 那么,我应该检查一下吗? 有时我们会犯错误。 你现在可能有一个程序错误 - 或者有人可以稍后创建一个程序错误。 这些错误可能导致异常或单元测试失败。 但调试很昂贵; 有多种方法来检测错误很有用。 快速编写的断言语句可以表达对人类读者的预期不变量。 在调试时,失败的断言可以快速查明错误。 Sutter和Alexandrescu在“C ++编码标准”中解决了这个 ...
  • 由于Enumerable.ToList永远不会返回null (请参阅文档的返回值部分),因此您可以安全地删除if 。 编辑:请注意,无论您的数据库包含什么, acctype 永远不会为null: 如果数据库中未找到任何值,则返回值将为空列表 (不同于null )。 如果找到一条记录且其值为null,则返回值将是包含一个条目的有效列表 ,其值为null。 但是,列表本身并不为 null 。 Since Enumerable.ToList never returns null (see the Return V ...
  • 请参阅以下内容了解更多详情 http://msdn.microsoft.com/en-us/library/ms178116.aspx See following for more details: http://msdn.microsoft.com/en-us/library/ms178116.aspx
  • 您可以在此处使用适配器模式。 创建一个名为IHWSysManager的接口 public interface IHWSysManager { int OpenConfiguration(string hwPath); } 真正的实现类只是将工作委托给库: public class HWSysManagerImpl : IHWSysManager { private HWSysManager _hwSysManager; //Initialize from constructor ...
  • 取决于你在做什么。 我会选择PowerShells模块化的相对路径。 移动或更新模块时,可以使用它提供所有相关资源。 我不太喜欢外部依赖,所以我坚持使用这种方法。 Env可能不存在或在系统上有所不同 - 模块或脚本的路径始终是清晰的。 Depends on what you are doing. I would go for relative paths as of powershells modularity. When you move or update a module, you give all ...
  • powershell命令适用于UNC路径,一直在UNC路径上使用Test-Path命令而没有任何问题,使用UNC路径将文件从本地复制到远程。 检查以下条件: 你需要使用有效的UNC路径[\ tfsbuildServer02 \ drop可以是\ tfsbuildServer02 \ e $ \ drop] 您需要对该文件夹具有写访问权限,使用powershell命令Icacls检查您对文件夹的权限 powershell command works fine with UNC paths , have bee ...
  • 是我试图实现的语法是不可能的? 这绝对是可能的,而且我肯定会有一些错误修正它可以正常工作。 您所描述的内容与异步模块定义(AMD)基本相同,后者广泛用于处理代码依赖性。 我建议您尝试使用requirejs并按照现有标准执行项目,而不是继续追求自己版本的相同概念。 is the syntax I'm trying to implement impossible or not? It's absolutely possible, and I'm sure with a bit of bugfixing it'd ...
  • 您不需要HAVING因为标准INNER连接不会返回b行而无需匹配行。 您也不需要GROUP BY - 使用COUNT(DISTINCT )代替: SELECT COUNT(DISTINCT b.id) AS cnt FROM b JOIN a ON a.b_id = b.id WHERE a.value = 1 You don't need HAVING because standard INNER join won't return b rows without matching a rows anyw ...
  • 解决方案是不使用jQuery来解析文档。 如果需要,可以使用jQuery.ajax ,但不要使用$来解析结果。 阅读控制台的答案, 显示有关内容安全策略的错误以及许多失败的GET请求,以了解和解决您的问题。 答案强烈建议使用vanilla JavaScript。 如果您仍想使用jQuery,请使用以下DOM解析方法: // responseText is a string, for example from calling jQuery.ajax var doc = document.implementat ...

相关文章

更多

最新问答

更多
  • 获取MVC 4使用的DisplayMode后缀(Get the DisplayMode Suffix being used by MVC 4)
  • 如何通过引用返回对象?(How is returning an object by reference possible?)
  • 矩阵如何存储在内存中?(How are matrices stored in memory?)
  • 每个请求的Java新会话?(Java New Session For Each Request?)
  • css:浮动div中重叠的标题h1(css: overlapping headlines h1 in floated divs)
  • 无论图像如何,Caffe预测同一类(Caffe predicts same class regardless of image)
  • xcode语法颜色编码解释?(xcode syntax color coding explained?)
  • 在Access 2010 Runtime中使用Office 2000校对工具(Use Office 2000 proofing tools in Access 2010 Runtime)
  • 从单独的Web主机将图像传输到服务器上(Getting images onto server from separate web host)
  • 从旧版本复制文件并保留它们(旧/新版本)(Copy a file from old revision and keep both of them (old / new revision))
  • 西安哪有PLC可控制编程的培训
  • 在Entity Framework中选择基类(Select base class in Entity Framework)
  • 在Android中出现错误“数据集和渲染器应该不为null,并且应该具有相同数量的系列”(Error “Dataset and renderer should be not null and should have the same number of series” in Android)
  • 电脑二级VF有什么用
  • Datamapper Ruby如何添加Hook方法(Datamapper Ruby How to add Hook Method)
  • 金华英语角.
  • 手机软件如何制作
  • 用于Android webview中图像保存的上下文菜单(Context Menu for Image Saving in an Android webview)
  • 注意:未定义的偏移量:PHP(Notice: Undefined offset: PHP)
  • 如何读R中的大数据集[复制](How to read large dataset in R [duplicate])
  • Unity 5 Heighmap与地形宽度/地形长度的分辨率关系?(Unity 5 Heighmap Resolution relationship to terrain width / terrain length?)
  • 如何通知PipedOutputStream线程写入最后一个字节的PipedInputStream线程?(How to notify PipedInputStream thread that PipedOutputStream thread has written last byte?)
  • python的访问器方法有哪些
  • DeviceNetworkInformation:哪个是哪个?(DeviceNetworkInformation: Which is which?)
  • 在Ruby中对组合进行排序(Sorting a combination in Ruby)
  • 网站开发的流程?
  • 使用Zend Framework 2中的JOIN sql检索数据(Retrieve data using JOIN sql in Zend Framework 2)
  • 条带格式类型格式模式编号无法正常工作(Stripes format type format pattern number not working properly)
  • 透明度错误IE11(Transparency bug IE11)
  • linux的基本操作命令。。。