Loading Hibernate properties outside context isn't working - java

I'm facing some strange problem here and right now I'm stuck. I've read some other posts on this regards and some of then helped me to configure my enviroment, but for some reason that I couldn't find out why it is not working.
I need to place the hibernate.connection.url, hibernate.connection.username and hibernate.connection.password properties outside my WAR file to make easier to configure theese parameters when the system is deployed on different servers. So after digging over the Google I find this solution:
applicationContext.xml:
...
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="sessionFactory" class="br.myapp.DataBaseConfig"/>
And the class DataBaseConfig
public class DataBaseConfig extends AnnotationSessionFactoryBean {
private final BaseConfig baseConfig = new BaseConfig();
public DataBaseConfig() {
super();
}
#Override
protected SessionFactory buildSessionFactory() throws Exception {
Properties dbConfig = new Properties();
dbConfig = baseConfig.getPropertiesFile("myPropertiesFile");
Configuration config = new Configuration();
Enumeration<Object> props = dbConfig.keys();
while ( props.hasMoreElements() ){
String key = (String)props.nextElement();
config.setProperty( key , dbConfig.getProperty(key) );
}
config.addResource("hibernate.cfg.xml");
SessionFactory sessionFactory = config.buildSessionFactory();
return sessionFactory;
}
}
And my hibernate.cfg.xml file looks like:
<hibernate-configuration>
<session-factory>
<mapping class="br.myapp.model.SomeClass1" />
<mapping class="br.myapp.model.SomeClass2" />
<mapping class="br.myapp.model.SomeClass3" />
</session-factory>
</hibernate-configuration>
My myPropertiesFile is:
hibernate.connection.driver_class=oracle.jdbc.driver.OracleDriver
hibernate.connection.url=jdbc:oracle:thin:#localhost:1524:MyDB
hibernate.connection.username=user
hibernate.connection.password=passpass
hibernate.default_schema=myschema
hibernate.connection.oracle.jdbc.V8Compatible=true
hibernate.show_sql=true
hibernate.dialect=org.hibernate.dialect.Oracle10gDialect
#I'm usign c3p0 to pool connections
hibernate.c3p0.min_size=5
hibernate.c3p0.max_size=20
hibernate.c3p0.timeout=300
hibernate.c3p0.max_statements=50
hibernate.c3p0.idle_test_period=3000
hibernate.cache.use_second_level_cache=true
hibernate.cache.use_query_cache=true
hibernate.cache.region.factory_class=net.sf.ehcache.hibernate.EhCacheRegionFactory
With this enviroment when I'm trying to get something from the database without success on this way:
final SomeClass1 sm = repository.find(SomeClass1.class)
.where( Restrictions.eq( "someField" , varFromWebForm ) )
.uniqueResult();
But sm always returns null, and on the console there is no query printed even with hibernate.show_sql=true setted.
The strange thing is that when I change the configurations on my applicationContext.xml file like this
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="configLocation">
<value>classpath:/hibernate.cfg.xml</value>
</property>
</bean>
And the hibernate.cfg.xml file to this
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
<property name="hibernate.connection.url">jdbc:oracle:thin:#localhost:1524:MyDB</property>
<property name="hibernate.connection.username">user</property>
<property name="hibernate.connection.password">passpass</property>
<property name="hibernate.default_schema">myschema</property>
<property name="hibernate.connection.oracle.jdbc.V8Compatible">true</property>
<property name="hibernate.show_sql">true</property>
<property name="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</property>
<property name="hibernate.c3p0.min_size">5</property>
<property name="hibernate.c3p0.max_size">20</property>
<property name="hibernate.c3p0.timeout">300</property>
<property name="hibernate.c3p0.max_statements">50</property>
<property name="hibernate.c3p0.idle_test_period">3000</property>
<property name="hibernate.cache.use_second_level_cache">true</property>
<property name="hibernate.cache.use_query_cache">true</property>
<property name="hibernate.cache.region.factory_class">net.sf.ehcache.hibernate.EhCacheRegionFactory</property>
<mapping class="br.myapp.model.SomeClass1" />
<mapping class="br.myapp.model.SomeClass2" />
<mapping class="br.myapp.model.SomeClass3" />
</session-factory>
</hibernate-configuration>
All works fine. So it is like the code that read the properties and inject it on the Configuration to Hibernate (DataBaseConfig) is not working properly.
Can someone point me out what am I doing wrong?
UPDATE:
There is no exceptions on the console. it just doesn't work.
UPDATE 2
This is the log from the apache server. I'm using VRaptor as controllerManager and the only things that appear when I call my method to do the query is the requisition to the controller nothing else, therefore I think that it is not important to put it here.
I've try to put the log here but the SO doesn't let me because it extrapolate the characters limit for a question so, here is a link to pastebin: http://pastebin.com/cASD7EPu
Thanks.

