I would like to use the setter of my Entity without updating the database.
credentials.setPassword(null);
return credentials;
While doing this, it automatically update the DB and set the password to null.
I would like to return the object credentials with password null, without updating the DB
Anyone knows how to do it?
You could (and maybe should) covert this Entity into a DTO before exposing it to wherever you are sending your data. That way you can fulfill whatever requirement you want (like not exposing the password) without updating your database.
if the entity is still associated with the session then there is a possibility of updating the database table when there is a change in the entity params.
refer this post for more details.
make sure that the entity detached and then make the changes or use DTO with the information you want to pass on to UI or destination.
Related
I have a web app backed by spring boot/jpa within which users can upload a file via the UI to make changes to JPA entities. I would like to return those changes as a 'preview' to the UI, without actually updating the database. I'm wondering what's considered the best practice for manipulating these JPA entities without actually making updates to the database until the user has approved the changes ... gather these records via CRUD to update? Pull the entity and then detach to manipulate and return? Return an updated clone?
Create a DTO(Data transfer object) with the fields that you need to preview, and when the user approve the changes, then use that DTO to update the database.
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 save in my database information about history, for example user "dog" edited field "grass" in table "garden".
I have trigger which saves everything correctly but I have problem with username "dog". Username is logged user's name and I don't now how to "catch" it, because I don't know how to tell my database (PostgreSQL) that this specific user did that.
How can I tell my trigger that it should use value "dog"?
I would like to write an application in Java using Spring Framework and Hibernate Framework. I haven't any app code, because now I'm creating database and thinking about my future application.
Any ideas?
For certain database platforms, they offer context parameters. To use these, you would:
Set the database context parameters.
You can simply use the native SQL interface exposed by Session or EntityManager to accomplish this step.
Register an AfterTransactionCompletionProcess with the Session.
This should basically use the provided Session and clear the database context parameters which you set as part of (1). You would want to do this regardless of whether the transaction was successful or not. This step makes sure those context parameters are cleared prior to giving the JDBC connection back to your connection pool.
Execute your normal ORM changes.
But there is probably a much simplier approach all together, called Hibernate Envers.
Hibernate Envers is designed to mirror your mapped #Entity classes and keep a running history of changes made to your entities. You can easily configure the fields you'd like audited should there only be a subset of fields you're interested in the history on. Additionally, the Envers API exposes an easy way for you to query the history tables and get historical snapshots.
In order to store your username "dog" with Hibernate Envers, you would need to merely implement a custom RevisionEntity that contains your userName field and set it. You can find more information on how to configure the necessary components for this here.
I have entity with updatedAt and updatedBy audit fields. I want to set this fields only if entity state was changed. So, for dirty checking I can use either Hibernate EmptyInterceptor interface (overriding onFlushDirty() method) or JPA listeners (#PreUpdate). But how I can get current userId inside interceptor or listener? To my mind comes 2 solutions:
Pass userId to DAO layer, so I can create custom interceptor passing to it constructor userId and then use this interceptor when creating new Session.
Set current userId to public-static ThreadLocal variable so I have access to it from any place.
But I think both approaches are ugly. So may be there is exist some more elegant way to solve my problem?
Please note, I can't use Envers library (it don't fit our project requirements).
Thanks.
I recommend storing the Person object in the Http session when the user authenticates. This way you can grab it from the session and use the merge functionality in the entity manager to convert it back to an attached entity.
I personally also assign the entity to the requiring domain object in the dao and do not use the #PreUpdate because I do not want the entity to have to know how to retrieve the current user object.
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.