We have an application thats already running for a long time. Now we are migrating it to Spring and possibly using Hibernate or any other ORM.
But we caught up with a question. Is it not recommended / bad idea to use Hibernate for the already existing Database and model the object around Schema?
Most people advocate NOT using Hibernate and instead of go with some other ORMs like iBatis. But in our company, all are proponents of Hibernate.
Any experiences?
I would say that it's irresponsible to choose Hibernate, iBatis, or anything else without knowing your requirements.
If you don't have a solid object model, I'd say that Hibernate is a terrible choice.
If you use stored procedures as the interface to your database, I'd say that Hibernate is a terrible choice.
If you don't like the dynamic SQL that Hibernate generates for you, I'd say that Hibernate is a terrible choice.
Get it? Knee-jerk reactions like the ones from those Hibernate proponents aren't a good idea.
It might be that iBatis or Spring JDBC template is a better choice than Hibernate. You ought to become more informed about that decision and make it for your application rather than blindly listen to a mob.
You don't have to be all or none about it, either. It's possible to implement part of your solution with one technology and the rest in another.
I'd recommend making your persistence layer interface-based so you can swap implementations without affecting clients.
I recommend looking at SansORM (a NoORM object mapper). It is designed for SQL-first development, which fits well with retrofitting an existing schema.
Hibernate works well if you can model your database under your objects.
Vice versa, you are likely to get the database model as your your domain model. You need to evaluate how distant those two models are, otherwise you are going to map the database => ORM objects => your domain model. I would avoid that.
If I want to skip the ORM part, I find myself quite happy with JDBI which I prefer over Spring JDBC Template
As others have pointed out an ORM is only a good choice if your database is not far from an object model.
If that is the case then an option would be Hibernate through JPA for two resons:
Netbeans has a tool to generate JPA Entities from an existing database. This entities are not dependant on Netbeans so you could use a different IDE after the initial reverse engineering.
Spring Data JPA can avoid writing trivial queries and focus on the hard ones.
Related
We are going to write a service for which we are trying to evaluate technology stack. So as part of ORM we are thinking of using hibernate but from one of my colleague I came to know abt ebean. But we don't have any idea of ebean.
So my question is: Is there any disadvantage associated to hibernate, any salability or performance bottleneck? And what is the advantage ebean brings to the table?
What does Ebean bring to the table?
In short with Ebean it brings a full function ORM that is a lot easier to use and most importantly optimize (Well, it is easy but can also be done automatically via profiling).
A query language designed to optimise object graph construction via good support for Partial Objects and built in avoidance of N + 1
A "Sessionless" ORM ... architected to not have attach/detach semantics (So this makes it easier to use / fast to master).
Ebean now has SQL2011 History support and ElasticSearch integration. You could argue Hibernate has similar features.
Reference links:
ElasticSearch http://ebean-orm.github.io/docs/features/elasticsearch/
Automatic query tuning http://ebean-orm.github.io/docs/query/autotune
N + 1 http://ebean-orm.github.io/docs/query/nplus1
There are lot of issues with hibernate and basically any implementation of JPA in large and very scalable application. You should consider use another solution at all. Issues are well described in article Large Application Model issues and how model should look like in article Model for large applications.
As it is mentioned before, Ebean is sessionless ORM so you don't need to think about sessions. Hibernate has first level cache which is impossible to disable. It means that if you query item through ORM and then delete it directly with SQL, it stays in the cache. You can explicitly clear the cache to get the most updated results from database but unfortunately such behavior may bring errors like "detached entity passed to persist".
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).
I want to write Java code to work with a database, no matter which database is used. My problem is that it wouldn't be Object related. There are some insertions and queries that are but most of them aren't.
Right now we are using Postgresql and pure JDBC, but we may have to make it work with Oracle.
Can Hibernate (which I've never used) solve my problem or should I go for something else ?
I have created jOOQ precisely for that. jOOQ models SQL itself as a domain-specific language in Java. It embraces using standard and vendor-specific features, such as built-in functions, window functions, stored procedures, hierarchical queries, etc. Whenever possible, a vendor-specific functionality from one database is simulated for other databases. That way, most of jOOQ-generated SQL is compatible with any of its 13 supported databases.
See also this related question here:
ORM frameworks used for insert only / query only apps
I like #unludo's JPA answer but I thought I'd add some additional details.
I would recommend changing your code to use persistance interface that you define.
public interface DataPersister {
public void saveFoo(Foo foo);
public void findFooById(int id);
...
}
Your first implementation of the interface would then be using JDBC/Postgresql. If you want to use JPA under the covers then fine. Or if you want to switch to some no-SQL database or even flat files then fine.
Once you have the separation in your own code between the usage of the data and the persistence implementation, then it is significantly easier to switch to a different persister. You can use a cheap database like H2 for testing and switch to Postgresql in production while migrating to a new database in the near future.
Hope this helps.
Problems with Hibernate is that you need to modelize your relational database like object model. Sometimes this make difficult working with existing database. So it depends your relational database.
Other framework (not JPA) is Ibatis. Try to look at this framework.
The standard for Java is JPA and it is very powerful. Hibernate is the industry standard as a JPA provider.
JPA helps you write a clean persistence layer. You may write queries which are sure not to break, because they are validated at compilation time. I like to use spring for this, it's so easy to unit test. But CDI now provides the same I believe.
It's also easy to write test classes. As a coworker once teached me, the model is the most important thing you have. You don't want it to break or you have problems.
With JPA you may also generate the schema from the entities, for any database you want to use. From experience, it's also very good.
JPA helps you put good practices at work. That's a lot of value.
Regarding #hvgotcodes answer, yes you have to be careful with the cost but you may also mix jdbc and jpa. That's what Dao's are for.
The problem with writing your own sql is you need to manually optimize it for your RDBMS. Some RDBMS support varying sql constructs.
So you need to balance that against the overhead of switching to an ORM based solution. Or, make sure you sql is 100% standard so you don't use any constructs that work in one RDBMS solution and not in another.
In your particular situation, it's probably going to be easier to just fix your sql than rework your entire persistence layer to use ORM. Sometimes the best tool is the one you know. If your current application doesn't have a concise model layer, switching to ORM is going to require a lot of work. You could of course use hibernate and just use strait sql queries, but what's the point if you are not going to model your data.
Hopefully, all your persistence concerns are in one DAO layer, with lots of integration tests, so you can quickly identify what breaks when you switch RDBMS. If you don't have integration tests that focus on persistence, then now is the time to start writing them.
I am starting out writing java code and interacting with databases for my "nextbigthing" project. Can someone direct me towards the best way to deal with adding/updating tables/records to databases? Here is my problem. There is too much repitition when it comes to DB code in java. I have to create the tables first (I use mysql). I then create classes in Java for each table. Then I create a AddRow, DeleteRow, UpdateRow and Search* depending on my need. For every table, every need creating this huge ass sql statement and the classes all seems like a huge waste of my time. There has to be a better, easier, more efficient way of doing things. Is there something out there that I do not know that will let me just tell Java what the table is and it automatically generate the queries and execute them for me? Its simple SQL that can be auto generated if it knows the column names and DB table inter dependencies. Seems like a very reasonable thing to have.
Check out Hibernate - a standard Java ORM solution.
User hibernate for mapping your classes to Database.
Set its hbm2ddl.auto to update to avoid writing DDL yourself. But note that this is not the most optimal way to take it to production.
Consider using Hibernate:
https://www.hibernate.org/
It can create java classes with regular CRUD methods from existing database schema.
Of course there is a much better way !
You really want to learn some bits of Java EE, and in particular JPA for database access.
For a complete crash course on Java EE, check out the Sun the Java EE 5 tutorial.
http://java.sun.com/javaee/5/docs/tutorial/doc/
Part 4 - Enterprise Beans
Part 5 - Persistence (JPA)
Then you want to try Hibernate (for instance) which has an implementation of JPA.
This is for Java 5 or later.
If you are still in Java 2, you might want to try Hibernate or iBatis.
You can also try iBatis, if you want control over SQL. Else JPA is good.
You can also try using Seam Framework. It has good reverse-engineering tools.
There is also torque (http://db.apache.org/torque/) which I personally prefer because it's simpler, and does exactly what I need.
With torque I can define a database with mysql(Well I use Postgresql, but Mysql is supported too) and Torque can then query the database and then generate java classes for each table in the database. With Torque you can then query the database and get back Java objects of the correct type.
It supports where clauses (Either with a Criteria object or you can write the sql yourself) and joins.
It also support foreign keys, so if you got a User table and a House table, where a user can own 0 or more houses, there will be a getHouses() method on the user object which will give you the list of House objects the user own.
To get a first look at the kind of code you can write, take a look at
http://db.apache.org/torque/releases/torque-3.3/tutorial/step5.html which contains examples which show how to load/save/query data with torque. (All the classes used in this example are auto-generated based on the database definition).
Or, if Hibernate is too much, try Spring JDBC. It eliminates a lot of boilerplate code for you.
iBatis is another good choice, intermediate between Spring JDBC and Hibernate.
It's just a matter of using the right tools. Use an IDE with tools to autogenerate the one and other.
If you're using Eclipse for Java EE and decide to head to JPA, then I can recommend to take benefit of the builtin Dali plugin. There's a nice PDF tutorial out at Eclipse.org.
If you're using Eclipse for Java EE and decide to head to "good ol" Hibernate, then I can recommend to take benefit of the Hibernatetools plugin. There's good reference guide out at Hibernate.org.
Both tools are capable of reverse-engineering from a SQL table to fullworthy Javabeans/entities and/or mapping files. It really takes most of boilerplate pains away. The DAO pattern is slightly superflous when grabbing JPA. In case of Hibernate you can consider to use a Generic DAO.
Stepwise, what would be a good way of integrating Spring and Hibernate into an existing JSF application that doesn't use ORM?
1) You would need to design the domain model first and then map it to the database. You could use hibernate reverse engineering tools for this.
2) Other option is to manually map your current objects(DTO) to database tables. Since you use JSF, I assume you'd be having some objects currently.
3) Design the Service Layer around the objects.
Spring -
1) You could use Spring to provide hibernate template, provide common services through bean.
2) You can manage the transaction in Spring.
I would recommend first to write tests to check your code of your previous persistent mechanism. This code could be used to check the correct behavior of our ORM integration.
As mentioned by other answers, having a clear DAO defined by interface helps to bound the DAO code.
Map the domain objects first, then write your DAO, then your service objects (which take care of large atomic suite of operations by enclosing its in a transaction).
Use persistence mechanism which is vendor-agnostic (JPA is the good and only choice).
Start with one kind of database and stick with it during all the migration. In very uncommon cases, you can meet subtle differences between databases which could be very hard to solve, especially if you're a beginner.
When starting, use automatic generation of database (generateDdl for hibernate subsystem) and then, when things starts to be stabilized, force #Table and #Column annotations to fix name of each column. At this point, write a SQL script which generate the database with empty tables. The reason if to fix your architecture and be sure you're controlling the database organization.
If you're serious about ORM, please look at Java Persistence With Hibernate of Christian Bauer (Manning publications), this is "the bible" about hibernate and JPA on Java.
If you've written Spring properly, you should have DAO/repository interfaces. If that's the case, all you have to do is write a new implementation of that interface using Hibernate, test it, and change your Spring configuration to inject it.
ORM presumes that you have an object model in place to map to a relational schema. If you don't, I would advise against using ORM. Better to use iBatis or JDBC in that case.