我正在使用OpenSessionInViewFilter,Spring和Hibernate进行数据访问。 OpenSessionInViewFilter配置如下
<filter>
<filter-name>openSessionInViewFilter</filter-name>
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
<init-param>
<param-name>sessionFactoryBeanName</param-name>
<param-value>sessionFactory</param-value>
</init-param>
<init-param>
<param-name>singleSession</param-name>
<param-value>false</param-value>
</init-param>
</filter>
现在我已经用注释映射了实体,就像那样
@Entity
@Table(name = "SERVICE_USER")
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class ServiceUser implements Serializable {
@Id
@GeneratedValue(generator = "service_user_id_generator", strategy = GenerationType.SEQUENCE)
@SequenceGenerator(name = "service_user_id_generator", sequenceName = "service_user_id_gen", allocationSize = 1)
private Long id;
@ManyToOne
@JoinColumn(name = "contract_type_id")
@ForeignKey(name = "service_user_ct_fk")
private ServiceUserContractType contractType;
}
现在我正在尝试构建并保存新的ServiceUser实体。为此,我有从数据库中检索ServiceUserContractType的服务,并在新创建的服务用户中设置相应的字段。从标记为事务的数据库获取contarct类型的方法。
要保存服务用户,请使用
sessionFactory.getCurrentSession().merge(serviceUser)
如果我尝试使用此方法来审核合同类型
public ServiceUserContractType getContractType(Long id){
Criteria criteria = sessionFactory.getCurrentSession().createCriteria(ServiceUserContractType.class);
criteria.add(Restrictions.eq("id", id));
return (ServiceUserContractType) criteria.uniqueResult();
}
然后,合并的那一刻叫我收到
object references an unsaved transient instance - save the transient instance before flushing
异常。我明白了,我在服务用户映射中将cascade = CascadeType.MERGE
添加到@ManyToOne
注释,它可以正常工作。但...
如果我使用
public ServiceUserContractType getContractType(Long id){
return (ServiceUserContractType) sessionFactory.getCurrentSession().load(ServiceUserContractType.class, id);
}
没有级联合并选项,它可以正常工作。
我在调试时看到的唯一区别是第一个方法(带条件)返回完全加载的合同类型实体,load
变量返回未初始化的代理。
有人可以解释这种情况下的工作原理吗?为什么代理可以在没有级联的情况下合并?为什么标准不是代理而是完全初始化的实体?