Is there a way to reduce unnecessary/empty fields in SQL inserts and SQL updates?
For example, I have a single hibernate entity class mapped to a table that has 10 columns. The populating of data is actually done in two phases. When the user submit a request, I will insert the request information into the table with the hibernate entity, but populating only 7 fields. After some processing (wait for other users interaction for example), I will populate the remaining 3 fields (with the id given from the previous insert).
If I stick with a single entity class, for the second update, the steps I do is as follows:
1) Load the entity identified by id
2) Save the entity, which generates sql that seems to be sending all the fields over.
Alternatively, I created two entity class, and point to the same table and save them seperately.
Does anyone have a better suggestion?
Kent
Edit:
What I really like to achieve is something to the following effect:
insert t(id,field1,field2) (?,?,?)
update t set field3=? field4=? where id=?
The best I could achieve now with dynamicUpdate=true is
insert t(id,field1,field2) (?,?,?)
select field1,field2,field3,field4 from t where id=?
update t set field3=? field4=? where id=?
Is there a way to eliminate that select statement? The original persisted object is not stored anywhere in memory after the insert.
An additional note. The entity class is annotated with Hibernate validation. I am currently trying out to achieve the above desired effect, so I commented them out. But when I turn them back on, I get validation errors due to #NotNull and #NotEmpty.
If you add the annotation:
#org.hibernate.annotations.Entity(dynamicUpdate = true)
to the top of your entity only the fields that have changed will be sent to the database.
Related
What should I do to represent this table in Spring Data Java Persistence Application Programming Interface (JPA)?
The table is specific because it has no primary key and every column in the table can have nulls, and it is read only.
In entity class I can not simply annotate a single column with #id because there is no column with unique values.
I can, of course, create composite virtual primary key in entity class by annotating every column with #id, and that works, but only if there are no nulls in the row. So if I select row(s) with all columns not null then this works. But if one or more columns contains null, Spring is not able to extract that row from table, and instead returns simply null for entire row rather than returning an entity object with only the appropriate field null.
Please do not say "just add id column to the table" because table is read only for us. My company was negotiating for more then a month just to get the read rights to the table! I can not simply add id field in the table.
What else can I do in this case? Other than manually executing a query and extracting the result. Can I somehow fake the id field to make Spring happy? id field is not important for our application, we will never filter the table by id, so it can be whatever makes Spring happy as far as I am concerned.
I don't think there is a way to do that.
Just get a NamedParameterJdbcTemplate injected and query away.
A central premise of JPA is that you can load data from a bunch of tables, edit the resulting object structure and JPA will take note and mirror the changes to the data in the database.
If you don't have anything to use as an id you wouldn't know which row to update. So this whole approach kinda fails to work.
You can use #EmeddedId with an ID you create. Set the ID field either #Transient or static so it won't affect persistence.
In the below example I use the UUID static method .randomUUID() to generate the ID.
So put this into your #Entity and you will get every row regardless of nulls. Inserts will work just fine too (depending on how you disambiguate your rows).
#EmbeddedId
static UUID uuid = UUID.randomUUID();
We are using hibernate 3 to insert some values, just plain bean objects. However, this specific process does not have a SELECT privilege on the same table that it does the INSERT. So, what bothers us, is the SELECT statement that is done right after the INSERT. I am just guessing it is done to retrieve the generated ID and may be some other stuff. But, what if I in my code don't need that? Can I somehow state to hibernate 'just insert this entity and do not re-select the generated ID' ? The main point is that this table is only allowed to be inserted into by this user, but its not allowed for SELECT.
Thank you.
I have Flat entity. I need to update a lot of rows in relevant table, but I don't know ids of updated rows. I know that there are some ways of doing it:
Select all flats by unique parameter (not #Id), update persisted entity and then save it.
I don't want use it, because I have to get from database a lot of entities, when I really don't need it.
Create update method in JpaRepository with #Modifying and #Query annotations like Update Flat f SET ..fields... WHERE f.unique_field=?1 But in my case Flat entity contains 20+ fields, so my method will have 20+ parameters that is not very beatifull.
Is there another way to update entities without knowing id and select queries?
I hope that there is something that looks like 2nd way but with entity as parameter of update instead of plenty fields.
For example
#Modifying
#Query("Update Flat f where f.unique_field=?1)
Flat updateFlatByUniqueField(Flat flat, Long uniqueField)
Hi I have a case where I need to do this select statement
SELECT c.*, count(r.competitorid) as num_comp, num_event.num_events
from competition c left join regcomp r on c.competitionid = r.competitionid
left join
(
select competition.competitionid, count(e.competitionid) as num_events
from competition left join `event` e on competition.competitionid = e.competitionid
group by competition.competitionid
) as num_event on c.competitionid = num_event.competitionid
)
AS winners ON winners.competitionid = c.competitionid;
My problem is that I do not know what pattern follow, or if there's a set of methods that I need to call to create the datasource for this table. I can create an IndexedContainer and add container properties, then add that to the Vaadin table, which is what I'm doing - but the problem is when I try to persist data, I am not able to use JPA later if I don't use it at the start.
JPA lets you access referenced tables via foreign keys very conveniently by doing setVisibleColumns("parent.child") and so it is possible in theory to show any information about a single row by picking the correct entry-entity so to speak.
But what do I do if I want to create a table that shows counts in one of the columns, obviously the count is not part of the entity - but if it isn't part of the entity how can I use the benefits of JPA on tables that include data generated by stuff like avg(), count() etc.
P.S. the query retrieves a table showing all the competitions and how many competitors and events are in that competition.
This depends on what JPA provider you use.
When using Hibernate you can use calculated properties as mentioned in this post.
It then gives such annotations:
#Formula("PRICE*1.155")
private float finalPrice;
or even more complex
#Formula("(select min(o.creation_date) from Orders o where o.customer_id = id)")
private Date firstOrderDate;
Look at the other post for more details on this Hibernate feature.
For EclipseLink/Toplink I know of no solution to the problem
Persistence means you have strong link between your classes and database tables, which are "hard, durable" things.
In your queston you are fetching data from a query, not a table, so talking about persistence in this context is not correct.
What you can do is to add in your Table a custom column where you make your custom things,
or make a database view and create an Entity on it (could autogenerate with JPATools) if you want to have the full power of JPAContainer.
Cheers.
I'm using Spring Data JPA with Hibernate.
I have a class with a composite key mapped to a database table.
When I perform a save operation using the JPARepository extended interface object, I see the following log in the console:
Hibernate: select rolefuncti0_.functionalityId as function1_4_0_, rolefuncti0_.roleId as roleId2_4_0_ from RoleFunctionality_Mapping rolefuncti0_ where rolefuncti0_.functionalityId=? and rolefuncti0_.roleId=?
Hibernate: insert into RoleFunctionality_Mapping (functionalityId, roleId) values (?, ?)
This is what I see when i repeat the operation with the same data:
Hibernate: select rolefuncti0_.functionalityId as function1_4_0_, rolefuncti0_.roleId as roleId2_4_0_ from RoleFunctionality_Mapping rolefuncti0_ where rolefuncti0_.functionalityId=? and rolefuncti0_.roleId=?
It appears Spring Data first checks whether the Key exists in the database, and then proceeds to perform insertion.
There should be a way to catch the information which hibernate has found (that the database entry/key exists in the database)? How can we check that?
There is no such way. Hibernate can not determine if the primary key exists except it would issue a SQL query itself. Hibernate assumes that this check is done by the application logic to allow this to become a matter of performance optimization.
The only chance Hibernate has to notice of duplicated key problems is a SQLException from the database (or the JDBC layer) informing about a unique constraint violation of the id field. And as always one should consider a Hibernate session as invalid if a SQLException occured (since Hibernate can not ensure a valid state taking interceptor and listener processing into account).
So the spring way of issuing an extra query is the way to go unless you can provide additional logic to ensure the key is not already present in the database by using additional counters, getting and reserving free ids in bulk or using application wide event / messaging solution to synchronize entity id allocation.