How can I implement JPA Auditing like functionality in Quarkus - spring-boot

I'm using Quarkus framework, and I want to implement functionality similar to JPA auditing like:
#MappedSuperclass
#EntityListeners(AuditingEntityListener.class)
public class EntityAuditInfo {
#CreatedBy
#Basic(optional = false)
#Column(name = "created_by", nullable = false)
private Integer createdBy;
#CreatedDate
#Basic(optional = false)
#Column(name = "created_on", nullable = false)
#Temporal(TemporalType.TIMESTAMP)
private Date createdOn;
#LastModifiedBy
#Column(name = "modified_by")
private Integer modifiedBy;
#LastModifiedDate
#Column(name = "modified_on")
#Temporal(TemporalType.TIMESTAMP)
private Date modifiedOn;
....
I have tried searching it in Quarkus documention but didn't.

Yes, this is supported (although not really documented as it's a standard Hibernate/JPA feature).
You can see some example usages in the Quarkus integration tests here.

Related

Spring JPA repository cannot resolve property of entity

Im trying to do a simple search for two columns for a table.
My customer entity class snipet:
#Entity
#Table(name = "CUSTOMER")
public class Customer {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "CUSTOMER_ID", nullable = false)
private int customer_id;
#Column(name = "FIRST_NAME", nullable = false)
private String first_name;
#Column(name = "LAST_NAME", nullable = false)
private String last_name;
#Column(name = "PHONE_NUMBER", nullable = false)
private String phone_number;
#Column(name = "EMAIL")
private String email;
my customerRepository class snipet:
#Repository
public interface CustomerRepository extends JpaRepository<Customer, Integer> {
List<Customer> findAllByFirst_nameAndLast_name(String firstName, String lastname);
}
When compiling and running springBoot i get this error:
nested exception is java.lang.IllegalArgumentException: Failed to create query for method public abstract java.util.List com.owl.owlserver.repositories.CustomerRepository.findAllByFirst_nameAndLast_name(java.lang.String,java.lang.String)! No property first found for type Customer!
So its not able to detect the fields in the customer object, should I be importing the customer class into the repository somehow?
The problem lies in your snake_case naming convention, it's recommended to use camelCase naming convention.
As the Spring docs say:
Because we treat the underscore character as a reserved character, we
strongly advise following standard Java naming conventions (that is,
not using underscores in property names but using camel case instead).
You can see a related JIRA issue here -- underscores are not supported in property names.
I would recommend keeping the properties in a camel-case as per standards
Because we treat the underscore character as a reserved character, we strongly advise following standard Java naming conventions (that is, not using underscores in property names but using camel case instead).
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "CUSTOMER_ID", nullable = false)
private int customerId;
#Column(name = "FIRST_NAME", nullable = false)
private String firstName;
#Column(name = "LAST_NAME", nullable = false)
private String lastName;
#Column(name = "PHONE_NUMBER", nullable = false)
private String phoneNumber;
#Column(name = "EMAIL")
private String email;
And then query as well as per Property Expressions
List<Customer> findAllByFirstNameAndLastName(String firstName, String lastname);
The whole point of Spring JPA is to simplify query building using the methods defined in Repository. The convention is to use the camelCase for naming field in Entity and the same while writing query methods. Just change the naming of entity fields from snake case to camel case and you're good to go.

How to add conditional based #NotNull constraint in spring boot?

We are using spring-boot.
I want to add conditional based constraint in java class.
For e.g.
#Entity
public class User {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name = "user_id")
private Integer userId;
#Column(name = "firstName")
private String firstName;
#Column(name = "lastName")
private String lastName;
}
Now in above code I want to put #NotNull constraint on lastName property if and only if the firstName property is not empty.

Set of enum Spring data

I want to use in my spring application with spring data set of enums, which will be stored in db. Currently i tried it in that way:
#NotNull
#Column(name = "ROLES")
#Enumerated(EnumType.STRING)
#ElementCollection(targetClass = Role.class)
private Role role;
#NotNull
#Column(name = "PERMISSIONS")
#Enumerated(EnumType.STRING)
#ElementCollection(targetClass = Permission.class)
private Set<Permission> permissions;
but as you propably know it do not work. How can i use enums to be stored in db?
Best regards!
You should add #CollectionTable anotation with specified name and join column.
May this will work for you.
#ElementCollection(targetClass = Permission.class)
#CollectionTable(name = "permissions", joinColumns = #JoinColumn(name = "permission_id"))
#Column(name = "permission", nullable = false)
#Enumerated(EnumType.STRING)
Set<Permission> permission;

