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
Related
I'm using Spring Data JPA in my project. I would like to keep track of #CreatedBy and #LastModifiedBy when an entity is saved or updated to know which user does that activity. But the issue I am facing is I have 2 different types of users. Those are SysUser and RefUser. Both of the user types have permission to do CRUD operations in any entity.
And another thing is I have seen the most examples persisting #CreatedBy and #LastModifiedBy as String fields. But the issue is when retrieving data from the database they are retrieving as User Ids (String values). I need to store user Ids as Strings, but when retrieving it should come the user's all details like user's id, name, gender etc.
public class Record extends Auditable<String> implements Serializable {}
#MappedSuperclass
#EntityListeners(AuditingEntityListener.class)
public abstract class Auditable<T> {
#CreatedBy
protected T createdBy;
#Temporal(TemporalType.TIMESTAMP)
#CreatedDate
protected Date createdDate;
#LastModifiedBy
protected T lastModifiedBy;
#Temporal(TemporalType.TIMESTAMP)
#LastModifiedDate
protected Date lastModifiedDate;
}
Also I have a common class annotated with #MappedSuperClass that extended by SysUser and RefUser. But when I am trying to add that common class as a filed like the following it says
'Basic' attribute type should not be 'Mapped Superclass'
private CommonEntity crUsr;
private CommonEntity upUsr;
So how can I achieve this? Anybody can help me? Thanks in advance.
Well, You can do one thing here. Create a common class named User put all the common properties from SysUser and RefUser in that class. Then you can extend that in both the class and keep only distinct fields in the Child classes. This way any user do the operation will belong to User Class.
After that you can do something like this in your Class:
public class Record extends Auditable<String> implements Serializable {}
#MappedSuperclass
#EntityListeners(AuditingEntityListener.class)
public abstract class Auditable<User> {
#CreatedBy
protected User createdBy;
#Temporal(TemporalType.TIMESTAMP)
#CreatedDate
protected Date createdDate;
#LastModifiedBy
protected T lastModifiedBy;
#Temporal(TemporalType.TIMESTAMP)
#LastModifiedDate
protected Date lastModifiedDate;
}
This should solve your problem.
I have a Spring Boot application with the following entities:
#Data
#Entity
#Table(name = "jokes")
#EqualsAndHashCode(callSuper = true)
public class Joke extends BaseEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#Column(name = "content")
private String content;
}
and
#Data
#MappedSuperclass
public abstract class BaseEntity {
#Column(updatable = false)
#CreationTimestamp
private LocalDateTime createdAt;
#UpdateTimestamp
private LocalDateTime updatedAt;
}
My Controller:
#PostMapping("/jokes")
public Joke createJoke(#Valid #RequestBody Joke joke) {
return jokeRepository.save(joke);
}
The fields createdAt and updatedAt are automatically updated. I am using swagger and when I go on an end point which allows me to create a new resource, then swagger gives me the option of updating the fields createdAt and updatedAt at as well as shown below. The are not actually being updated, but I would like to not see them there. Anyone knows how I could do this?
If you want the fileds to be hidden only at the Swagger level, you can do it with the #Schema annotation of Swagger
#Data
#MappedSuperclass
public abstract class BaseEntity {
#Column(updatable = false)
#CreationTimestamp
#Schema(hidden = true) // One way to do it
private LocalDateTime createdAt;
#UpdateTimestamp
#Schema(accessMode = READ_ONLY) // Other way to do it
private LocalDateTime updatedAt;
}
The difference between the two of them is, hidden will remove the property from Schema component which will make it unavailable for both request and response payloads while accessMode will hide it only for request payloads and not show the access mode in the Schema component as mentioned in the documentation.
accessMode:
Allows to specify the access mode (AccessMode.READ_ONLY, READ_WRITE) AccessMode.READ_ONLY: value will not be written to during a request but may be returned during a response. AccessMode.WRITE_ONLY: value will only be written to during a request but not returned during a response. AccessMode.READ_WRITE: value will be written to during a request and returned during a response.
hidden:
Allows schema to be marked as hidden.
And if you want it to be ignored by the JSON parser that you're using, you'll need something like JsonIgnore if you're using Jackson as the parser.
#Data
#MappedSuperclass
public abstract class BaseEntity {
#Column(updatable = false)
#CreationTimestamp
#JsonIgnore // Jackson will ignore this field
private LocalDateTime createdAt;
#UpdateTimestamp
#JsonIgnore // this will also be ignored
private LocalDateTime updatedAt;
}
This is my first Java Spring project ever. I'm using PostgreSQL to store a WorkedDay entity as follows:
#Entity
#Table
public class WorkedDay {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column
#JsonFormat(pattern = "yyyy-MM-dd")
private Date weekDay;
#Column
private Long employeeId;
#ManyToOne
#PrimaryKeyJoinColumn(name = "employeeId", referencedColumnName = "id")
private Employee employee;
#OneToMany
private List<WorkedHours> workedHours = new ArrayList<>();
}
All "WorkedDays" are stored in a PostgreSQL table using a WorkedDayRepository class that extends CrudRepository. I'm also creating a report service which should return a list of WorkedDays in a given month.
public class WorkedDayRepositoryImpl implements WorkedDayRepositoryCustom {
public List<WorkedDay> getReportByMonthValue(int monthValue) {
//service code implementation here
}
}
I'm currently facing problems creating this custom query, since I need to retrieve from the table all Date weekDay attributes with a specific month, passed as argument.
I'm inexperienced with Spring JPA. Is there a better(or simpler) way to do this? I tried to use Specifications and Querydsl but failed.
This should work
#Repository
public interface WorkedDayRepository extends CrudRepository<WorkedDay> {
List<WorkedDay> findByWeekDay_Month(int month)
}
You could try #Query in combination with the MONTH Function.
#Repository
public interface WorkedDayRepository extends CrudRepository<WorkedDay> {
#Query("select w from WorkedDay w where MONTH(w.weekDay) = ?1")
List<WorkedDay> findByWeekDay(int month)
}
Keep in mind that not all databases might support MONTH(). Otherwise you could work with SUBSTRING(w.weekDay,6,7)
I am working on a REST based JAVA project using Spring framework. Some of my JPA entities have #JsonIgnore annotation from jackson for the properties. Example below.
#Entity
#Table(name="TRANSACTION")
public class Transaction {
#Id
#Column(name="SERIAL", length=16)
private String serial;
#Column(name="NARRATION", length=128)
private String narration;
#OneToMany(mappedBy="transaction", cascade=CascadeType.ALL, fetch=FetchType.EAGER)
private List<TransactionDetail> details;
// other fields goes here
}
#Entity
#Table(name="TRANSACTION_DETAIL")
public class TransactionDetail {
#Id
#Column(name="UUID", updatable=false)
private String uuid;
#JsonIgnore
#ManyToOne
#JoinColumn(name="FK_TRANSACTION")
private Transaction transaction;
#Column(name="ACCOUNT_NO")
private int accountNo;
// other fields goes here
}
As per the above class relationship, I want the #JsonIgnore to be applied only when I fetch Transactions.
List<Transactions> transactions = transactionsRepo.findAll()
But If I am directly fetching the TransactionDetails, I need the property transaction in TransactionDetail to be fetched as well.
List<TransactionDetail> details = transactionDetailsRepo.findByAccountNo(accountNo);
How can I use the #JsonIgnore to do this? Or else is there any other proper way to achieve this?
#Entity
#JsonInclude(JsonInclude.Include.NON_NULL)
#Table(name="TRANSACTION_DETAIL")
public class TransactionDetail {
#Id
#Column(name="UUID", updatable=false)
private String uuid;
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name="FK_TRANSACTION")
private Transaction transaction;
#Column(name="ACCOUNT_NO")
private int accountNo;
// other fields goes here
}
You can try using fetchtype as lazy , what this does is it will fetch the property in Transaction Detail Entity. but it will not fetch the related data of transaction_detail which means all of the other ones will be null. you can annotate your entity with #JsonInclude as I did to include only non null values.
and please add jackson-datatype-hibernate Jar files or if you are using maven add the dependencies in pom file
I want to exclude certain fields from a POST to my repositories.
For example I want to set the version myself so users cannot set this field themselves.
For example in the class below.
#Entity
public class User {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#CreatedDate
private LocalDateTime created;
#LastModifiedDate
private LocalDateTime lastModified;
private String name;
}
I have tried to use the #ReadOnlyProperty annotation and not having a setter for the version field. But nothing worked, users can still set the version fields themselves. I have also tried to implement a global initializer like below, but without success. The binder gets picked up though.
#ControllerAdvice
public class GlobalInitializer {
#InitBinder
public void globalBinder(WebDataBinder webDataBinder) {
webDataBinder.setDisallowedFields("name");
}
}
You should place #JsonIgnore on field and on setter, and place #JsonProperty("propertyName") on getter.
Just tested - works for me:
#JsonIgnore
#LastModifiedDate
private LocalDate lastUpdated;
#JsonProperty("lastUpdated")
public LocalDate getLastUpdated() {
return lastUpdated;
}
#JsonIgnore
public void setLastUpdated(LocalDate lastUpdated) {
this.lastUpdated = lastUpdated;
}