Resolving Hibernate subtleties - java

I have spent several days now researching Hibernate and have several small questions about it that in and of themselves don't really merit cluttering SO but I think, together, help give some insight to how Hibernate operates as a whole:
To create a Hibernate entity, one must add a reference to it in the hibernate.cfg.xml config file as well as annotating the respective POJO as being an #Entity. This feels horribly redundant. Why can you just use the annotation and just skip the XML entry?
Hibernate seems to have great built-in support for parameter binding with its Query API, but I see no such options for the Criteria API. Is parameterizing possible with Criteria instances: if so, how, and if not, why?
I see many L2 (2nd level) Cache Providers: EhCache, OSCache, SwarmCache, etc. Is it possible to write your own CacheProvider, throw it on the ruuntime classpath and have Hibernate use your own homegrown cache system (like SLF4J does with logger bindings)?
Thanks in advance!

Because it would force Hibernate to scan all the classes of the classpath to discover annotated classes. And because you might have some entities in the classpath that you don't want to use in your application. Or you might want to have some entities in a session factory, and some others in another one. Or even the same entity in two seperate session factories.
The Criteria API has methods which bind the parameters directly: Restrictions.eq("someProperty", someValue); for example.
It's of course possible to write your own second-level cache, but you would have to configure Hibernate to use it, as you do with all the other providers. Dropping the classes in the classpath is not sufficient.

Related

Does Hibernate have to drive database design?

