E ai pessoal,
:?: Estou tendo um erro na inicialização do Hibernate, porém não sei se isso está interferindo no seu funcionamento, pois eu executei uma query e ela funcionou sem problemas.
2004-02-03 08:52:22,859 [INFO] util.NamingHelper - Creating subcontext: hibernate
2004-02-03 08:52:22,890 [WARN] impl.SessionFactoryObjectFactory - Could not bind factory to JNDI
javax.naming.NamingException: Context is read only
at org.apache.naming.NamingContext.checkWritable(NamingContext.java:947)
at org.apache.naming.NamingContext.createSubcontext(NamingContext.java:561)
...
at java.lang.Thread.run(Thread.java:534)
:?: Alguém, por ai sabe como posso configurar dois bancos distintos no arquivo de configuração do Hibernate? Tentei fazer isso:
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration
PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-2.0.dtd">
<hibernate-configuration>
<session-factory name="java:comp/env/hibernate/SessionFactory">
<property name="connection.datasource">java:comp/env/jdbc/ComputeasyPG</property>
<property name="show_sql">true</property>
<property name="dialect">net.sf.hibernate.dialect.PostgreSQLDialect</property>
<property name="transaction.factory_class">net.sf.hibernate.transaction.JDBCTransactionFactory</property>
<property name="jdbc.UserTransaction">java:comp/UserTransaction</property>
<!-- Mapping files -->
<mapping resource="br/com/computeasy/hibernate/exemplos/TmpUsuario.hbm.xml"/>
</session-factory>
<session-factory name="java:comp/env/hibernate/SessionFactory">
<property name="connection.datasource">java:comp/env/jdbc/ComputeasyORCL</property>
<property name="show_sql">true</property>
<property name="dialect">net.sf.hibernate.dialect.OracleDialect</property>
<property name="transaction.factory_class">net.sf.hibernate.transaction.JDBCTransactionFactory</property>
<property name="jdbc.UserTransaction">java:comp/UserTransaction</property>
<!-- Mapping files -->
<mapping resource="br/com/computeasy/hibernate/exemplos/Usuario.hbm.xml"/>
</session-factory>
</hibernate-configuration>
Valeu pessoal!
Um grande abraço para todos!
1 - se vc tirar este name do session-factory -> <session-factory name=“java:comp/env/hibernate/SessionFactory”> continua o erro?
2 - nunca fiz o Hibernate se conectar em dois bancos como vc está fazendo, mas para existem um método openSession(Connection connection) em SessionFactory que vc pode usar para o Hibernate usar a conexao que vc passou.
Isso mesmo, retirei o java:comp/env/hibernate/SessionFactory e o erro não ocorreu mais.
:?: Só uma coisa, para que serve este name?
[quote=“ricardolecheta”]
2 - nunca fiz o Hibernate se conectar em dois bancos como vc está fazendo, mas para existem um método openSession(Connection connection) em SessionFactory que vc pode usar para o Hibernate usar a conexao que vc passou.[/quote]
Vou precisar trabalhar constantemente com dois bancos de dados ou talvez até três… Estes acessos não serão esporádicos já que possuo sistemas distintos que trabalham com SQLServer, Oracle e Postgresql.
:idea: Se alguém por ai já teve alguma experiência semelhate. Qualquer dica vai ajudar muito…
Um abraço galera…
é para obter a SessionFactory a partir de um nome JNDI…
vc pode criar 2 Configuration… e para cada uma vc cria uma SessionFactory para obter suas Sessions…
o Configuration possui um método configure() que por default procura o hibernate.cfg.xml, mas vc pode passar outro assim:
[code]Configuration cfg = new Configuration();
Configuration cfg2 = new Configuration();
cfg.configure("/hibernate.cfg.xml");
cfg2.configure("/hibernate2.cfg.xml");
sessionFactory = cfg.buildSessionFactory();
sessionFactory2 = cfg2.buildSessionFactory(); [/code]
entao vc terá duas SessionFactory…
Valeu acho que isso resolve o meu problema, deixo como hibernate.cfg.xml a conexão que eu mais uso e passo por parâmetros as outras.
Estive lendo um tutorial sobre o Hibernate, e o autor utiliza um filter para resgatar a SessionFactory.
:?: É realmente necessário utilizar um filter para gerenciar a SessionFactory?
Por que a SessionFactory não pode ser chamada dentro do JavaBean.
Um abraço galera, segue abaixo o código utilizado no tutorial para resgatar a SessionFactory. :wink:
Retirado de: http://www.gloegl.de/5.html
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import net.sf.hibernate.SessionFactory;
import net.sf.hibernate.Session;
import net.sf.hibernate.Transaction;
import net.sf.hibernate.HibernateException;
import net.sf.hibernate.cfg.Configuration;
public class SessionManager implements Filter
{
protected static ThreadLocal hibernateHolder = new ThreadLocal();
protected static ThreadLocal txHolder = new ThreadLocal();
protected static SessionFactory factory;
public void init(FilterConfig filterConfig) throws ServletException
{
// Initialize hibernate
try
{
factory = new Configuration().configure().buildSessionFactory();
}
catch (HibernateException ex) { throw new ServletException(ex); }
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException
{
if (hibernateHolder.get() != null)
throw new IllegalStateException(
"A session is already associated with this thread! "
+ "Someone must have called getSession() outside of the context "
+ "of a servlet request.");
try {
chain.doFilter(request, response);
}
finally {
Session sess = (Session)hibernateHolder.get();
Transaction tx = (Transaction)txHolder.get();
if (sess != null) {
hibernateHolder.set(null);
try {
if (tx != null) {
tx.commit();
}
sess.close();
}
catch (HibernateException ex) { throw new ServletException(ex); }
}
}
}
public static Session getSession() throws HibernateException
{
Session sess = (Session)hibernateHolder.get();
Transaction tx = (Transaction)txHolder.get();
if (sess == null)
{
sess = factory.openSession();
txHolder.set(sess.beginTransaction());
hibernateHolder.set(sess);
} else {
if (tx == null) {
throw new IllegalStateException("Transaction was allready rolled back");
}
}
return sess;
}
public static void rollback() throws HibernateException {
Transaction tx = (Transaction)txHolder.get();
if (tx == null) {
throw new IllegalStateException("Transaction was allready rolled back");
}
tx.rollback();
txHolder.set(null);
}
public void destroy() {
try {
factory.close();
}
catch (HibernateException ex) { throw new RuntimeException(ex); }
}
}
fazer isso é questão de gosto, a sacada é que vc deve ter uma SessionFactory apenas, neste exemplo o autor usou este Filter para controlar isso.
outro jeito seria simplesmente implementar o pattern ThreadLocal numa classe separada, assim:
http://www.hibernate.org/42.html
no exemplo foi feito o lookup para recuperar a SessionFactory… vc pode alterar isto se quiser, mas lembre-se de criar apenas uma nesta classe…
Ai é só usar esta classe HibernateSession.currentSession() para obter a Session de onde vc precisar…
a outra coisa, bacana este tutorial que vc passou
Fiz uma alteração no filter.
Não tenho certeza se é uma alteração correta. ou se terei que fazer uma classe para cada um dos bancos de dados que estarei utilizando
Vejam:
Estarei pondo apenas partes do código acima:
Primeiro eu crio uma sessionFactory para cada banco de dados
[code]…
protected static SessionFactory factoryPG;
protected static SessionFactory factoryORCL;
public void init(FilterConfig filterConfig) throws ServletException {
// Initialize hibernate
try
{
Configuration pg = new Configuration().configure("hibernate.cfg.xml");
Configuration orcl = new Configuration().configure("Oracle.cfg.xml");
factoryPG = pg.buildSessionFactory();
factoryORCL = orcl.buildSessionFactory();
}
catch (HibernateException ex) { throw new ServletException(ex); }
}
…[/code]
Depois no getSession eu informo a session de qual banco de dados de que estou solicitando:
[code]…
/**
* Resgata a session atual:
*
* @param dataBase - 0: Postgresql, 1: Oracle
*/
public static Session getSession(int dataBase) throws HibernateException {
Session sess = (Session) hibernateHolder.get();
Transaction tx = (Transaction)txHolder.get();
if (sess == null) {
switch (dataBase) {
case 0 : sess = factoryPG.openSession();
case 1 : sess = factoryORCL.openSession();
}
txHolder.set(sess.beginTransaction());
hibernateHolder.set(sess);
} else {
if (tx == null) {
throw new IllegalStateException("Transaction was allready rolled back");
}
}
return sess;
}
…[/code]
o melhor é deixar um filtro apenas mesmo, me parece que sua alteração está certa sim.
O legal de fazer o filtro é que vc pode usar o pattern “Open Session in View”, isto é util quando vc usa o lazy-loading do Hibernate… pq se vc fechar a Session e mandar para a view, sempre que vc for acessar um objeto ainda nao carregado vai dar pau !
ai com o filter, a Session do Hibernate ainda vai estar aberta na view , entao vc pode usar o lazy-loading mais facil…