I have a person table and Person.java which maps to the table. I have an edit ui to change details of a Person record. On the edit page user normally changes 1 or 2 fields at a time. I am using AJAX to send the update call and want to only send the fields which are changed. Currently sending the whole object back.
The problem is at the backend about how to update database for only the changed fields.
The UI layer creates a Person object with only the changed fields and rest of the fields will be uninitialized. The object is then passed to DAO for persistence. How the DAO would know what fields are changed? What fields are uninitialized or deliberately set to null for update. Currently the whole object comes so I update all the columns.
What I usually do it's to get first the object with all its fields from the database. Then I update the field that I want and then I send it back to the DAO. The DAO updates the whole object no matter what. Doing it in this way the DAO does not care which one was changed.
There are some special cases though where you might want to add another DAO method.
if you are using ORM (Hibernate) for persistence then you can use hibernate.merge to do a selective update.
Approach for JDBC:
Keep the object in session which is used to fill the UI with the initial values that the user can edit.
When user submit the changes, compare the submitted values with the object in session and add to a map that contain field name and new value. Use this map to create the update query dynamically.
Related
I'm playing around with spring-data-jdbc and discovered a problem, with I can't solve using Google.
No matter what I try to do, I just can't push a trivial object into the database (Bean1.java:25):
carRepository.save(new Car(2L, "BMW", "5"));
Both, without one and with a TransactionManager +#Transactional the database (apparently) does not commit the record.
The code is based on a Postgres database, but you might also simply use a H2 below and get the same result.
Here is the (minimalistic) source code:
https://github.com/bitmagier/spring-data-jdbc-sandbox/tree/stackoverflow-question
Can somebody tell me, why the car is not inserted into the database?
This is not related to transactions not working.
Instead, it's about Spring Data JDBC considering your instance an existing instance that needs updating (instead of inserting).
You can verify this is the problem by activating logging for org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate. You should see an update but no insert.
By default, Spring Data JDBC considers an entity as new when it has an id of an object type and a value of null or of a primitive type (e.g. int or long) and a value of 0.
If your entity has an attribute with #Version annotation that attribute will be used to determine if the instance is a new one.
You have the following options in order to make it work:
Set the id to null and configure your database schema so that it will automatically create a new value on insert. After the save your entity instance will contain the generated value from the database.
Note: Spring Data JDBC will set the id even if it is final in your entity.
Leave the id null and set it in a Before-Convert listener to the desired value.
Let your entity implement Persistable. This allows you to control when an entity is considered new. You'll probably need a listener as well so you can let the entity know it is not new any longer.
Beginning with version 1.1 of Spring Data JDBC you'll also be able to use a JdbcAggregateTemplate to do a direct insert, without inspecting the id, see https://jira.spring.io/browse/DATAJDBC-282. Of course, you can do that in a custom method of your repository, as is done in this example: https://github.com/spring-projects/spring-data-examples/pull/441
I would like to update a field by a unique ID in a MySQL database.
First method: fetch the object (select * from) from the database using unique ID (by uniqueresult()), then set the desired value to object and saveOrUpdate is performed.
Second method is to write an update query in a DAO implementation (update table tab set tab.name=123 where..., executeUpdate()), also the same result.
Which is a good way to perform update operation and why?
Well if you are using Hibernate, why would you do it in native SQL when you can just use Hibernate Sessions's .get(), .load(), .merge() .update() methods.
Here's an example from Hibernate documentation to modify a persistent object:
DomesticCat cat = (DomesticCat) sess.load( Cat.class, new Long(69) );
cat.setName("PK");
sess.flush(); // changes to cat are automatically detected and persisted
For further reading you can check Modifying persistent objects and Modifying detached objects sections in Hibernate documentation.
And according to the documentation :
The most straightforward way to update the state of an object is to load() it and then manipulate it directly while the Session is open.
I hope this answers both your questions Which is a good way to perform update operation and why?.
There is no "good way" to perform the update you want to. It entierly depend on your needs.
Both method work, but the first will permit you to update more than one field without having to modify your sql query. It will be the responsability of the developper to take care at the state of the object before calling the saveOrUpdate method.
The second method will ensure that no other field will be update in database.
Answer you on your future needs. Do you only need this field to be updated? Can it change in the future? What will be the inpact of both method on the application?
Then you will have your answer.
I want to create and persist an object with member fields which are from other entities. I have the int keys of these fields when the user sends this information from a web page.
I see two scenarios for creating the object:
Directly make a row in the DB table using those keys but I suspect this is the wrong way to go.
Create a constructor which takes objects of the same type as the member fields and invoke the constructor after I obtain the objects using those keys. (I am not sure if this right and if it is, what would be the next step after creating the object. Should I immediately try to persist the new object or not?)
I imagine this pertains to Hibernate only (I'm just now beginning to use these two frameworks). I have an application that tracks sessions for users. While a session is active, the Session entity is stored in a table for active sessions. When the user goes offline and the session ends, the session is moved to a secondary historical table.
How do I achieve this with Hibernate? Right now I have a Session.hbm.xml file that maps a Session object to the active sessions table. Can I map it to a secondary table and somehow specify to which table I want it to persist when I call saveOrUpdate?
My reputation currently won't allow me to answer my own question this quickly. I don't want anyone to waste their time on this though, since I found an answer, so I'm posting it here as an edit.
I can do this by making use of the entity-name attribute in a mapping file. I created a second mapping, identical to Session.hbm.xml, called HistoricalSession.hbm.xml. In this new mapping file I reference the same Session class, but add:
entity-name="HistoricalSession"
Then I map the object to my second (historical) table just like normal. Calling save() or saveOrUpdate() defaults to using the classname as the entity-name, and saves in my primary table as before. Now, when I want to save a session to the historical table I use the Hibernate API overrides that allow you to specify an entity-name:
saveOrUpdate("HistoricalSession",session);
This accomplishes exactly what I want without need to create another Java class for historical sessions
I can do this by making use of the entity-name attribute in a mapping file. I created a second mapping, identical to Session.hbm.xml, called HistoricalSession.hbm.xml. In this new mapping file I reference the same Session class, but add:
entity-name="HistoricalSession"
Then I map the object to my second (historical) table just like normal. Calling save() or saveOrUpdate() defaults to using the classname as the entity-name, and saves in my primary table as before. Now, when I want to save a session to the historical table I use the Hibernate API overrides that allow you to specify an entity-name:
saveOrUpdate("HistoricalSession",session);
This accomplishes exactly what I want without need to create another Java class for historical sessions
A couple of way to do this could be:
Use a database trigger when the session gets expired the trrigger will move the row to the historical table.
You can create a HistoricalSession extends Session and then do a second mapping for HistoricalSession and write the code to delete from Session and insert into historical session.
Your need sounds like more of an audit like.
Check project Hibernate Envers it might help solve your case in a better way.
I am starting to use JPA and I always get confused with the term of entities and their usage, I have read a lot but I still don't quite get it.
I read the Oracle documentation of it but it does not really explain its role in the transaction.
What are JPA enities? does they actually hold the data for each row, I mean, are they stored instances that hold the row data? or they just map tables of the db and then insert and delete in them?
for example if I use this:
entity.setUserName("michel");
Then persisting it, then changing the user name, and persisitig it again (i.e merging it)
Does this change the previously entered user name? or does it create a new row in the db?
An Entity is roughly the same thing as an instance of a class when you are thinking from a code perspective or a row in a table (basically) when you are thinking from a database perspective.
So, it's essentially a persisted / persistable instance of a class. Changing values on it works just like changing values on any other class instance. The difference is that you can persist those changes and, in general, the current state of the class instance (entity) will overwrite the values the row for that instance (entity) had in the database, based on the primary key in the database matching the "id" or similar field in the class instance (entity).
There are exceptions to this behavior, of course, but this is true in general.
It's a model. It's a domain object that can be persisted. Don't over think it. Akin to a Rails model. And remember, models (in this paradigm) are mutable!