I spent all of yesterday reading various articles/tutorials on Hibernate and although I am blown-away by how powerful it is, I have one major concern with it.
It seems that the standard practice is to allow Hibernate to design/generate your DB schema for you, which is a new and scary concept that I am choking on. From the tutorials I read, you just add a new entity to your hibernate.cfg.xml config file, annotate any POJO you want with #Entity, and voila - Hibernate creates the tables for you. Although this is very cool, it has me wondering about a handful of scenarios:
What if you already have a DB schema and the one Hibernate wants to generate for you does not conform to it? What if you have a crazy DBA that refuses to budge on the pre-defined (non-Hibernate) schema?
What if you have reference tables with tens of thousands of records in it (like all the cities in the world)? Would you have to instantiate and save() tens of thousands of unique POJOs or is there a way to configure Hibernate so it will honor and not overwrite data already existing in your tables?
What if you want to do perf tuning on your schema/tables? This includes indexing, normalizing above and beyond what Hibernate creates automatically?
What if you want to add constraints or triggers to your tables? Indexes?
I guess at the root of this is the following:
It looks like Hibernate creates and forces a particular schema/config on your DB. I am wondering how this agenda will conflict with our platform standards, our DBA philosophies, and our ability to perf tune/tweak tables that Hibernate interacts with.
Thanks in advance.
I think you're attributing too much power to Hibernate.
Hibernate does have an idiom that may influence database implementation.
Hibernate does not generate a schema for you unless you ask it to do so. It's possible to start with an existing schema and map it to Java objects using Hibernate. But it might not be possible or optimal if the schema conflicts with Hibernate requirements.
If the DBA won't budge - as they shouldn't - or Hibernate can't accomodate you, then you have your answer: you can't use Hibernate.
Your DBA might consent, but your app might find that the dynamic SQL that's generated for you by Hibernate isn't what you want.
Fortunately for you, it's not the only game in town.
I don't think implementations have to be all or none. If you use simple JDBC to access reference data, what's the harm?
Database design considerations should be independent of Hibernate. Constraints, triggers, normalization, and indexes should be driven by business needs, not your middleware choices.
If you don't have a solid object model, or the schema can't accomodate it, then you should reconsider Hibernate. There's straight JDBC, stored procedures, Spring JDBC, and iBatis as alternatives.
Hibernate comes with a default way to map objects to tables - like several tools/libraries, it favours convention over configuration for simplicity.
However, if you want to map the entities to database tables differently, you can explicitly tell Hibernate how these are mapped (from simple attributes such as changing the table name, through to redefining the foreign-key relationships between related entities and how this is persisted).
If you do this correctly, you don't need to instantiate and save existing data, as this would be pointless - the database already contains the information about the entities in exactly the form that Hibernate understands. (Think about it - to load and then immediately save an entity should always be a no-op, and so can be skipped altogether.)
So the short answer to your question is "no". If you don't care for designing tables, you can let Hibernate adopt a reasonable default. If you do want to design your schema explicitly though, you can do this and then describe that exact schema to Hibernate.
As someone who's worked on java and hibernate in the enterprise for a long time, I have seen very few projects which use this capability. You'll see some build tools and other things do this, but for a real enterprise app, i've never seen this.
Most DBA's won't let the application user create tables. They rely on a privileged user to do those things, and the user that the app connects as would have r/w privs on the data but not the schema itself.
As a result, you write the SQL yourself, and you do the hibernate mappings to match. It doesn't mean your object design won't influence your SQL, but you should still always create your schema upfront.
No. You can use hibernate tools to generate the entities from existing database.
There are 2 ways you can go about in using Hibernate. If you have good DBA or database designer, then it is better to design the database and then map it into hibernate.
On the other hand if you don't have DBA and have good developer then let Hibernate generate Database for you.
The concept behind Hibernate is to map Database and the Objects. So it is called as ORM (Object-Relational Mapping) tool.
Read here for Object Relational Impedance.
This is the preferred way for a quick'n dirty prototype or a simple tutorial, but it's far from being the preferred way for any production application. I largely prefer designing the database independently, using scripts to generate the schema, tables, views, indexes, etc., and map the schema to entities.
As long as the mapping finds the tables and columns in the database, everything is fine.
As soon as you have data in your database and the schema must change, you'll have to write migration scripts anyway. You can't just drop everything and restart from scratch. The tutorials are written for developers starting with Hibernate and who must discover Hibernate as quick as possible, without dealing with complex SQL scripts.
What if you already have a DB schema ...
I don't know where you get that impression. Hibernate can use existing schema. It is quite flexible.
What if you have reference tables ...
Make the relationship LAZY, and it won't load automatically. Only changed object will be saved.
What if you want to do perf tuning ...
Just don't use the generated schema. It is just a starting point. You can customize as you need.
What if you want to add constraints or triggers to your tables? Indexes?
Some as above.
You can use hibernate with an existing database schema.
You can use various annotations to map to existing tables and columns, for example:
#Table(name = "dbschema.dbTable") - should be placed before your class file to map it
#Column(name = "colName") - to map a column
Just be sure that the hibernate is configured with this option:
hibernate.hbm2ddl.auto=update
If you set this to create it will create the schema, so do not do this in your case.
Use hibernate/jpa when appropiate. A common practice when designing apps is to extract the draft and alter it manually after needs (indices etc). However, it will be a pain for you if you change the db layout from hibernate way to do things. Lots of the beauty of JPA will be lost. For tasks which require heavy performance tuning and full control - just go for reguar jdbc.
Some answers:
A. It is possible to add an index annotation : see the table annotation.
B. If you have reference tables, you may choose to have lazy fetching or eager fetching (i.e - if your tables represent a person and a its books - whether to load a person without its book, or with its books)
C. Hibernate can be used to work on existing schema. The schema might not be trivial to work with , but as other have said, you should design db only according to business needs, and not according to framework conventions
D. I would like to encourage you also to read what hibernate does "under the hood" - it uses lots of usage of proxies, which hurts performance, you must understand well the scope of session , and the usages of 1st level and 2nd level cache .
E. Following what I wrote at section D - working with triggers will cause your DB to change "under the hood" when it comes to hibernate. Consider a case where updating a record will create (using a trigger) an entry in some archiving table , and let's say this table is also annotated via hibernate - your hibernate caching will not be aware of the change that happend outside of the application scope.
F. It is important to me to state that I'm not against Hibernate, but you should not use it for all solutions, this is a mistake I did in the past. I now work with Spring-JDBC and I'm quite pleased (for our application needs it will be hard to use Hibernate, and I assume we will consider this only in the case we need to support more than one DB flavor).

Why ormlite has its own annotations?

From what I see in ormlite it has implemented its annotations as well as JPA standard annotations. First of all, what was the reason of designing new set of annotations?
Secondly, how one can use standard annotation like #Entity, etc instead of ormlite specific annotations. Right now, I am getting not defined error for those entities. Do I need a jar file?
#DataNucleus is correct. ORMLite is not a fully compliant JPA implementation. There are many features of ORMLite that do not map well with the JPA annotations and it was easier to create my own set. JPA is also a very large specification and I didn't want a large percentage of the annotations to generate UnsupportedOperationException or jut fail quietly. Lastly, I was trying to write a ORM library with 0 dependencies.
All that said, I am interested in improving ORMLite's JPA compatibility so if you have any suggestions on how to make it better, please send them to the developers mailing list. I'd love to improve it.
Because it isn't a real JPA implementation, and just makes use of JPA annotations for convenience. Obviously, by using it, you lose the portability offered by JPA itself, but then it may have some advantages for very specific situations

Java Database API requiring no XML configuration

