避免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
最满意答案
如果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 aswitch
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 ++编码标准”中解决了这个 ...
-
并非所有代码路径都返回值(Not all code paths return a value)[2023-09-19]
由于Enumerable.ToList永远不会返回null (请参阅文档的返回值部分),因此您可以安全地删除if 。 编辑:请注意,无论您的数据库包含什么, acctype 永远不会为null: 如果数据库中未找到任何值,则返回值将为空列表 (不同于null )。 如果找到一条记录且其值为null,则返回值将是包含一个条目的有效列表 ,其值为null。 但是,列表本身并不为 null 。 Since Enumerable.ToList never returns null (see the Return V ... -
在移动到服务器主机之前,如何处理代码中的文件路径?(How do I handle file paths in my code before moving to server host?)[2022-02-20]
请参阅以下内容了解更多详情 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 ...
-
这个“DI”结构是不可能的,还是我应该找一个bug?(Is this “DI” structure impossible, or should I look for a bug?)[2023-06-20]
是我试图实现的语法是不可能的? 这绝对是可能的,而且我肯定会有一些错误修正它可以正常工作。 您所描述的内容与异步模块定义(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 ... -
查询对我来说不可能?(query impossible for me?)[2021-05-14]
您不需要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 ... -
处理相对图像路径ajax(Handle Relative Image Paths ajax)[2021-12-08]
解决方案是不使用jQuery来解析文档。 如果需要,可以使用jQuery.ajax ,但不要使用$来解析结果。 阅读控制台的答案, 显示有关内容安全策略的错误以及许多失败的GET请求,以了解和解决您的问题。 答案强烈建议使用vanilla JavaScript。 如果您仍想使用jQuery,请使用以下DOM解析方法: // responseText is a string, for example from calling jQuery.ajax var doc = document.implementat ...