When you say (DataBaseConfig) is not working properly : Do you have somes Exceptions and a StackTrace returned by the Spring Container. Try To launch your app in debug/trace mode to see what happen exactly.

I've managed to solve my own question by changing the way I read the configurations. The waqy I was doing does not work and I couldn't find out why. Which is like this:
#Override
protected SessionFactory buildSessionFactory() throws Exception {
Properties dbConfig = new Properties();
dbConfig = baseConfig.getPropertiesFile("myPropertiesFile");
Configuration config = new Configuration();
Enumeration<Object> props = dbConfig.keys();
while ( props.hasMoreElements() ){
String key = (String)props.nextElement();
config.setProperty( key , dbConfig.getProperty(key) );
}
config.addResource("hibernate.cfg.xml");
SessionFactory sessionFactory = config.buildSessionFactory();
return sessionFactory;
}
So I was reading the Hibernate#Configuration docs and find the method configure(File file). Then I took the hibernate.cfg.xml out of my context and put it on my configs directory (which I get from a Util class of my project) and it work fine. The final method is like:
#Override
protected SessionFactory buildSessionFactory() throws Exception {
Configuration config = new Configuration();
config.configure(
new File( BaseConfig.CONFIG_BASE
+ File.separator
+ "hibernate.cfg.xml" )
);
SessionFactory sessionFactory = config.buildSessionFactory();
return sessionFactory;
}
And now it is working fine. I would like to find out why the previous configuration did not work to understand. This is not the best solution but solved my problem.
I've a friend here that always says: "It isn't an ugly solution until someone else show a better one!". So for now I will stick with this one.
Thanks to the ones who came here and tryied to help me.
I will not mark this answer as the right one for some time to see if someone else can show me a better solution :)

Related

hibernate.hbm2ddl.auto - Create-Drop is not working in Hibernate

I am using create-drop for hibernate and its not working. I am restarting my project but still its not dropping my old table and its data.
<property name="hibernate.hbm2ddl.auto">create-drop</property>
hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC"-//Hibernate/HibernateConfiguration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- Database connection settings -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/demo</property>
<property name="connection.username">root</property>
<property name="connection.password">****</property>
<!-- SQL dialect -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.show_sql">true</property>
<!-- Drop and re-create the database schema on startup -->
<property name="hibernate.hbm2ddl.auto">create-drop</property>
<property name="hibernate.current_session_context_class">thread</property>
<!-- Names the annotated entity class -->
<mapping class="domains.Test"/>
<mapping class="domains.LoginDetails"/>
<mapping class="domains.User"/>
</session-factory>
</hibernate-configuration>
I found that, I don't know if I am wrong or correct. While I was running my application hibernate was not dropping any table nor creating any table even though create-drop is mentioned in configuration file. But when I created one new object and save method is called hibernate dropped all tables and created all tables again. So question raised in my mind that may be hibernate is only performing operation when there is a sessionFactory object is there. I am using Singleton pattern to create sessionFacotry object. So until I am not doing any CRUD operation sessionFactory object will not be created and hence it was not dropping or recreating all tables. Please correct me if I am wrong.
public static SessionFactory sessionFactory;
private HibernateUtility(){}
public static SessionFactory getSessionFactory() {
try{
if (sessionFactory == null) {
sessionFactory = new Configuration().configure().buildSessionFactory();
}
}catch(Exception e) {
System.out.println(e);
}
return sessionFactory;
}
Until I am calling this method from DAO hibernate not doing any create or drop table operation. This is what I am trying to say. Until sessionFactory object is not created create-drop not working
Analysis
(Note: This is just a guess.)
It seems an instance of the SessionFactory interface is not getting closed (by Tomcat?).
Solution
It is necessary to configure Tomcat to manage the Hibernate's SessionFactory appropriately. Please refer to:
Using Hibernate with Tomcat |JBoss Developer.
TomcatHibernate - Tomcat Wiki.
Setup Hibernate Session Factory in Tomcat - Stack Overflow.
dev - Tomcat, JPA, Hibernate and MySQL. The related gist: Integrate Hibernate 4.1 in a raw Tomcat 7 (no JPA, no Spring, etc) ยท GitHub.
configure hibernate with embedded tomcat 7 programmatically - Stack Overflow.

Hibernate 5 + Non JTA datasource: object not being stored

