Java >(我已经清理了代码,只保留了重要的东西)
而且,如果我使用单线程版本(lRunnable.run()),我就有zip文件,但如果我运行多线程版本(thread.start())(我在这里阻止了该版本,以确保在测试中连接不会被父线程关闭,但在我删除thread.join()之后),我会出现以下异常: 错误[…ExportThreadHelper](线程-115)延迟初始化失败 角色的集合:。步骤,无法初始化代理-无会话: org.hibernate.LazyInitializationException:延迟初始化失败 角色的集合:。步骤,无法初始化代理-无会话 在 org.hibernate.collection.internal.AbstractPersistentCollection.ThrowlazyiInitializationException(AbstractPersistentCollection.java:569) [hibernate-core-4.2.14.SP1-redhat-1.jar:4.2.14.SP1-redhat-1]位于 org.hibernate.collection.internal.AbstractPersistentCollection.WithTemporarySessionIneed(AbstractPersistentCollection.java:188) [hibernate-core-4.2.14.SP1-redhat-1.jar:4.2.14.SP1-redhat-1]位于 org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:548) [hibernate-core-4.2.14.SP1-redhat-1.jar:4.2.14.SP1-redhat-1]位于 org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:126) [hibernate-core-4.2.14.SP1-redhat-1.jar:4.2.14.SP1-redhat-1]位于 org.hibernate.collection.internal.PersistentBag.iterator(PersistentBag.java:266) [hibernate-core-4.2.14.SP1-redhat-1.jar:4.2.14.SP1-redhat-1]位于 ExportThreadHelper$1.execute(ExportThreadHelper.java:101) [metier-2.3.0-SNAPSHOT.jar:] ExportThreadHelper$1.execute(ExportThreadHelper.java:1) [metier-2.3.0-SNAPSHOT.jar:] ExportThreadHelper.transaction(ExportThreadHelper.java:148) [metier-2.3.0-SNAPSHOT.jar:] ExportThreadHelper.export(ExportThreadHelper.java:97) [metier-2.3.0-SNAPSHOT.jar:] ExportMetier$1.run(ExportMetier.java:62)[metier-2.3.0-SNAPSHOT.jar:] 在java.lang.Thread.run(Thread.java:722)[rt.jar:1.7.0_04]Java >(我已经清理了代码,只保留了重要的东西),java,multithreading,hibernate,transactions,jta,Java,Multithreading,Hibernate,Transactions,Jta,而且,如果我使用单线程版本(lRunnable.run()),我就有zip文件,但如果我运行多线程版本(thread.start())(我在这里阻止了该版本,以确保在测试中连接不会被父线程关闭,但在我删除thread.join()之后),我会出现以下异常: 错误[…ExportThreadHelper](线程-115)延迟初始化失败 角色的集合:。步骤,无法初始化代理-无会话: org.hibernate.LazyInitializationException:延迟初始化失败 角色的集合:。步骤
您看到我的代码中有问题吗?您需要像这样更改查询:
@NamedQueries({
@NamedQuery(name = "Process.GetByCode", query = "SELECT p FROM Process p LEFT JOIN FETCH p.steps WHERE p.code=:code")
})
您需要如下更改查询:
@NamedQueries({
@NamedQuery(name = "Process.GetByCode", query = "SELECT p FROM Process p LEFT JOIN FETCH p.steps WHERE p.code=:code")
})
在project中是否有名为
ExportThreadHelper.java
的文件,是否可以发布该文件。特别是靠近90-150的行?通过第一次查看异常,似乎您正试图从进程中访问集合
,对象退出hibernate会话。要么不关闭hibernate会话,要么将fetch=FetchType.EAGER
设置为私有收集步骤代码>感谢您的关注-ExportThreadHelper进入“控制器”部分-我想保持延迟加载,因为数据太多,我不会在所有情况下都使用它。您是否在project中有名为ExportThreadHelper.java
的文件,您可以发布该文件吗。特别是靠近90-150的行?通过第一次查看异常,似乎您正试图从进程中访问集合
,对象退出hibernate会话。要么不关闭hibernate会话,要么将fetch=FetchType.EAGER
设置为私有收集步骤代码>感谢您的关注-ExportThreadHelper进入了“控制器”部分-我想保持延迟加载,因为数据太多,我不会在所有情况下都使用它。我也可以在字段中添加“fetch=EAGER”,但我不想要它,因为否则我们会一直获得每个情况下的所有数据。我想保持延迟加载并正确使用事务。为什么不使用两个查询呢?我不想依赖于上下文。这是一个在REST上工作的大型应用程序。这个新的REST资源必须在响应的zip文件中创建一个“导出”。因此,如果您调用“/rest/myResource”,您将得到一个JSON,如果您调用“/rest/export”,您将得到一个带有“/rest/myResource.JSON”的“zip文件”,其中包含第一个请求的响应。这是一个简单的例子,但问题在于:我想调用线程中的所有其他业务方法来生成zip文件。我也可以在字段中添加“fetch=EAGER”,但我不想要它,因为否则我们会一直获取每个案例的所有数据。我想保持延迟加载并正确使用事务。为什么不使用两个查询呢?我不想依赖于上下文。这是一个在REST上工作的大型应用程序。这个新的REST资源必须在响应的zip文件中创建一个“导出”。因此,如果您调用“/rest/myResource”,您将得到一个JSON,如果您调用“/rest/export”,您将得到一个带有“/rest/myResource.JSON”的“zip文件”,其中包含第一个请求的响应。这是一个简单的示例,但问题在于:我想调用线程中的所有其他业务方法来生成zip文件。
public interface IProcessDao {
Processus getByCode(final String pCode);
}
public class ProcessDao implements IProcessDao {
@Override
public Processus getByCode(final String pCode) {
Processus lResult = null;
try {
final TypedQuery<Processus> lRequest = pEm.createNamedQuery("Process.GetByCode", Process.class);
lRequest.setParameter("code", pCode);
lResult = lRequest.getSingleResult();
} catch (final NoResultException e) {
// Return null
lResult = null;
}
return lResult;
}
}
public interface IExport {
/**
* Generate export
*
* @param pProcessCode Process code
* @return Datas
*/
InputStream export(final String pProcessCode);
}
public class Export implements IExport {
@PersistenceContext(unitName="authorizations")
private EntityManager entityManagerAuthorizations;
@Inject
private ExportThreadHelper exportThreadHelper;
@Override
public InputStream export(final String pProcessCode) {
//Check if user has the profile. Use database "AUTHORIZATIONS"
checkProfil(entityManagerAuthorizations, Profiles.ADMIN);
final PipedInputStream lInputStream = new PipedInputStream();
OutputStream lOutputStream = null;
try {
lOutputStream = new FileOutputStream("d:/test.zip");// new
// PipedOutputStream(lInputStream);
} catch (final IOException e) {
throw new RuntimeException("Cannot start zip generation", e);
}
final ZipOutputStream lZipOutputStream = new ZipOutputStream(lOutputStream);
final Runnable lRunnable = new Runnable() {
@Override
public void run() {
try {
exportThreadHelper.export(pProcessCode, lZipOutputStream);
} catch (final Exception e) {
logger.error(e);
} finally {
IOUtils.closeQuietly(lZipOutputStream);
}
}
};
//To execute in same thread :
//lRunnable.run();
//To execute in another thread
final Thread lThread = new Thread(lRunnable);
lThread.start();
try {
lThread.join();
} catch (final InterruptedException e1) {
throw new RuntimeException(e1);
}
try {
return new FileInputStream("d:/test.zip");
} catch (final FileNotFoundException e) {
logger.error(e);
}
return lInputStream;
}
}
public class ExportThreadHelper {
private class ProcessToExport {
//...
}
@PersistenceContext
@Named("Application")
private EntityManager entityManagerThreadable;
@Inject
private IProcessDao processDao;
public void export(final String pProcesssCode, final ZipOutputStream pZipOutputStream)
throws MyWayBusinessException {
try {
final ProcessToExport lProcessToExport = new ProcessToExport();
transaction(entityManagerThreadable, new Callable<Void>() {
@Override
public Void execute() {
final Process lProcess = processDao.getByCode(pProcesssCode);
for (final Step lStep : lProcess.getSteps()) {
//Many things
}
return null;
}
});
//MANY OTHER TREATMENTS
} catch (final Exception e) {
logger.error(e);
throw new RuntimeException("Cannot generate export", e);
}
}
@Override
@TransactionAttribute(TransactionAttributeType.REQUIRED)
protected <T> T transaction(final EntityManager pEntityManager, final Callable<T> pCallable) {
//I've tried with and without the annotation and with and without the "UserTransaction"
try {
final UserTransaction tx = com.arjuna.ats.jta.UserTransaction.userTransaction();
try {
tx.begin();
final T lResultat = pCallable.execute();
tx.commit();
return lResultat;
} catch (final Throwable e) {
tx.rollback();
throw e;
}
} catch (final Throwable e) {
throw new RuntimeException(e);
}
}
}
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd ">
<persistence-unit name="APPLICATION" transaction-type="JTA">
<jta-data-source>java:/jdbc/app</jta-data-source>
<class>Processus</class>
<class>Step</class>
<properties>
<!-- Scan for annotated classes and Hibernate mapping XML files -->
<property name="hibernate.archive.autodetection" value="class, hbm" />
</properties>
</persistence-unit>
<persistence-unit name="AUTHORIZATION" transaction-type="JTA">
<jta-data-source>java:/jdbc/AUTHORIZATION</jta-data-source>
<!-- many things... -->
</persistence-unit>
</persistence>
@NamedQueries({
@NamedQuery(name = "Process.GetByCode", query = "SELECT p FROM Process p LEFT JOIN FETCH p.steps WHERE p.code=:code")
})