I am recently back in Javaland from Ruby and Activerecord and was wondering if there were any database solutions that do not require me to set up XML files to use them, and if possible supply any configuration in pure Java?
If you like ActiveRecords in Ruby, you might be interested in jOOQ (Java Object Oriented Querying, a database abstraction library that I wrote). jOOQ requires only little configuration for its source code generator. Your database schema is mapped 1:1 to Java classes, which can then be used in a fluent API very similar to SQL itself.
Also, jOOQ doesn't manage transactions, sessions, caches, etc like JPA or Hibernate might do. So there is no additional runtime configuration required.
http://www.jooq.org
You can configure Hibernate without using any XML via the Configuration class (it doesn't have to read XML documents). It's easier to avoid the mapping of .hbm.xml files if you're using annotated classes and AnnotationConfiguration instead.
See this for more details: http://docs.jboss.org/hibernate/core/3.3/reference/en/html/session-configuration.html#configuration-programmatic
There are many. Though hibernate is the most famous one. It has annotation for most of the configuration and that too is not required, if you use naming strategies.
http://www.hibernate.org/

how to assign different concurrency strategy to the same (persistence) entity?

I'm using JPA and I am using second-level cache for all the reference entities.
Everything's working well, I can get the entities from second-level cache is they were already been selected before.
Now, I have two applications, they both use the same database (so they both use the same table, values, etc).
1.The read-only application just read data from database, it doesn't modify the database at all. Therefore, I choose the "READ_ ONLY" concurrency strategy for the second-level cache, aiming at a better performance.
2.The read-write application read and write as well the data of database, it modify the database. Consequently, I have to choose the "READ_ WRITE" or "NONSTRICT_ READ_ WRITE" concurrency strategy for the second-level cache.
However, the concurrency strategy is assigned in the annotation of each entity class, so I cannot change it programatically. (I don't use class mapping files for JPA, so I can't use two mapping files, each for a different concurrency strategy for the same entity class.)
My Question is, is there a good way to change the concurrenty strategy of the second-level cache on the fly according to my 2 different applications?
I have not used Hibernate, but at least if you use JPA it is possible to override even a single annotation with a deployment descriptor file. You should also be able to override also any vendor specific property with the deployment descriptor.
Unfortunately I cannot give you an example but hope this helps you.
So Therefore, I think the current solution is to replace all the annotations of each entities with Hibernate mapping files, so that for different deployment (application as well), we could use different Hibernate mapping files.

JPA 1 is not good enough

Working in a medium size project during last 4 months - we
are using JPA and Spring - I'm quite sure that JPA is not
powerfull for projects that requires more than CRUD
screen... Query interface is poor, Hibernate doesn't
respect JPA spec all the time and lot of times I need to use
hibernate classes, annotations and config.
What do you guys think about JPA? Is it not good enough?
Well I think most of the time JPA is "good enough" but I miss the Criteria API a lot (only provided by Hibernate)
Hibernate has been a long time in the road. That's why it has many functions not avaiable in JPA yet. But with time JPA will catch up. Until then, use JPA and Hibernate specific settings where necessary. If you need to switch later, it'll be a lot easier.
Well I can't provide specific guidance without knowing more about your particular case. It seems like you're using Hibernate's JPA implementation. You might try other JPA implementations if there is something about Hibernate's you don't like. As far as the query interface, if JPA's queries aren't doing what you want, you always have the ability to get a plain old Connection and work with that. The genius of the framework is that -- at the very least -- you don't have to write all the CRUD code ever again. I would never claim JPA is perfect, but it's better than hand-writing SQL all the time to do trivial things.
We combine JPA 2.0, Hibernate Core, Hibernate Search and Hibernate Validator via our in-house wrapper framework. It does everything we throw at it :)
Combine that with Maven and we have a database built for us too! Add DBUnit into the mix and you've got everything you need.
Wickedly fast searches via Lucene, but using Hibernate Criteria/HQL queries are very cool. All this power behind a GWT suggest box is great.
My advice would be simply to use Hibernate. Hibernate coupled with JPA annotations + Hibernate annotations is pretty powerful. You can even configure an EntityManagerFactory to autodiscover Entities on the classpath but then call getSessionFactory() to leverage the native Hibernate APIs in your application. If you are using Spring it's very easy to do this with LocalContainerEntityManagerFactoryBean and HibernateJpaVendorAdapter.
Sure any ORM is better than hand-writting SQL for CRUD operations... the thing is: I'm think there is no reason to use JPA instead pure Hibernate because I'm mixing both a lot. If I'm not getting a hidden provider why use JPA anyway?
One of the nice things about using JPA vs Hibernate Annotations is the automatic configuration and discovery of persistent classes. Also, it depends on how much of the time you need to break from using the JPA API, if you are only doing it 10% of the time, it would still make switching providers a lot easier than if you were to use hibernate for 100% of your queries.

Categories

Resources