Ble*_*tri 159 java orm session hibernate lazy-loading
我得到以下异常:
Exception in thread "main" org.hibernate.LazyInitializationException: could not initialize proxy - no Session
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:167)
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:215)
at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:190)
at sei.persistence.wf.entities.Element_$$_jvstc68_47.getNote(Element_$$_jvstc68_47.java)
at JSON_to_XML.createBpmnRepresantation(JSON_to_XML.java:139)
at JSON_to_XML.main(JSON_to_XML.java:84)
Run Code Online (Sandbox Code Playgroud)
当我尝试从main调用以下行时:
Model subProcessModel = getModelByModelGroup(1112);
System.out.println(subProcessModel.getElement().getNote());
Run Code Online (Sandbox Code Playgroud)
我getModelByModelGroup(int modelgroupid)首先实现了这个方法,如下所示:
public static Model getModelByModelGroup(int modelGroupId, boolean openTransaction) {
Session session = SessionFactoryHelper.getSessionFactory().getCurrentSession();
Transaction tx = null;
if (openTransaction) {
tx = session.getTransaction();
}
String responseMessage = "";
try {
if (openTransaction) {
tx.begin();
}
Query query = session.createQuery("from Model where modelGroup.id = :modelGroupId");
query.setParameter("modelGroupId", modelGroupId);
List<Model> modelList = (List<Model>)query.list();
Model model = null;
for (Model m : modelList) {
if (m.getModelType().getId() == 3) {
model = m;
break;
}
}
if (model == null) {
Object[] arrModels = modelList.toArray();
if (arrModels.length == 0) {
throw new Exception("Non esiste ");
}
model = (Model)arrModels[0];
}
if (openTransaction) {
tx.commit();
}
return model;
} catch(Exception ex) {
if (openTransaction) {
tx.rollback();
}
ex.printStackTrace();
if (responseMessage.compareTo("") == 0) {
responseMessage = "Error" + ex.getMessage();
}
return null;
}
}
Run Code Online (Sandbox Code Playgroud)
得到了例外.然后一位朋友建议我总是测试会话并获取当前会话以避免此错误.所以我这样做了:
public static Model getModelByModelGroup(int modelGroupId) {
Session session = null;
boolean openSession = session == null;
Transaction tx = null;
if (openSession) {
session = SessionFactoryHelper.getSessionFactory().getCurrentSession();
tx = session.getTransaction();
}
String responseMessage = "";
try {
if (openSession) {
tx.begin();
}
Query query = session.createQuery("from Model where modelGroup.id = :modelGroupId");
query.setParameter("modelGroupId", modelGroupId);
List<Model> modelList = (List<Model>)query.list();
Model model = null;
for (Model m : modelList) {
if (m.getModelType().getId() == 3) {
model = m;
break;
}
}
if (model == null) {
Object[] arrModels = modelList.toArray();
if (arrModels.length == 0) {
throw new RuntimeException("Non esiste");
}
model = (Model)arrModels[0];
if (openSession) {
tx.commit();
}
return model;
} catch(RuntimeException ex) {
if (openSession) {
tx.rollback();
}
ex.printStackTrace();
if (responseMessage.compareTo("") == 0) {
responseMessage = "Error" + ex.getMessage();
}
return null;
}
}
}
Run Code Online (Sandbox Code Playgroud)
但仍然得到相同的错误.我一直在阅读这个错误,并找到了一些可能的解决方案.其中一个是将lazyLoad设置为false但我不允许这样做,这就是为什么我被建议控制会话
use*_*995 134
如果你使用Spring将类标记为@Transactional,那么Spring将处理会话管理.
@Transactional
public class MyClass {
...
}
Run Code Online (Sandbox Code Playgroud)
通过使用@Transactional,可以自动处理许多重要方面,例如事务传播.在这种情况下,如果调用另一个事务方法,则该方法可以选择加入正在进行的事务,避免"无会话"异常.
Wil*_*wan 105
你可以尝试设置
<property name="hibernate.enable_lazy_load_no_trans">true</property>
Run Code Online (Sandbox Code Playgroud)
在hibernate.cfg.xml或persistence.xml中
这个属性要记住的问题在这里得到了很好的解释
gor*_*ncy 80
这里的错误是您的会话管理配置设置为在提交事务时关闭会话.检查您是否有类似的东西:
<property name="current_session_context_class">thread</property>
Run Code Online (Sandbox Code Playgroud)
在您的配置中.
为了克服这个问题,您可以更改会话工厂的配置或打开另一个会话,而不仅仅是要求那些延迟加载的对象.但我在这里建议的是在getModelByModelGroup本身初始化这个惰性集合并调用:
Hibernate.initialize(subProcessModel.getElement());
Run Code Online (Sandbox Code Playgroud)
当你还在活跃的会话中.
最后一件事.友好的建议.你的方法中有这样的东西:
for (Model m : modelList) {
if (m.getModelType().getId() == 3) {
model = m;
break;
}
}
Run Code Online (Sandbox Code Playgroud)
请注意这段代码只是在查询语句中过滤那些类型id等于3的模型,只需要几行.
更多阅读:
Vla*_*cea 43
处理的最好方法LazyInitializationException是使用JOIN FETCH指令:
Query query = session.createQuery(
"from Model m " +
"join fetch m.modelType " +
"where modelGroup.id = :modelGroupId"
);
Run Code Online (Sandbox Code Playgroud)
无论如何,不要使用以下一些答案所建议的反模式:
有时,DTO投影是比获取实体更好的选择,这样,你就不会得到任何实体LazyInitializationException.
Smr*_*thy 12
对于下面的注释,我得到了一对多关系的相同错误.
@OneToMany(mappedBy="department", cascade = CascadeType.ALL)
Run Code Online (Sandbox Code Playgroud)
添加fetch = FetchType.EAGER后更改如下,它对我有用.
@OneToMany(mappedBy="department", cascade = CascadeType.ALL, fetch=FetchType.EAGER)
Run Code Online (Sandbox Code Playgroud)
如果你使用spring data jpa,spring boot你可以在application.properties中添加这一行
spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true
Run Code Online (Sandbox Code Playgroud)
小智 8
这个例外因为你打电话session.getEntityById(),会话将被关闭.因此,您需要将实体重新附加到会话中.或者Easy解决方案只是配置default-lazy="false" 为您entity.hbm.xml或者如果您使用注释只是添加@Proxy(lazy=false)到您的实体类.
我遇到了同样的问题。我认为解决此问题的另一种方法是,您可以按以下方式更改查询以加入从模型中获取元素的联接:
Query query = session.createQuery("from Model m join fetch m.element where modelGroup.id = :modelGroupId")
Run Code Online (Sandbox Code Playgroud)
小智 5
这意味着您尝试访问的对象未加载,因此编写一个查询,对您尝试访问的对象进行连接提取。
例如:
如果您尝试从 ObjectA 获取 ObjectB,其中 ObjectB 是 ObjectA 中的外键。
询问 :
SELECT objA FROM ObjectA obj JOIN FETCH obj.objectB objB
Run Code Online (Sandbox Code Playgroud)
在不同的用例中面临相同的异常。
用例:尝试使用 DTO 投影从数据库读取数据。
解决方案:使用get方法而不是load。
通用操作
public class HibernateTemplate {
public static Object loadObject(Class<?> cls, Serializable s) {
Object o = null;
Transaction tx = null;
try {
Session session = HibernateUtil.getSessionFactory().openSession();
tx = session.beginTransaction();
o = session.load(cls, s); /*change load to get*/
tx.commit();
session.close();
} catch (Exception e) {
e.printStackTrace();
}
return o;
}
Run Code Online (Sandbox Code Playgroud)
}
持久化类
public class Customer {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "Id")
private int customerId;
@Column(name = "Name")
private String customerName;
@Column(name = "City")
private String city;
//constructors , setters and getters
}
Run Code Online (Sandbox Code Playgroud)
客户DAO接口
public interface CustomerDAO
{
public CustomerTO getCustomerById(int cid);
}
Run Code Online (Sandbox Code Playgroud)
实体传输对象类
public class CustomerTO {
private int customerId;
private String customerName;
private String city;
//constructors , setters and getters
Run Code Online (Sandbox Code Playgroud)
}
工厂级
public class DAOFactory {
static CustomerDAO customerDAO;
static {
customerDAO = new HibernateCustomerDAO();
}
public static CustomerDAO getCustomerDAO() {
return customerDAO;
}
Run Code Online (Sandbox Code Playgroud)
}
实体特定的 DAO
public class HibernateCustomerDAO implements CustomerDAO {
@Override
public CustomerTO getCustomerById(int cid) {
Customer cust = (Customer) HibernateTemplate.loadObject(Customer.class, cid);
CustomerTO cto = new CustomerTO(cust.getCustomerId(), cust.getCustomerName(), cust.getCity());
return cto;
}
Run Code Online (Sandbox Code Playgroud)
}
检索数据:测试类
CustomerDAO cdao = DAOFactory.getCustomerDAO();
CustomerTO c1 = cdao.getCustomerById(2);
System.out.println("CustomerName -> " + c1.getCustomerName() + " ,CustomerCity -> " + c1.getCity());
Run Code Online (Sandbox Code Playgroud)
当前数据
Hibernate系统生成的查询和输出
休眠:从 CustomerLab31 customer0_ 中选择 customer0_.Id 作为 Id1_0_0_、customer0_.City 作为 City2_0_0_、customer0_.Name 作为 Name3_0_0_,其中 customer0_.Id=?
客户名称 -> 科迪,客户城市 -> 洛杉矶
| 归档时间: |
|
| 查看次数: |
400882 次 |
| 最近记录: |