1

我正在使用 Spring 3.1.1.RELEASE、Hibernate 4.1.0.Final、JPA 2.0 构建 WAR,并回复 JBoss 7.1.1.Final。我有这个实体有几个懒惰的关联......</p>

@GenericGenerator(name = "uuid-strategy", strategy = "uuid.hex")
@Entity
@Table(name = "cb_contract",
    uniqueConstraints = {@UniqueConstraint(columnNames={"OPPORTUNITY_ID","PRODUCT_ID"})}
)
public class Contract implements Serializable {

    …
    @Id
    @Column(name = "ID")
    @GeneratedValue(generator = "uuid-strategy")
    private String id;

    @OneToOne(fetch = FetchType.LAZY, targetEntity = Product.class)
    @JoinColumn(name = "PRODUCT_ID")
    @NotNull
    private Product product;

    @OneToOne(fetch = FetchType.LAZY, targetEntity = Organization.class)
    @JoinColumn(name = "ORGANIZATION_ID")
    @NotNull
    private Organization org;

我从一种事务方法加载这些实体……</p>

@Transactional
@Service
public class ContractServiceImpl implements ContractService
...

public List<Contract> findContractByOppId(final String oppId)
{
    final Contract contract = new Contract();
    contract.setOpportunityId(oppId);
    return m_contractDao.find(contract);
}   // findContractByOppId

然后尝试将它们保存在另一个@Transactional方法中(这个私有方法是从@Transactional公共方法中调用的):

@Service
@Transactional
public class UserServiceImpl implements UserService
{
...
private void saveUserContracts(final User user, final Set<Contract> contracts)
{
    if (contracts != null)
    {
        for (final Contract contract : contracts)
        {
            contract.getOrg();
            contract.getProduct();

            final UserContract userContract = new UserContract();
            userContract.setContract(contract);
            userContract.setUser(user);
            userContractDao.save(userContract);
        }   // for
    }   // if
}   // saveUserContracts

但是,在尝试保存它们时,我得到了以下异常。如何让惰性实体加载(最好使用 JPA,而不是特定于 Hibernate 的方法)?

org.hibernate.LazyInitializationException: could not initialize proxy - no Session
    at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:149)
    at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:195)
    at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:185)
    at org.mainco.subco.organization.domain.Organization_$$_javassist_10.hashCode(Organization_$$_javassist_10.java)
    at org.mainco.subco.ecom.domain.Contract.hashCode(Contract.java:134)
    at java.util.HashMap.put(HashMap.java:372)
    at java.util.HashSet.add(HashSet.java:200)
    at java.util.AbstractCollection.addAll(AbstractCollection.java:305)
    at java.util.HashSet.<init>(HashSet.java:100)
    at org.mainco.subco.user.test.service.UserServiceTest.testAddUser(UserServiceTest.java:116)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

谢谢, - 戴夫

4

1 回答 1

0

根据提供的信息,我认为至少有三件事是错误的(如果我的解释与现实不符,请纠正我):

  • Contract#hashCode()似乎依赖于延迟加载的属性。不要那样做,这hashCode是一种基本的方法,它需要在每个上下文中工作,即即使实体没有附加到会话。
  • 您似乎正在做这样的事情:X 类调用事务服务 A,获取结果并将它们传递给另一个事务服务 B。发生的情况是,一旦 A 完成,所有实体都将被分离,即它们不再附加到持久性会话,这意味着您不能延迟加载成员。即使在您有会话的 B 内部,这些实体也不会自动重新连接。本质上这就是异常的原因。
  • UserServiceTest可能或可能没有正确设置事务支持,真的不能说。

您可以做的是确保 X 本身是事务性的,在这种情况下,A 和 B 中的方法默认参与同一个事务。在 X 完成之前,实体不会分离。

于 2013-02-11T18:26:14.540 回答