Bom dia pessoal,
preciso de ajuda com meu sistema, ainda não consegui entender como resolver o problema.
O sistema esta sendo desenvolvido para a plataforma OSGI, utilizando spring e hibernate.
Cada camada está em um plugin diferente, ou seja, tenho um plugin persistencia contendo o model, um plugin dao com todos os DAOs, outro para BO e outro para views.
Tudo está funcionando legal, o problema eu acho que fica na camada de DAO/Model. Já tentei utilizar duas “versões”, em uma delas (vamos chamar de versao1), ocorre uma LazyInitializationException nas coleções quando preciso acessá-las nas views, a outra (versão2) não tem problema de lazy exception só que ocorre uma ConcurrentModificationException (muito imprevisível, por sinal) pois tenho duas ou mais threads acessando uma mesma sessão (segundo pesquisa na web).
Por isso queria saber de vocês qual é a maneira mais correta de fazer tudo isso funcionar.
Segue as classes/relacionamento que considero mais relevantes…
//Classe de persistencia, existem diversas outras
@Entity
@Table(name = "Agencia")
@DynamicInsert
@DynamicUpdate
public class Agencia implements Serializable {
private int prefixo;
private String nome;
private Agencia jurisdicionante;
private Set<Agencia> jurisdicionadas;
//Getters e Setter suprimidos
}
Configuração Spring no plugin Persistencia
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:osgi="http://www.springframework.org/schema/osgi"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi-2.0-m1.xsd">
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
...
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>br.com.sga.persistence.Agencia</value>
</list>
</property>
<property name="hibernateProperties">
<props>
...
</props>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<context:property-placeholder location="jdbc.properties" />
<osgi:service ref="sessionFactory" interface="org.hibernate.SessionFactory" />
<osgi:service ref="transactionManager" interface="org.springframework.transaction.PlatformTransactionManager" />
</beans>
//Interface genérica para todos os DAOs
public interface GenericDAO<T, PK> {
public void save(T entity);
//update, saveOrUpdate, delete, etc.
}
//Interface específica, para construção do proxy baseado por interface
public interface AgenciaDAO extends GenericDAO<Agencia, Integer> {
//pode haver outras funções aqui
}
//Implementação
@Repository("agenciaDAO")
public class AgenciaDAOImpl extends HibernateDAO<Agencia, Integer> implements
AgenciaDAO {
@Autowired(required = true)
public AgenciaDAOImpl(SessionFactory sessionFactory) {
super(sessionFactory);
}
}
Versão 1
//Implementação padrão para todos os DAOs (Versão 1)
public abstract class HibernateDAO<T, PK extends Serializable> implements GenericDAO<T, PK> {
private final Class<T> clazz;
protected final SessionFactory sessionFactory;
public HibernateDAO(SessionFactory sessionFactory) {
ParameterizedType parameterizedType = (ParameterizedType) this.getClass().getGenericSuperclass();
this.clazz = ((Class<T>) parameterizedType.getActualTypeArguments()[0]);
this.sessionFactory = sessionFactory;
}
@Override
public synchronized void save(T entity) {
Session session = sessionFactory.getCurrentSession();
Transaction transaction = null;
try {
transaction = session.beginTransaction();
session.save(entity);
transaction.commit();
} catch (HibernateException hibernateEx) {
if (transaction != null) {
transaction.rollback();
}
//Exception handling
} finally {
if (session.isOpen()) {
session.close();
}
}
};
//update, saveOrUpdate, delete, etc., seguem o mesmo padrão de implementação do save
}
Versão 2
//É a única classe que mudei, todo o resto é o mesmo, inclusive mapeamentos.
public abstract class HibernateDAO<T, PK extends Serializable> implements
GenericDAO<T, PK> {
private final Class<T> clazz;
protected final Session session;
@SuppressWarnings("unchecked")
public HibernateDAO(SessionFactory sessionFactory) {
ParameterizedType parameterizedType = (ParameterizedType) this.getClass().getGenericSuperclass();
this.clazz = ((Class<T>) parameterizedType.getActualTypeArguments()[0]);
this.session = SessionFactoryUtils.openSession(sessionFactory);
}
@Override
public synchronized void save(T entity) {
try {
session.save(entity);
session.flush();
} catch (HibernateException hibernateEx) {
//Exception handling
}
};
//update, svaeOrUpdate, delete, etc.
@PreDestroy
public synchronized void close() {
if (session.isOpen()) {
SessionFactoryUtils.closeSession(session);
}
}
}
Configuração Spring para o plugin DAO
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:osgi="http://www.springframework.org/schema/osgi"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi-2.0-m1.xsd"
default-autowire="byType">
<osgi:reference id="sessionfactory" bean-name="sessionFactory"
interface="org.hibernate.SessionFactory" />
<bean id="agenciaDAO" class="br.com.sga.dao.repository.impl.AgenciaDAOImpl"
depends-on="sessionfactory" />
<osgi:service ref="acessoDAO" interface="br.com.sga.dao.repository.AcessoDAO" />
<context:component-scan base-package="br.com.sga.dao.impl" />
</beans>
Plugin BO
//Interface para o proxy
public interface AgenciaBO {
}
//Implementação
@Service("agenciaBO")
public class AgenciaBOImpl implements AgenciaBO {
private final agenciaDAO agenciaDAO;
@Autowired(required = true)
public AgenciaBOImpl(AgenciaDAO agenciaDAO) {
this.agenciaDAO = agenciaDAO;
}
@Override
public void save(Agencia entity) {
agenciaDAO.save(entity);
}
//update, saveOrUpdate, delete, etc.
}
Configuração Spring plugin BO
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:osgi="http://www.springframework.org/schema/osgi" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi-2.0-m1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd"
default-autowire="byType">
<!-- OSGI REFERENCES -->
<osgi:reference id="transactionManager" bean-name="transactionManager"
interface="org.springframework.transaction.PlatformTransactionManager" />
<osgi:reference id="agenciaDAO" interface="br.com.sga.dao.repository.AgenciaDAO" />
<!-- BEANS -->
<bean id="agenciaBO" class="br.com.sga.business.service.impl.AgenciaBOImpl" />
<!-- OSGI SERVICES -->
<osgi:service ref="agenciaBO" interface="br.com.sga.business.service.AgenciaBO" />
<!-- CONFIG -->
<context:annotation-config />
<context:component-scan base-package="br.com.sga.business.service.impl" scoped-proxy="interfaces" />
<tx:annotation-driven transaction-manager="transactionManager" />
</beans>
Finalmente, acho que é isso. valeu galera…