I need to write pretty straight forward DB code and I'm considering MyBatis over plain JDBC (I believe full ORM is an overkill).
Considering that in both MyBatis and plain JDBC you find yourself:
Hand writing SQL statements.
Manually wiring DB rows to JAVA DTO objects (either via code or config).
The MyBatis benefits over JDBC I know of are:
Out-of-the-box table/query caching.
Dynamic SQL.
SQL is stored outside of the code.
Templating SQL for easier DB vendor Independence.
What other MyBatis-Over-JDBC benefits are there to consider?
I dont know you'll count this one as advantage or not but there's MyBatisGenerator, And It generates all basic needed Queries plus some Advanced Queries too and DTO objects automatically based on a single XML file.
Plus it has Eclipse Plugin For the same.
Most of the times you do not need to map explicity columns to pojos so bullet number 2 is a difference rather than a similarity.
The main difference IMHO is the API that is much simpler in MyBatis than in JDBC. If used with Spring or Guice you will not need to call MyBatis API in your code at all.
Mappers and injection helps the testing a lot because mappers are plain interfaces so easy to mock.
About : 'Manually wiring DB rows to JAVA DTO objects (either via code or config).'
This is not totally true, if you use conventions you can get an automatic mapping from DB tables to Java classes, example you have a CUSTOMER table that has fields like ID, COMPANY_NAME, PHONE_NUMBER, and a Java class Customer with properties id, companyName and phoneNumber, MyBatis is smart enough to figurate the DB to camel case convention and no mapping is required from you. Great!
MyBatis require less code and is cleaner than plain JDBC coding
MyBatis supports named parameters, JDBC supports only placeholders? (ugg!)
With a single line you can change from Reuse Prepared Statement Mode to Bath Mode, in plain JDBC it will take you a rewrite of your code.
Related
After making some search on the web, I think that when using Spring Data JPA Named Queries, we need some extra implementation or definitions comparing to the derived or dynamic queries in Spring Data JPA. In this scene, I am really wondering that do we really need to use Spring Data JPA Named Queries?
Spring Data derived queries are intended (and useful) only for very simple queries. Those queries where you look at the name that you would naturally give such a method and would immediately know how to implement it in SQL or JPQL.
As soon as a query gets a little more complex we shouldn't use derived queries anymore, and often we can't even if we wanted to. For example query derivation doesn't have a way to control the precedence between AND and OR.
For all other queries we need to explicitly code the query one way or the others. And if you don't want your queries mixed with your repository, a named query is a very viable alternative.
We have a (possibly large) custom data structure implemented in Java (8+). It has a simple and optimal API for querying pieces of data. The logical structure is roughly similar to an RDMS (it has e. g. relations, columns, primary keys, and foreign keys), but there is no SQL driver.
The main goal is to access the data via ORM (mapping logical entities to JPA annotated beans). It would be nice if we could use JPQL. Hibernate is preferred but other alternatives are welcome too.
What is the simplest way to achieve this? Which are the key parts of such an implementation?
(P. S. Directly implementing SessionImplementor, EntityManagerImplementor etc. seems to be too complicated.)
You have two possibilities.
Implement a JDBC compliant driver for your system, so you can use a JPA implementation such as Hibernate "directly" (although you may need to create a custom dialect for your system).
Program directly against the JPA specification like ObjectDB does, which bypasses the need to go through SQL and JPA implementations completely.
The latter one is probably easier, but you'd still need to implement the full JPA API. If it's a custom in-house-only system, there's very little sense in doing either one.
One idea I thought up just now, that I feel may work is this:
Use an existing database implementation like H2 and use the JPA integration with that. H2 already has a JPA integration libraries, so it should be easy.
In this database, create a Java stored procedure or function and call it from your current application through JPA. See this H2 documentation on how to create a Java stored procedure or function. (You may want to explore the section "Using a Function as a Table" also.)
Define a protocol for the service methods and encapsulate it in a model class. An instance of this model class may be passed to the function/SP and responses retrieved.
Caveat: I have never done this myself but I think it will work.
Edit: Here is a diagram representing the thought. Though the diagram show H2 separately, it will most probably be in the same JVM as "Your Java/JEE application". However, since it is not necessary to use H2, I have shown it as as separate entity.
I am working in a project which uses JPA ORM and framework provides two kinds of method to create queries.
entityManager.createQuery(query1);
entityManager.createNativeQuery(query2);
I understand the kinds of query string is to be passed to use them, but I don't know exactly why do we need to create native query? Probably we don't want to use ORM capabilities there?
You do not need to create a native query unless you want to. JPQL eventually is translated into SQL by the framework but the framework lets you call the native query also. Why would want to do that:
Low level access, which means that you can optimize and handle the mapping by yourself; with SQL you actually access the database table while with JPQL you access the entity objects;
Maybe you do not want to learn JPQL if you already know SQL
You already have the queries written in SQL, and do not have resources/time to port them to JPQL
createQuery uses JPAs own query language, you select from Class names instead of table names. This is not SQL, it is just similar, and is later transformed to real SQL. Mapping to java classes will be done automatically and actual class instances will be returned as result.
createNativeQuery uses real SQL, and will not be able to use JPA features. This method is used in general if you need to do something really odd that is not supported by JPA. A list of Object[] will be returned, and mapping to java objects will have to be done manually. In other words, its just like working with a DB before JPA came to, just slightly more convenient since connection handling is done automatically.
I have used it for optimization purposes. Using Native queries means that the ORM mapping is not in place, and instead of JPQL, you use the DB's native syntax. So, as #RasmusFranke also pointed out, if you need something that is not supported by JPA (like when you want to use DB vendor specific extensions, which is conceptually a bad idea, since JPA is all about being DB agnostic, but happens nevertheless. I know...)
The other effect of this is that by using native queries, only the supplied query is run. No eager fetching of other entities, or other unwanted stuff. This way, if you deal with huge amounts of objects, you can save some heap space.
I haven't worked with hibernate. I have little bit of experience in java. I was going through source of a beast of an java application created by Oracle(Retail Price Management). I was expecting a lot of sql code embedded in there as the application makes heavy use of database. But to my surprise, NO embedded SQL code! so far. I found that it was using what is called as "Hibernate" from the lot of .hbm.xml files. Is it a trademark for java programs using hibernate or maybe I haven't seen the complete codebase?. Could someone enlighten me how this is possible?. Thanks.
Hibernate, as all ORM tools, indeed lessens or eliminates the need to use raw SQL in Java code, due to the following:
many associations between various entities are recorded in the Hibernate mapping, so these are fetched automatically by Hibernate - i.e. if you have an aggregation relationshiop between two classes on the Java side, this may be mapped as a foreign key relationship in the DB, and Hibernate, whenever an instance of class A is loaded, can automatically load the associated instances of class B too,
many queries can be done in Hibernate's own HQL query language, or using its Criteria API.
Under the hood Hibernate does generate SQL to communicate with the DB, but this is not visible on the Java side. It can be seen in the logs though, if it is enabled.
Due to this, programs using Hibernate very rarely need to use JDBC or SQL directly. The exceptions are typically ralted to "tricky" legacy DB schemas which can't be fully handled by Hibernate.
Because that's the whole purpose of using Hibernate or any other object-relational mapping framework.
Hibernate solves object-relational impedance mismatch problems by replacing direct persistence-related database accesses with high-level object handling functions.
Hibernate generates SQL for all its standard database operations. It understands different SQL dialects, and the mapping files (.hbm.xml) tell it about the database structure so it knows how to construct its queries. There is a showSql setting you can turn on if you want to see it outputting its generated SQL as it runs.
Hibernate is an Object-Relational Mapper (ORM). ORMs are used to hide the ugly details of SQL incompatibility[sic] between databases from your program -- you define your tables and map them to an object hierarchy (the .hbm.xml files) and then Hibernate does the rest. Thus most programs that use Hibernate won't see a single phrase of SQL, unless there's a specific reason to execute a complicated query.
Hibernate is a tool, or technology that takes care of the interaction between the database and application for you. You have to tell the structure of the application and the database to it, this is what is in the .hbm.xml files.
The SQL is generated by Hibernate at runtime (kind of)
Say you have an Fruit class, and objects of this is persisted into a T_FRUIT table.
You say this to hibernate, via the .hbm.xml files. That there is a table T_FRUIT, this table is represented by the Fruit class, and which fields in the Fruit class correspond to which columns in th T_FRUIT table.
And then it knows whenever you are trying to save a fruit, it should insert/update to the T_FRUIT table.
When you want to create an Apple, you create an object of fruit corresponding to apple and save "save this fruit".
Hibernate takes care of persisting it.
You can have relationships defined between tables, and Hibernate is intelligent enough to persist in multiple tables.
When you fetch a fruit, hibernate fetches the details of the fruit and its children also(data from referencing tables). And you can say whether you want fetch all the children
at once, or as and when required.
And so on. Aim is to make your life easier, and code maintainable, easy to read, portable,...
With this info, let me redirect you.
I want to copy all data of a specific table from database1 to database2. In my system i have access via hibernate to the domain object from database1, i don't have to transform the data-structure. i have only a native jdbc connection to database2.
whats the best solution to make this groovy script very generally to support all kinds of domain objects i have? so this script only gets my domain object and the connection string to database and inserts all the data?
I faced a similar issue where I needed the ability to export every hibernate entity to an SQL script, in other words if you had a Person object with two properties (username, password) you should be able to generate the SQL insert statement of that Object.
Person.username = x
Person.password = y
then the process would extract from that object the equivalent SQL insert and create something like:
insert into person (username, password) values ('x', 'y');
However my solution was based on the fact that mappings are done using hibernate annotations and not XML configuration, if this is your case you could achieve the same with 1 or 2 working days, just read the annotations. noting that you will have to do an extra step which is executing the resulted SQL inserts on the other DB.
FYI: this method toSQL() was added in a superclass (AbstractHibernateEntity) that every hibernate entity extended, so calling it was the easiest thing to do.
This was the complicated solution and most general one, however if you only need to copy one table from DB to another I would suggest to simple go with a simple JDBC call and avoid complicating your life ;-)
Regards.
Maybe the easiest would be to stick on the technology level that is common to both databases.
If they exist, you could use database-specific commands, that would be really fast.
If not, you could use simple jdbc on both. You could that in a generic way :-)