Reputation: 15174
I have an HBM file populated for a table we have. I think created the Java Entity that Hibernate would use. In the Entity, I have the empty constructor and then a full constructor that has all the fields. I put them in the same order as what is in the HBM file as well.
Every time Hibernate uses the Entity, it always calls the empty constructor instead of the full constructor.
Is there a trick or anything that would make Hibernate use the full constructor? This also is happening for all children of the Entity as well. I am running into an issue where my query.list() is running slow and want to get this to work to see if it will speed things up.
Thank you!
Note: I did not include the contents of the HBM and Java file because (a) it contains company information and (b) it is rather large. It would take a very long time to strip things out. I am sorry if this is inconvenient :(
Upvotes: 1
Views: 3005
Reputation: 575
After some research I found this useful
An hibernate entity must define a no argument constructor. Hibernate creates new instances of entities through reflection, with the Class.newInstance()
method. This method requires a no argument constructor to succeed. If an entity does not provide a no argument constructor, an Hibernate’s InstantiationException
will be thrown.
Check here
Upvotes: 0
Reputation: 9328
There are 3 strategies for instantiating objects through Hibernate (that I know of).
Standard method
HQL or criteria queries like select from cat
will create POJOs (here, instances of Cat
- or subclasses), and Hibernate will do so by calling the no-arg constructor. From documentation :
All persistent classes must have a default constructor (which can be non-public) so that Hibernate can instantiate them using java.lang.reflect.Constructor.newInstance(). It is recommended that this constructor be defined with at least package visibility in order for runtime proxy generation to work properly.
Choosing a Constructor with HQL
One can reference a specific constructor to invoke through a specially crafted select statement in a HQL query.
E.g. select new com.example.Cat(cat.id, cat.name) from Cat
works. If your request is correctly defined, you can also use functions such as count()
in your select. This would call a 2 arguments contructor on Cat
- although I do not think this will automatically adjust to find another class that Cat
in case of polymorphism.
You can explore various possibilities (e.g. how to build a list) in the documentation : http://docs.jboss.org/hibernate/core/3.3/reference/en/html/queryhql.html#queryhql-select
Using a result transformer
The concept of ResultTransformer
allows you to specify, on a Criteria
objet, how results will be transformed to objects. Using an AliasToBeanConstructorResultTransformer
, which takes a java.lang.Constructor
as an argument, you can choose the constructor being called.
(By default, every criteria has a ResultTransformer
which is RootEntityResultTransformer
).
Upvotes: 5
Reputation: 3877
Are you working with really large resultsets? What repository are you using? I've encountered similar issues and it came down to database settings for hibernate.
Here are a few other questions to check out:
Simple hibernate query returning very slowly
Hibernate queries slow down drastically after an entity is loaded in the session
For hibernate, I've found the following settings you may tweak to improve performance. :
// update - Create if schema doesn't exists; update if column doesn't
// exist
// create - Empties the database before creating it
// create-drop - Drops the database when the SessionFactory is closed
config.setProperty("hibernate.hbm2ddl.auto", hbm2ddlMode);
config.setProperty("hibernate.cache.use_query_cache", "true");
config.setProperty("hibernate.cache.use_second_level_cache", "true");
config.setProperty("hibernate.cache.region.factory_class",
"org.hibernate.cache.ehcache.EhCacheRegionFactory");
config.setProperty("hibernate.cache.provider_class",
"org.hibernate.cache.EhCacheProvider");
// config.setProperty("hibernate.cache.provider_class",
// "org.hibernate.cache.NoCacheProvider");
config.setProperty("hibernate.jdbc.fetch_size", "1000");
config.setProperty("hibernate.jdbc.batch_size", "50"); //batches network calls in one
config.setProperty("hibernate.jdbc.use_scrollable_resultset", "true");
config.setProperty("hibernate.connection.provider_class",
"org.hibernate.connection.C3P0ConnectionProvider");
config.setProperty("hibernate.c3p0.acquire_increment", "1");
config.setProperty("hibernate.c3p0.idle_test_period", "10");
config.setProperty("hibernate.c3p0.min_size", "1");
config.setProperty("hibernate.c3p0.max_size", "8");
config.setProperty("hibernate.c3p0.timeout", "10");
config.setProperty("javax.persistence.validation.mode", "none");
config
.setProperty("hibernate.temp.use_jdbc_metadata_defaults", "false");
config.setProperty("hibernate.show_sql", "false");
Note, these specific settings may not be ideal for your database, but you should be able to improve performance by tweaking the properties above. Detailed explanation can be found on the doc site.
For sqlite, you have to tweak a few additional settings:
config.setPageSize(4096);
config.setCacheSize(-256);
config.setSharedCache(true);
config.setReadUncommited(true);
//Be careful with these settings if needed for concurrency
//***************************************************
config.setLockingMode(LockingMode.NORMAL);
config.setSynchronous(SynchronousMode.NORMAL);
config.setJournalMode(JournalMode.WAL);
config.setTempStore(TempStore.MEMORY);
//***************************************************
Postgres is a bit simpler and more isolated to the database settings itself. However, keep in mind the query optimizer kicks in after the first query run.
Upvotes: 1