Spring JPA audting is not invoked

I have implemented spring data jpa auditing. Below is my configuration file
#Configuration
#ComponentScan(basePackages = "com.myapplication.test")
#EnableWebMvc
#EnableTransactionManagement
#EnableJpaRepositories(basePackages = "com.myapplication.test.repository")
#EnableJpaAuditing(auditorAwareRef = "auditorProvider", dateTimeProviderRef = "dateTimeProvider")
#EnableSpringDataWebSupport
public class ApplicationConfiguration {
private static final Logger loggger = Logger.getLogger(ApplicationConfiguration.class);
#Autowired
private ConfigurationProperties configProps;
#Bean("auditorProvider")
public AuditorAware<Integer> auditorProvider() {
return () -> {
AuthenticationToken authentication = (AuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
return (authentication != null && authentication.isAuthenticated()) ? authentication.getUser().getUserId() : null;
};
}
#Bean
public DateTimeProvider dateTimeProvider() {
return () -> GregorianCalendar.from(ZonedDateTime.now());
}
}
Here is my entity super class
#MappedSuperclass
#EntityListeners(AuditingEntityListener.class)
public abstract class BaseEntity {
#JsonIgnore
#Column(name = "created_by", updatable = false)
private Integer createdBy;
#JsonIgnore
#CreationTimestamp
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "created_on", updatable = false)
private Date createdOn;
#JsonIgnore
#Column(name = "last_updated_by")
private Integer updatedBy;
#JsonIgnore
#UpdateTimestamp
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "last_updated_on")
private Date updatedOn;
}
auditorProvider is getting the user id from the Spring Security context. I have used spring-security-oauth2.
below the versions of the libraries I am having
<spring.version>4.3.6.RELEASE</spring.version>
<hibernate.version>5.2.9.Final</hibernate.version>
<springsecurity.version>4.1.4.RELEASE</springsecurity.version>
<springsecurityoauth2.version>2.0.12.RELEASE</springsecurityoauth2.version>
When I save an entity the auditing methods are not getting called(in debug) and created/updated fields are not updated in the table.
Instead of using the hibernate annotations, you should use the spring data ones like:
#Column(name = "created_date", nullable = false, updatable = false)
#CreatedDate
private long createdDate;
#Column(name = "modified_date")
#LastModifiedDate
private long modifiedDate;
This always worked for me, as specified in this tutorial: Jpa Auditing

Spring/JPA PostgreSQL - Spring Data Auditing INTEGER instead of bytea, Envers

In my Spring/JPA/Hibernate/Envers PostgreSQL application I'm trying to implement Spring Data Auditing
I have a following entity:
#Audited
#AuditTable("levels_history")
#Entity
#Table(name = "levels")
public class Level extends BaseEntity implements Serializable {
private static final long serialVersionUID = 642499791438799548L;
#Id
#SequenceGenerator(name = "levels_id_seq", sequenceName = "levels_id_seq", allocationSize = 1)
#GeneratedValue(strategy = GenerationType.AUTO, generator = "levels_id_seq")
private Long id;
private String name;
#NotAudited
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "level")
private List<Card> card = new ArrayList<Card>();
#CreatedBy
#Column(name = "created_by_user_id")
private User createdByUser;
#LastModifiedBy
#Column(name = "last_modified_by_user_id")
private User lastModifiedByUser;
where I have added:
#CreatedBy
#Column(name = "created_by_user_id")
private User createdByUser;
#LastModifiedBy
#Column(name = "last_modified_by_user_id")
private User lastModifiedByUser;
at the database level I want to write INTEGER ID for created_by_user_id and last_modified_by_user_id but during execution my application throws an error that created_by_user_id should be bytea type.
What am I doing wrong and how to configure Spring Data Auditing to use INTEGER for this purpose ?

Resources