Spring boot data update existing record without version - java

I have a collection in mongo containing both new data with the version field and old data imported from an old couchbase bucket which doesn't contain the version field.
How can I update an existing record? i.e. adding the version=0 automatically on save?
public class Entity {
private String someField;
#CreatedDate
private Instant createdAt;
#LastModifiedDate
private Instant updatedAt;
#Version
private Long version;
}

Related

Spring Data JPA Returning Proxy Object For One Record and Real Object For One Record

I am using spring-data-jpa to read data from db.
JPA Entity
#Entity
#Table(name = "ICM_STATUSES")
public class IcmMdStatuses implements Serializable {
#Id
#Column(name = "STATUS_INTERNAL_IDENTIFIER")
private long statusInternalIdentifier;
#Column(name = "STATUS_IDENTIFIER")
private String statusIdentifier;
#Column(name = "STATUS_NAME")
private String statusName;
#Column(name = "STATE_NAME")
private String stateName;
#Column(name = "IS_ACTIVE")
private String isActive= "Y";
#Column(name = "CREATED_BY")
private String createdBy;
#CreationTimestamp
#Column(name = "CREATE_DATE")
private Date createdDate;
#Column(name = "UPDATED_BY")
private String updatedBy;
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "UPDATE_DATE")
private Date updateDate;
}
JPA Repository
public interface StatusRepository extends JpaRepository<IcmMdStatuses, Long> {
Optional<IcmMdStatuses> findByStatusIdentifier(String statusIdentifier);
}
DB Table Data
Problem:
If I try to fetch Open status record. I am getting Hibernate Proxy Object instead of real object.
If I try to fetch Reopen status record. i am getting real object.
Except for Open status, for the rest all statuses i am getting real objects.
I could able to get the real object using Hibernate.unproxy(-)
Problem
MyEntity entity = new MyEntity();
//If i use any other status except Open the below line saves pk of that particular status.
entity.setFromStatus(statusRepository.findByStatusIdentifier("Open"));//saving null in db
entity.setToStatus(statusRepository.findByStatusIdentifier("Reopen"));//saving value 93(PK of Reopen status)
myRepo.save(entity);
Please help to understand what's the actual issue, as i am experiencing this issue only for Open Status, rest all works as expected.
The problem is most probably due to open-session-in-view and the fact that you loaded some other object that refers to this Open status object. Since that other object did not load the Open status object, it created a proxy for it which is then part of the persistence context. The next time you load that object, you retrieve that proxy instead of the real object because Hibernate must maintain the object identity guarantee for a persistence context.

Hibernate #UpdateTimestamp annotation usage

I am using Hibernate core 5.4.22 and Hibernate common annotations 5.1.2. I have tried to save the update timestamp on the DB entry using the following annotation:
#UpdateTimestamp
private LocalDateTime closedDateTime;
Unfortunately, this works only when creating a new entry in the DB but not when updating the entry row.
According to the hibernate documentation:
The #UpdateTimestamp annotation instructs Hibernate to set the annotated entity attribute with the current timestamp value of the JVM when the entity is being persisted.
The supported property types are:
java.util.Date
java.util.Calendar
java.sql.Date
java.sql.Time
java.sql.Timestamp
You use direct update query, but the #UpdateTimestamp annotation does not work for this case.
Imagine you have the TestData entity:
#Entity
public class TestData
{
#Id
private Long id;
private String name;
#UpdateTimestamp
private LocalDateTime time;
}
So, you can create new entity in the following way:
TestData testData = new TestData();
testData.setId(1L);
testData.setName("Name 1");
entityManager.persist(testData);
or update existing entity in the following way:
TestData testData = entityManager.find(TestData.class, 1L);
testData.setName("Name 11");
testData = entityManager.merge(testData);
in the last case hibernate will update the time field automatically by the following query:
13:00:32,468 DEBUG SQL:144 - // update com.test.hibernate.entities.TestData
update TEST_SCHEMA.TST_TEST_DATA
set
name=?,
time=?
where
id=?

Spring data Mongo Audit fields reflected in nested documents

