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 :-)
Related
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 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.
I am working on a stand-alone Java project (not Java EE), I am currently learning JDBC, I am creating a database where it contains Employee information, such as Personal information, Contact Information, Employee Information and Tax information, all of these are classes with references with each other and they have setters and getters, I am wondering how would I insert their data value in the database/tables I created in the database? in short I have Employee an employee object with like this
Employee(PersonalInformation information,ContactInformation cInformation)
Something like that, how would I add their data in the tables I made in the database?
how would I add their data in the tables I made in the database?
By using JDBC to send INSERT statements to the database, one for each object in your object graph (assuming you have one table per class).
And yes, that's a lot of boring, repetitive code to write, which is likely to contain errors and quite a burden to maintain.
Which is why people have written Object-Relational mappers like Hibernate, and there's a Java standard for that called JPA. Which is part of Java EE, but that doesn't mean you have to run a Java EE server to use it.
Update: OK, so you cannot use an ORM, probably because you're supposed to understand how JDBC works first, which makes sense because ORMs are based on JDBC and sometimes you have to go down to that level when there is a problem.
When using JDBC directly, you typically create a DAO (data ccess object) layer that is responsible for writing and reading objects to/from the database. For dealing with a nested object, one DAO can call the other.
And no, the DAOs are not called in the setters and getters. There called by the part of your application that reacts to user input. E.g. when the user opens the application and the start screen shows a list of employees, you'd call an EmployeeDAO.findAll() method, and when the user makes changes to an employee and clicks on "save", you'd call the EmployeeDAO.save() method.
I recommend you to look at Spring's JdbcTemplate (http://www.java2s.com/Code/Java/Spring/ControlParameterTypeInJdbcTemplateQuery.htm)
Its looks like this:
SingleConnectionDataSource ds = new SingleConnectionDataSource();
ds.setDriverClassName("org.hsqldb.jdbcDriver");
ds.setUrl("jdbc:hsqldb:data/tutorial");
ds.setUsername("sa");
ds.setPassword("");
JdbcTemplate jt = new JdbcTemplate(ds);
jt.execute("insert into employee (id, name) values (?, ?)", 1, "Tom");
Use one jdbcTemplate per DAO class instance.
This may help you
Pass all the required values to the respective objects.
get all their values and frame a query using those values like
Employee em = new Employee(perinfo, continfo);
String emp_per_info = em.getSomeInfo(); // it this returns a string
...
//so on
query="insert into table_name values(variables go here);"
let me know if it didn't work
What you are trying to do is called "Object to Relational Mapping". You have the java Objects which make up your object domain and there is the DB Table which make up the relational model. You have relate them. Save the data and query to get them back.
You have two approaches to write a kind of your own limited framework or use an existing framework. Existing frameworks include :
Hibernate
iBatis
and so on.
To do one on your own, simplest way to do would be writing simple result set to object mappers and creating insert strings.
I would suggest you study some ORM docs to know more.
Regards
As my understanding on setting hibernate, I need to create
table meta data file (person.hbm.xml), include all the fields mapping
java object (person.java)
If we use stored procedures for all transaction, do we still need the above configuration?
It seems hibernate and stored procedures will overlap,
We set up the stored procedure because we don't want the to developer know all the field in db. If tables change, then we need update above files.
Does it mean if we purely use stored procedure, we should just go for JDBC?
If hibernate, we should stay in HQL?
You can use native SQL and map the result to object:
sess.createSQLQuery("SELECT * FROM CATS").addEntity(Cat.class);
The JDBC syntax to invoke store procedure is like following:
CallableStatement proc =
connection.prepareCall("{ call set_death_age(?, ?) }");
proc.setString(1, poetName);
proc.setInt(2, age);
So maybe, you can invoke stored procedure and map them to object:
sess.createSQLQuery("{ call my_stored_proc }").addEntity(Cat.class);
Note also that updates made through stored procedures will escape hibernate, which means that you will need to evict objects from the 1st level and 2nd level cache yourself.
So as you see, hibernate and stored procedure don't really fit naturally together.
we set up the stored procedure because
we don't want the to developer know
all the field in db. if table change,
then we need update above files.
If you're concerned about security, either use:
database views
Oracle column priviledges
provide mapping files and forbid their modification by developpers
Using Hibenate with Stored Procedures is a certain overlap. As you for example need to write astored procedure for INSERT, UPDATE, DELETE and SELECT, Hibernate provides an easiest way to interract with with relational database objects by mappings them into metadata files like you mentioned person.hbm.xml.
Yes, the use of stored procedure wil require you to write these metadata files anyway. A stored procedure will not replace the Hibernate mappings. Those mapping only tell Hibernate how to persist your object-oriented model to the database. A great thing about Hibernate is that you may even, if needed, generate you database model from your JAVA code through the schema generation tool.
As for the stored procedures, one recommended way is to configure your stored procedures as named queries from within the configuration file. This, however, makes you miss the better potential, in my opinion, of Hibernate.
Does this answer your question? Do you need further explanations?
It is possible to use native-sql and to use stored procedure for querying (with limiations/rules). But, as written in the documentation:
Stored procedures currently only return scalars and entities. <return-join> and <load-collection> are not supported.
So if you want to work with non-managed entities (i.e. not scalars in an Object[]), you'll have to apply a ResultTransformer in the code.
But at the end, if you want to hide the database to developers, if you don't want to map objects to tables, if you don't want to work with associations, if you don't want to use HQL, if you don't want to use an OO approach, then I really wonder why you want to use Hibernate. You'd better use raw JDBC (with Spring for example) or maybe a data-mapper like iBATIS.
You can map the database fields in a result set to an object in hibernate: the documentation explains how.
The idea of Hibernate is to fill the object-relational gap. With the stored procedures (which I can't guess since you haven't told anything about them) you can't get objects from database. You still get rows.
Hiding the database columns from developers sounds like a bad practice to me. Hiding them from the application is perhaps what you want, and you achieve that with the metadata file.
I am using Spring JdbcTemplate with the DAO pattern to access a database. Instead of creating the database tables manually, I am looking for a way to generate the tables in the DAO layer.
I understand that I can use the JdbcTemplate to execute statements, I am only looking for the right place to do it.
Is there a best practice for that?
You can use the execute(String) method:
public void execute(String sql) throws DataAccessException
Issue a single SQL execute, typically a DDL statement.
Specified by: execute in interface JdbcOperations
Parameters: sql - static SQL to execute
Throws: DataAccessException - if there is any problem
However as beny23 mentions I would be suspicious of an actual need to do this programatically in a live application.
Slightly offtopic:
Is it absolutely necessary that you need to execute the DDL commands from within your code? In fact I do think it is a good idea to have separation between db admin and db usage. Our Oracle database security setup here is actually set up so that the tables are set up using a different database user (DB_OWNER), than the one running the SELECTs, INSERTs, DELETEs are run by DB_USER.
This prevents accidentially deleting tables or modifying the schema and also allows the DB_USER to be setup such that only the privileges that are absolutely necessary are granted, which adds a layer of security.
I suppose it depends on the nature of your service/application, but think about the benefit of creating the tables inside the code (and whether a possible bug in the DDL code could accidentially destroy production data).
Use .update() methods available in the (Simple)JdbcOperations, the number they return is the number of affected rows. They're supposed to be specifically used for both INSERT and UPDATE statements.