I'm using hibernate to auto generate IDs for table, but i need to manually insert some rows (about 10k, just once) related to another table. I'm using Oracle DB. How can I do that? How does hibernate generete values? It is possible to use it?
#Id
#GeneratedValue
private Long id;
Of course that's possible, we're doing that all the time. Whether and how depends on the id generation strategy you use and how your database is set up.
We're using a (customized) table generator that generates positive ids so whenever we need to manually insert elements we use negative ids. That way those ids don't interfere with Hibernate's id generation and we are able to immediately identify manually inserted rows.
If you don't like negative ids you could use a different generation strateg, e.g.
a sequence on the id column that is used by Hibernate as well as manual inserts
a high-low table generator (that's what we're using) with the initial low value set to some higher value and thus essentially reserving the lower positive values for manual inserts)
an "assigned" id generator, i.e. your application defines the id (e.g. an employee's employee-id) and thus you'd know which ids can be added manually
See, #GeneratedValue will only work if You call hibernate API.
To use Autoincrement values, we don't need hibernate #GeneratedValue feature.
You can enable the auto to generate from Database itself. mark a column auto generate.
Refer to :
https://chartio.com/resources/tutorials/how-to-define-an-auto-increment-primary-key-in-oracle/
While inserting don't include the column name and values in your bulk insert Query for column marked as Auto increment.
Related
I am running a Spring Boot application were I use JPA. I am using Postgresql as DB.
I get some data from an api where there is no Id for each row. So I have to use #Id and #GeneratedValue. But my problem is that when I request this data again I might get the exact same rows or some of them again. I can make a composite key that consist of 3 of the columns but then how do I do with the Id that I would like to keep (autogenerated value). If I understand correct, I canĀ“t use composite primary key and a generate #Id at the same time?
An extension of this question is that sometimes a column in each row are updated. Then I would like to update only this column and not create a new row in the DB.
I could make a modified query that checks if the three column (composite key) already exist then I update that row if any change or if row is missing just save. Or is their any other option that I have missed so I do not have to write any query myself?
You are correct, you have to decide if you want to use a single autogenerated Id or a composite key, you can't have both at the same time. And if your API can't handle a single Id you are probably better of doing as you are thinking in your extended question; creating a composite key and when updating rows check for a row that match your three values.
I have an entity with autogenerated id value and I am using MySQL DB
entity definition
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
table column definition in MYSQL
id bigint not null auto_increment
And I had to copy data to the table from external and I want to continue generating entities and save them, But seems in JPA side it generates id values which already have in the DB (which are copied from externally)
Is there any way to tell JPA, generate next id from whatever in MySQL table?
And when I use both autogenerating from JPA side and auto-increment column in DB side, how internally it works, which side gets the priority?
GenerationType.IDENTITY is not the best way of use, due to a lack of performance it involves. The way it work is that it relies on an auto-incremented database column and lets the database generate a new value with each insert operation, so there would be a sequence in DB which generates the values.
But here comes the problem: if you use Hibernate, it requires a primary key value for each managed entity, so it has to perform the insert statement immediately to be able to work. This avoid the use of JDBC batching optimization.
And when I use both autogenerating from JPA side and auto-increment
column in DB side, how internally it works, which side gets the
priority?
The #GeneratedValue(strategy=GenerationType.TABLE) indicates the provider to use a table to get the IDs when inserting new entities into the database.
When using Hibernate as provider, you will find a table called hibernate_sequences with two columns: entity name and max identity already assigned to this entity.
Hope this helps.
I am developing an application that support multiple databases and hibernate fulfilling that requirement.
Now the issue is in primary auto generate key. some databases support auto increment and some required sequence for increment the identity. to solve this issue the use the following strategy
strategy = GenerationType.TABLE (javax.persistence)
This is fulfilling my requirement.
in this post, a user comment that
its always better to use increment or sequence instead of table generation if you need the ids to be in sequence
If I use the auto increment or sequence, it means it required some changes # annotation level, when I move one database to another (extra burden)
update me , it is really better to use increment or sequence instead of table generation or it is just a statement?
Auto increment drawbacks: You don't know the id until the transaction has committed (which can be a problem in JPA, since some EntityManager operations rely on Id's). Not all databases support auto increment fields.
Sequence drawbacks: Not all databases have sequences.
Table drawbacks: Id's are not necessarily consecutive.
Since it is very unlikely that you run out of Id's, using Table generation remains a good option. You can even tweak the id allocation size in order to use more consecutive id's (default size is 50):
#TableGenerator(name="myGenerator", allocationSize=1)
However, this will result in at least two queries to the id allocation table for each insert: one to step the value of the latest id, and one to retrieve it.
Is it OK to truncate tables while at the same time using Hibernate to insert data?
We parse a big XML file with many relationships into Hibernate POJO's and persist to the DB.
We are now planning on purging existing data at certain points in time by truncating the tables. Is this OK?
It seems to work fine. We don't use Hibernate's second level cache. One thing I did notice, which is fine, is that when inserting we generate primary keys using Hibernate's #GeneratedValue where Hibernate just uses a key value one greater than the highest value in the table - and even though we are truncating the tables, Hibernate remembers the prior value and uses prior value + 1 as opposed to starting over at 1. This is fine, just unexpected.
Note that the reason we do truncate as opposed to calling delete() on the Hibernate POJO's is for speed. We have gazillions of rows of data, and truncate is just so much faster.
We are now planning on purging existing data at certain points in time by truncating the tables. Is this OK?
If you're not using the second level cache and if you didn't load Entities from the table you're going to truncate in the Session, the following should work (assuming it doesn't break integrity constraints):
Session s = sf.openSession();
PreparedStatement ps = s.connection().prepareStatement("TRUNCATE TABLE XXX");
ps.executeUpdate();
And you should be able to persist entities after that, either in the same transaction or another one.
Of course, such a TRUNCATE won't generate any Hibernate event or trigger any callback, if this matters.
(...) when inserting we generate primary keys using Hibernate's #GeneratedValue (...)
If you are using the default strategy for #GeneratedValue (i.e. AUTO), then it should default to a sequence with Oracle and a sequence won't be reseted if you truncate a table or delete records.
We truncate tables like jdbcTemplate.execute("TRUNCATE TABLE abc")
This should be equivalent (you'll end-up using the same underlying JDBC connection than Hibernate).
What sequence would Hibernate use for the inserts?
AFAIK, Hibernate generates a default "hibernate_sequence" sequence for you if you don't declare your own.
I thought it was just doing a max(field) + 1 on the table?
I don't think so and the fact that Hibernate doesn't start over from 1 after the TRUNCATE seems to confirm that it doesn't. I suggest to activate SQL logging to see the exact statements performed against your database on INSERT.
The generator we specify for #GeneratedValue is just a "dummy" generator (doesn't correspond to any sequence that we've created).
I'm not 100% sure but if you didn't declare any #SequenceGenerator (or #TableGenerator), I don't think that specifying a generator changes something.
Depends on your application. If deleting rows in the database is okey, then truncate is okey, too.
As far as you don't have any Pre- or PostRemove listeners on your entities, there should be no problems.
On the other hand... is it possible that there are still entities loaded in an EntityManager at truncate time, or is this a writeonly table (like a logging table). In this case you won't have any problem at all.
How can I generate insert statements like insert into table (sequence.nextval, 'b0) using hibernate?
Hibernate currently selects the sequence.nextval value and only then it uses the value to insert the entry in the table.
Note: I'm not very fond of custom id generators.
Hibernate selects sequence.nextval because it has to return that value back to you (e.g. set ID on your entity). Unless you're doing something very esoteric I strongly doubt this has a big impact on performance (e.g. it's nothing compared to the actual insert). That said, you can look at Hibernate's sequence hi-lo generator - it would only access the sequence once in a while instead of every insert.
If you're using Oracle 10 client or above, check out sequence-identity in the most recent Hibernate versions to do what you're asking for.