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?
Related
First, let me list the things I have used:
Eclipse JEE version 2021-03
Apache Tomcat Server 9
Hibernate ORM version 5.2.18.Final
PostgreSQL 14
Java 8
Some driver I have used: the required in lib of Hibernate ORM, postgresql-42.2.22.jar, jaxb-api-1.0.jar
Second is my code:
In the main class, I use it to run the application I let the name of class is CreateStudentDemo in the phucldh.Demo package in the src folder
public static void main(String[] args) {
// create session factory
SessionFactory factory = new Configuration().configure("hibernate.cfg.xml").addAnnotatedClass(Student.class).buildSessionFactory();
// create session
Session session = factory.getCurrentSession();
try {
// create a student object
Student tempStudent = new Student("Le", "Phuc", "phucldh.work#gmail.com");
// start a transaction
session.beginTransaction();
// save the student object
session.save(tempStudent);
// commit transaction
session.getTransaction().commit();
} catch (Exception e) {
System.out.println("Create student demo error: " + e.getMessage());
} finally {
factory.close();
}
}
And to connect to PostgreSQL I have a configuration file hibernate.cfg.xml in the src folder and the content of this file:
<session-factory>
<!-- JDBC Database connection settings -->
<property name="connection.driver_class">org.postgresql.Driver</property>
<property name="connection.url">jdbc:postgresql://localhost:5432/HibernateLearn</property>
<property name="connection.username">postgres</property>
<property name="connection.password">********</property>
<!-- JDBC connection pool settings ... using built-in test pool -->
<property name="connection.pool_size">1</property>
<!-- Select our SQL dialect -->
<property name="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</property>
<!-- Set the current session context -->
<property name="current_session_context_class">thread</property>
<!-- Disable the second-level cache -->
<property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property>
<!-- Echo the SQL to stdout -->
<property name="show_sql">true</property>
<!-- Drop and re-create the database schema on startup -->
<property name="hbm2ddl.auto">create</property>
</session-factory>
That all I have done but when I running I have a problem:
INFO: HHH000206: hibernate.properties not found
Exception in thread "main" java.lang.NoSuchMethodError: 'javax.xml.bind.JAXBContext javax.xml.bind.JAXBContext.newInstance(java.lang.Class[])'
at org.hibernate.boot.cfgxml.internal.JaxbCfgProcessor.unmarshal(JaxbCfgProcessor.java:122)
at org.hibernate.boot.cfgxml.internal.JaxbCfgProcessor.unmarshal(JaxbCfgProcessor.java:65)
at org.hibernate.boot.cfgxml.internal.ConfigLoader.loadConfigXmlResource(ConfigLoader.java:57)
at org.hibernate.boot.registry.StandardServiceRegistryBuilder.configure(StandardServiceRegistryBuilder.java:163)
at org.hibernate.cfg.Configuration.configure(Configuration.java:258)
at phucldh.Demo.CreateStudentDemo.main(CreateStudentDemo.java:15)
And I see that line 15 of CreateStudentDemo.java is the line about
SessionFactory factory = new Configuration().configure("hibernate.cfg.xml").addAnnotatedClass(Student.class).buildSessionFactory();
So I hope that anybody can help me find what I have wrong. Thank everybody very much. Hope all have a nice day.
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.
I am getting the below error while running my Hibernate program on Hibernate 5.0.1:
Exception in thread "main" org.hibernate.MappingException: Unknown entity: com.abhinav.hibernate.UserDetails
at org.hibernate.internal.SessionFactoryImpl.getEntityPersister(SessionFactoryImpl.java:776)
at org.hibernate.internal.SessionImpl.getEntityPersister(SessionImpl.java:1542)
at org.hibernate.engine.internal.ForeignKeys.isTransient(ForeignKeys.java:225)
at org.hibernate.event.internal.AbstractSaveEventListener.getEntityState(AbstractSaveEventListener.java:499)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:99)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:58)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:778)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:751)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:756)
at com.abhinav.hibernate.main.HibernateTest.main(HibernateTest.java:26)
Below is the configuration file:
<session-factory>
<!-- Database connection settings -->
<property name="connection.driver_class">org.postgresql.Driver</property>
<property name="connection.url">jdbc:postgresql://localhost:5432/hibernatedb</property>
<property name="connection.username">postgres</property>
<property name="connection.password">password</property>
<!-- JDBC connection pool (use the built-in) -->
<property name="connection.pool_size">1</property>
<!-- SQL dialect -->
<property name="dialect">org.hibernate.dialect.PostgreSQLDialect</property>
<!-- Disable the second-level cache -->
<property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</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>
<mapping resource="com.abhinav.hibernate.UserDetails"/>
</session-factory>
The main class:
package com.abhinav.hibernate.main;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import com.abhinav.hibernate.UserDetails;
public class HibernateTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
UserDetails userDetails = new UserDetails();
userDetails.setUserId(1);
userDetails.setUserName("Abhinav");
Configuration configuration = new Configuration().configure();
StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties());
SessionFactory sessionFactory = configuration.buildSessionFactory(builder.build());
Session session = sessionFactory.openSession();
session.getTransaction();
System.out.println("Session: "+session);
// session.save(userDetails);
session.persist(userDetails);
System.out.println("Session after save: "+session+" User details: "+userDetails.getUserId()+" "+userDetails.getUserName());
session.getTransaction().commit();
}
Entity Class: UserDetails with fields userId and userName.
There are two problems there
You need to use
<mapping class="com.abhinav.hibernate.UserDetails"/>
if you use annotations for mapping (resource is used for xml mappings).
You can't use Hibernate 4 way for building a session factory for Hibernate 5. The correct way:
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Refer for details
Hibernate 5 :- org.hibernate.MappingException: Unknown entity
I am developing a Jersey application which is connected to a PostgreSQL database. I am looking for a solution how to configure Hibernate in a way that it always connects correctly to either the local or the Heroku based database (depending on if I deploy my application locally or if I push it to Heroku).
Using the Heroku guides, I tried something like this:
HibernateUtil.java:
private static SessionFactory buildSessionFactory() {
try {
// Create the SessionFactory from hibernate.cfg.xml
Configuration configuration = new Configuration();
configuration.configure("hibernate.cfg.xml");
configuration.setProperty("hibernate.connection.url",
System.getenv("DATABASE_URL"));
URI dbUri = new URI(System.getenv("DATABASE_URL"));
String username = dbUri.getUserInfo().split(":")[0];
String password = dbUri.getUserInfo().split(":")[1];
String dbUrl = "jdbc:postgresql://" + dbUri.getHost() + ':'
+ dbUri.getPort() + dbUri.getPath();
configuration
.setProperty("hibernate.connection.username", username);
configuration
.setProperty("hibernate.connection.password", password);
configuration.setProperty("hibernate.connection.url", dbUrl);
System.out.println("Hibernate Annotation Configuration loaded");
ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
.applySettings(configuration.getProperties()).build();
System.out.println("Hibernate Annotation serviceRegistry created");
SessionFactory sessionFactory = configuration
.buildSessionFactory(serviceRegistry);
return sessionFactory;
} catch (Throwable ex) {
// Make sure you log the exception, as it might be swallowed
System.err.println("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}
My hibernate.cfg.xml looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 4.0//EN"
"http://hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- Database connection properties - Driver, URL, user, password -->
<property name="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</property>
<property name="hibernate.connection.driver_class">org.postgresql.Driver</property>
<property name="hibernate.connection.url">jdbc:postgresql://localhost/MYAPP</property>
<property name="hibernate.connection.username">user</property>
<property name="hibernate.connection.password">password</property>
<!-- org.hibernate.HibernateException: No CurrentSessionContext configured! -->
<property name="hibernate.current_session_context_class">thread</property>
<!-- Mapping with model class containing annotations -->
<mapping class="com.example.object" />
</session-factory>
</hibernate-configuration>
The idea is that HibernateUtil overrides the hibernate.cfg.xml properties (url, user, password). Deploying locally works but deploying to Heroku fails:
remote: [ERROR] Failed to execute goal de.juplo:hibernate4-maven-plugin:
.1.0:export (default) on project myapp: Execution default of goal de.juplo:hib
rnate4-maven-plugin:1.1.0:export failed: Error calling Driver#connect: Connecti
n to localhost:5432 refused. Check that the hostname and port are correct and t
at the postmaster is accepting TCP/IP connections. Connection refused -> [Help
]
It looks like on Heroku, your app is using the configuration from hibernate.cfg.xml instead of the buildSessionFactory() method. Can you confirm that the buildSessionFactory() is being called?
I think you should remove the hibernate.connection.* properties from your hibernate.cfg.xml and use DATABASE_URL locally. You can either set it in your env, or put it in a .env file and run your app locally with foreman start, which will pick this file up. This is the best way to ensure pairity between dev and prod environments, and it will test your buildSessionFactory() code.
You can even use the Heroku database locally if you desire by following this guide. Capture the Heroku DATABASE_URL and put it in your .env file. Then add the ssl=true&sslfactory=org.postgresql.ssl.NonValidatingFactory args to the JDBC URL.
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 :)