When saving an audited (#CreatedDate, #LastModifiedDate) document with nested audited documents, the two dates will be also reflected in nested docs.
This is the scenario:
DocumentA.java
public class DocumentA {
#Id
private String id;
#Version
private Long version;
#CreatedDate
private Long createdDate;
#LastModifiedDate
private Long lastModifiedDate;
// getters and setters
}
DocumentB.java
public class DocumentB {
#Id
private String id;
#Version
private Long version;
#CreatedDate
private Long createdDate;
#LastModifiedDate
private Long lastModifiedDate;
private DocumentA docA;
// getters and setters
}
DocumentA is already stored in db having its createdDate and lastModifiedDate set. Then, when saving new DocumentB with nested DocumentA, the 2 dates of nested DocumentA will be modified to the same values just set for DocumentB. This only happen in nested document, while stored DocumentA is not touched (luckily!). The expected behaviour is that nested document will remain exactly the same just set via code (it means the same of the original documentA)
This is working like it is design.
Embedding the document A is not same as having the reference to document A. Embedding document is managed as part of main document means all the changes are tracked as they are top level fields in document B. Referencing document it is tracked and managed separately.
If you are only referencing you should either use manual reference and load using separate call or using $lookup aggregation query. Other alternative would be to use dbref to have the driver load the referenced document when it is loading the main document.

findByDate in spring boot jpa gives empty list

I'm using spring boot JPA for CRUD operations. I'm querying the database table with the field name created_at which is of type date.There are some rows in the table with the given date but JPA is giving zero result set. I'm using Oracle 11g
Here is my entity
import java.sql.Date;
#Entity
#Table(name="veev_json")
public class VeevJson {
#Id
#Column(name="ID")
private int id;
#Column(name="CREATED_AT")
private Date createdDate;
}
My JPA Repository
import java.util.Date;
#Repository
public interface VeevJsonRepository extends JpaRepository<VeevJson, Integer> {
public List<VeevJson> findByCreatedDate(Date date);
}
Calling the function in the service layer
Date date = new Date(); //taking current date of type java.util.Date
List<VeevJson> documents = veevJsonRepository.findByCreatedDate(date);
My DB table structure
ID NUMBER(10,0)
CREATED_AT DATE
SQL query generated by the hibernate:
select veevjson0_.ID as ID1_1_, veevjson0_.CREATED_AT as CREATED_AT2_1_, veevjson0_.JSON as JSON3_1_, veevjson0_.STATUS as STATUS4_1_ from veev_json veevjson0_ where veevjson0_.CREATED_AT=?
When using a field with type Date, you should also use the #Temporal annotation. The default value of #Temporal is TemporalType.TIMESTAMP, and your JPA implementation may get confused about dealing with a field of type java.util.Date, passing as argument of query the timestamp instead of date.
Please annotate your field as
import java.util.Date;
#Entity
#Table(name = "veev_json")
public class VeevJson {
#Id
#Column(name = "ID")
private int id;
#Temporal(TemporalType.DATE)
#Column(name = "CREATED_AT")
public Date createdDate;
...
}
Doing so will allow JPA implementation to send as queried value only the date (probably in 'YYYY-MM-dd' format) instead of timestamp or any other value.
If you prefer and your JDBC supports 4.1 version, you may exchange the java.util.Date for java8 time API types, but I guess this is out of scope here.

Audited wrong date-time in DB

I use #Audited annotation in Spring to have auditing about my update, create etc. on my db.
But I obtain on my database, a date-time with 2 hour less than real time, for example, I created a object and the I saved it, I have as create date-time: 2014-08-04 12:0 but I created it at 14:00.
This is my Auditor class, that every class audited extend:
#SuppressWarnings("serial")
#MappedSuperclass
public abstract class AbstractAudit implements Auditable<String, Long>, Serializable {
#Version
private int version;
#JsonIgnore
#Column(updatable=false)
private String createdBy;
#Type(type="org.jadira.usertype.dateandtime.joda.PersistentDateTime")
#DateTimeFormat(iso=ISO.DATE_TIME)
#JsonIgnore
#Column(updatable=false)
private DateTime createdDate;
#JsonIgnore
private String lastModifiedBy;
#Type(type="org.jadira.usertype.dateandtime.joda.PersistentDateTime")
#DateTimeFormat(iso=ISO.DATE_TIME)
#JsonIgnore
private DateTime lastModifiedDate;
//getter and setter method
}
How can I fix it??
Have I add some configuration on my project or on my server (Tomcat 7) ?
Thanks
Try to set this property in your jpa provider settings:
<prop key="jadira.usertype.databaseZone">jvm</prop>
Hope this helps.
Regards

Categories