I'm facing a problem and have no idea what's going wrong. The cenary:
Hibernate 5
Apache Tomcat 9
JSF 2
No Spring. It's important to say because I saw this problem happening realted with Spring use, but this is not my case.
The datasource was correctly configured on Tomcat, and the Hibernate also creates the tables and update schemma correctly for each new Entity.
The problem is when I try to persist a new Entity, nothing happens. Then I tried to include "flush()" call... but then I've got an error saying I have no transaction active:
javax.persistence.TransactionRequiredException: no transaction is in progress
It seems to be a problem related with a transaction requirement, but I have also tried:
include "#Transactional" annotation on method;
include "#Transactional" annotation on class;
Force begin transaction with "beginTransaction()" call but then I've got a NullPointer;
So... I don't know what do to.
Follow you'll see my relevant code. Can you help me to solve this problem?
persistence.xml file:
<persistence-unit name="hospitalPU" transaction-type="RESOURCE_LOCAL">
<description>
Persistence unit for Hibernate
</description>
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<non-jta-data-source>java:comp/env/jdbc/hospitalDatasource</non-jta-data-source>
<properties>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.hbm2ddl.auto" value="update" />
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect" />
<property name="hibernate.format_sql" value="true" />
<property name="hibernate.default_catalog" value="hospital" />
<property name="hibernate.connection.datasource" value="java:comp/env/jdbc/hospitalDatasource"/>
<property name="hibernate.id.new_generator_mappings" value="false" />
</properties>
</persistence-unit>
My Entity:
#Entity(name="Dominio")
#Table(name="Dominio")
public class Dominio implements Serializable{
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue
private Integer id;
here goes another fileds and getters/setters...
On my managed bean, I have:
#PersistenceUnit
private EntityManagerFactory emf;
And:
protected synchronized EntityManager getEntityManager() {
if (emf == null) {
emf = Persistence.createEntityManagerFactory("hospitalPU");
}
return emf.createEntityManager();
}
It seems to work fine, but the problem happens here:
With this, nothing happen and no Exception occours. Just NOTHING happens:
getEntityManager().persist(getDominio());
With this, I have "javax.persistence.TransactionRequiredException: no transaction is in progress":
getEntityManager().persist(getDominio());
getEntityManager().flush(); //exception occours here!
What am I doing wrong? Thanks in advance for you all!
you need to more configure the persistence.xml or hibernate.cfg.xml. you can refer bellow link to configure these xml files.
https://gist.github.com/imanoleizaguirre/3819393
http://www.journaldev.com/7122/jsf-spring-hibernate-integration-example-tutorial
http://www.javaknowledge.info/simple-crud-using-jsf2hibernate-integration-and-mysql/
This one here clearly explains what is the problem:
"javax.persistence.TransactionRequiredException: no transaction is in progress"
First, you have clearly mentioned that you are using a Non-JTA datasource. meaning that the container will no longer manage for you transaction boundaries. You must begin and commit/rollback transactions on your own. You therefore need to follow the following:
EntityManager em = ....
EntityTransaction et = em.getTransaction();
try {
et.begin();
em.persist(entity);
et.commit();
} catch (Exception ex) {
et.rollback();
throw new RuntimeException(ex);
}

Running H2 embedded database in spring / hibernate

I am trying to create an spring boot application utilizing hibernate and h2. From what I have found online this can be done but I am having a problem starting the application. Hibernate is complaining that it cannot make a connection to the h2 database I have created.
Caused by: org.hibernate.HibernateException: Unable to make JDBC Connection [jdbc:h2:~/todo]
My theory is that the application needs to start for the database be available but hibernate is not letting the application start without the connection.
Am I on the right track with this theory, has there been similar issues that someone knows how to get around this?
Hibernate config
**<?xml version="1.0" encoding="UTF-8"?>
<hibernate-configuration>
<session-factory>
<!--Database connection settings -->
<property name="connection.driver_class">com.mysql.cj.jdbc.Driver</property>
<property name="connection.url">jdbc:h2:~/todo</property>
<property name="connection.username">username</property>
<property name="connection.password" />
<!--Set the database dialect -->
<property name="dialect">org.hibernate.dialect.H2Dialect</property>
<!--Echo all executed SQL to stdout-->
<property name="show_sql">true</property>
<!--Drop and re-create the database schema on startup-->
<property name="hbm2ddl.auto">create</property>
<!--Name the annotated Entity classes -->
<mapping class="com.todo.beans.User" />
</session-factory>
</hibernate-configuration>**
h2 config
import org.h2.server.web.WebServlet;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
#Configuration
public class WebConfiguration {
#Bean
ServletRegistrationBean h2servletRegistration(){
ServletRegistrationBean registrationBean = new ServletRegistrationBean( new WebServlet());
registrationBean.addUrlMappings("/console/*");
return registrationBean;
}
}
change following properties in hibernate config
<property name="connection.driver_class">org.h2.Driver</property>
<property name="connection.url">jdbc:h2:mem:todo;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
</property>
Problem is with driver class; you may keep url as it is.
This sample project can help you.
https://github.com/dornala/HotelStackoverflow

change datasource url at runtime in spring

I have spring application configured via annotations. Here is part of my config
#Configuration
#EnableTransactionManagement
public class JpaSpringConfiguration {
#Bean(destroyMethod = "close")
#Lazy
#Primary
public BasicDataSource dataSource(#Value("${statistics.hostname}") String statisticsHostname) {
final BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName("org.postgresql.Driver");
String url = String.format("jdbc:postgresql://%s:5432/statistics-db", statisticsHostname);
dataSource.setUrl(url);
....
return dataSource;
}
#Bean
public static PropertyPlaceholderConfigurer propertyPlaceholderConfigurer() {
final PropertyPlaceholderConfigurer placeholderConfigurer = new PropertyPlaceholderConfigurer();
placeholderConfigurer.setSystemPropertiesMode(SYSTEM_PROPERTIES_MODE_OVERRIDE);
Properties properties = new Properties();
properties.setProperty("statistics.hostname", "localhost");
placeholderConfigurer.setProperties(properties);
return placeholderConfigurer;
}
Until recently we had xml configuration
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
<property name="properties">
<props>
<prop key="statistics.hostname">localhost</prop>
</props>
</property>
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" lazy-init="true" destroy-method="close">
<property name="driverClassName" value="org.postgresql.Driver" />
<property name="url" value="jdbc:postgresql://${statistics.hostname}:5432/statistics-db" />
<property name="username" value="user" />
<property name="password" value="password" />
</bean>
When user selected different server to connect to we set system property and closed application context and refreshed
System.setProperty("statistics.hostname", hostname)
applicationContext.close()
applicationContext.refresh()
This does not work when I use annotation configuration.
My questions are:
why it does not work now?
how to get rid of setting hostname via system property altogether?
EDIT: I just found out that I forgot ${} around the name of the parameter in method dataSource(). So it works now but question 2 still remains.
not sure why it doesnt work, but you may try to do couple more things:
Is closing context before refresh really needed? Try to only refresh it.
You can mark your bean as #RefreshScope ( but it requires spring cloud ) and refresh it using /refresh endpoint. That would require another endpoint to actually update your host on a bean before calling refresh.
"how to get rid of setting hostname via system property altogether?"
pass that to property file which is the way it is normally configured. If you are using spring boot, then you only have to configure:
spring.datasource.url=
spring.datasource.username=
spring.datasource.password=
...
properties. Datasource bean would be created using those values for you.

Hibernate returns wrong results after updating rows

I am still a newbie with Hibernate but I am getting crazy. The thing is that after updating some Entities in the database Hibernate is not able to return me those changes. Also making SQL Queries return old values (Compared with the results I get from MySQLWorkbench)
I thought that it was a Cache problem, however in my hibernate.cnf,xml I have the following lines disabling 2nd line cache. Has anybody a solution for that problem?. I am using Hibernate v.4.3.1.
The conf file looks like:
<property name="connection.pool_size">3</property>
<!-- SQL dialect -->
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- Enable Hibernate's automatic session context management -->
<property name="current_session_context_class">thread</property>
<!-- Disable the second-level cache -->
<property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property>
<property name="hibernate.cache.use_second_level_cache">false</property>
<property name="hibernate.cache.use_query_cache">false</property>
<!-- Echo all executed SQL to stdout -->
<property name="show_sql">true</property>
<property name="format_sql">false</property>
<property name="show_comments">false</property>
I have a class to open the session factory:
public class HibernateUtil {
private static final SessionFactory sessionFactory;
static {
try {
// Create the SessionFactory from hibernate.cfg.xml
Configuration configuration = new Configuration();
configuration.configure();
StandardServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(
configuration.getProperties()).build();
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
} catch (Throwable ex) {
// Make sure you log the exception, as it might be swallowed
System.err.println("Initial SessionFactory creation failed." + ex);
ex.printStackTrace();
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionFactory() {
sessionFactory.getCache().evictAllRegions();
sessionFactory.getCache().evictEntityRegions();
sessionFactory.getCache().evictCollectionRegions();
sessionFactory.getCache().evictQueryRegions();
return sessionFactory;
}
}
UPDATE
I am using GWT+RequestFactory+Hibernate the thing is that changing the RequestProxy EntityProxy to ValueProxy (as I dont need an EntityProxy) is working fine. Could it be a problem of RequestFactory?

Categories

Resources