Spring Boot Auditing Hostname and HostIp - java

I have an auditing entity which defined like this:
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import java.io.Serializable;
import java.time.Instant;
import javax.persistence.Column;
import javax.persistence.EntityListeners;
import javax.persistence.MappedSuperclass;
/**
* Base abstract class for entities which will hold definitions for created, last modified, created by,
* last modified by attributes.
*/
#MappedSuperclass
#EntityListeners(AuditingEntityListener.class)
public abstract class AbstractAuditingEntity implements Serializable {
private static final long serialVersionUID = 1L;
#CreatedBy
#Column(name = "created_by", nullable = false, length = 50, updatable = false)
#JsonIgnore
private String createdBy;
#CreatedDate
#Column(name = "created_date", updatable = false)
#JsonIgnore
private Instant createdDate = Instant.now();
#LastModifiedBy
#Column(name = "last_modified_by", length = 50)
#JsonIgnore
private String lastModifiedBy;
#LastModifiedDate
#Column(name = "last_modified_date")
#JsonIgnore
private Instant lastModifiedDate = Instant.now();
public String getCreatedBy() {
return createdBy;
}
public void setCreatedBy(String createdBy) {
this.createdBy = createdBy;
}
public Instant getCreatedDate() {
return createdDate;
}
public void setCreatedDate(Instant createdDate) {
this.createdDate = createdDate;
}
public String getLastModifiedBy() {
return lastModifiedBy;
}
public void setLastModifiedBy(String lastModifiedBy) {
this.lastModifiedBy = lastModifiedBy;
}
public Instant getLastModifiedDate() {
return lastModifiedDate;
}
public void setLastModifiedDate(Instant lastModifiedDate) {
this.lastModifiedDate = lastModifiedDate;
}
}
And this is the implementation:
import com.app.derin.uaa.config.Constants;
import java.util.Optional;
import org.springframework.data.domain.AuditorAware;
import org.springframework.stereotype.Component;
/**
* Implementation of {#link AuditorAware} based on Spring Security.
*/
#Component
public class SpringSecurityAuditorAware implements AuditorAware<String> {
#Override
public Optional<String> getCurrentAuditor() {
return Optional.of(SecurityUtils.getCurrentUserName().orElse(Constants.SYSTEM_ACCOUNT));
}
}
But I also need to store Hostname of request ip ( if it can be acquired from browser/dns if not it can be null) and request ip.
I found some examples and i changed my class to this:
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.hibernate.annotations.ColumnDefault;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import javax.persistence.*;
import java.io.Serializable;
import java.time.Instant;
#MappedSuperclass
#EntityListeners(AuditingEntityListener.class)
public abstract class AbstractAuditingEntity<T> implements Serializable {
#CreatedDate
#JsonIgnore
#Column(name = "created_date", updatable = false)
private Instant createdDate = Instant.now();
#CreatedBy
#JsonIgnore
#Column(name = "created_by", updatable = false)
#Embedded
private T createdBy;
#LastModifiedDate
#Column(name = "modified_date")
#JsonIgnore
private Instant modifiedDate = Instant.now();;
#LastModifiedBy
#Column(name = "modified_by")
#JsonIgnore
#Embedded
private T modifiedBy;
public Instant getCreatedDate() {
return createdDate;
}
public void setCreatedDate(Instant createdDate) {
this.createdDate = createdDate;
}
public T getCreatedBy() {
return createdBy;
}
public void setCreatedBy(T createdBy) {
this.createdBy = createdBy;
}
public Instant getModifiedDate() {
return modifiedDate;
}
public void setModifiedDate(Instant modifiedDate) {
this.modifiedDate = modifiedDate;
}
public T getModifiedBy() {
return modifiedBy;
}
public void setModifiedBy(T modifiedBy) {
this.modifiedBy = modifiedBy;
}
}
And my implementation to this:
import com.app.derin.configuration.config.Constants;
import java.util.Optional;
import com.app.derin.configuration.ext.AuditorDetails;
import org.springframework.data.domain.AuditorAware;
import org.springframework.stereotype.Component;
/**
* Implementation of {#link AuditorAware} based on Spring Security.
*/
#Component
public class SpringSecurityAuditorAware implements AuditorAware<AuditorDetails> {
#Override
public Optional<AuditorDetails> getCurrentAuditor() {
AuditorDetails currentAuditor = new AuditorDetails();
currentAuditor.setLoggedUser(SecurityUtils.getCurrentUserLogin().orElse(Constants.SYSTEM_ACCOUNT));
currentAuditor.setHostIp("ip");
return Optional.of(currentAuditor);
}
}
But if I am right hibernate doesn't support generic types. I am getting this error:
[ERROR] Error setting up or running Liquibase:
[ERROR] org.hibernate.AnnotationException: Property com.app.derin.configuration.ext.extendedFields.AbstractAuditingEntity.createdBy has an unbound type and no explicit target entity. Resolve this Generic usage issue or set an explicit targe
t attribute (eg #OneToMany(target=) or use an explicit #Type
Is there any way to achieve this?

I found solution and here is how did:
After a lot of googling i found that my problem is with hibernate annotation. I am trying to send Datatype that hibernate doesn't know about. So I changed my class to custom type for hibernate.
More info you can check this link. It helped me.
My AuditorDetails class:
import java.io.Serializable;
import java.util.Objects;
public final class AuditorDetails implements Serializable {
private final String loggedUser;
private final String hostName;
private final String hostIp;
public AuditorDetails(String loggedUser, String hostName, String hostIp) {
this.loggedUser = loggedUser;
this.hostName = hostName;
this.hostIp = hostIp;
}
public String getLoggedUser() {
return loggedUser;
}
public String getHostName() {
return hostName;
}
public String getHostIp() {
return hostIp;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
AuditorDetails that = (AuditorDetails) o;
return Objects.equals(loggedUser, that.loggedUser) &&
Objects.equals(hostName, that.hostName) &&
Objects.equals(hostIp, that.hostIp);
}
#Override
public int hashCode() {
return Objects.hash(loggedUser, hostName, hostIp);
}
}
AuditorDetailsType class:
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.usertype.UserType;
import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.Objects;
public class AuditorDetailsType implements UserType {
#Override
public int[] sqlTypes() {
return new int[]{Types.VARCHAR, Types.VARCHAR, Types.VARCHAR};
}
#Override
public Class returnedClass() {
return AuditorDetails.class;
}
#Override
public boolean equals(Object o, Object o1) throws HibernateException {
if(o == o1)
return true;
if (Objects.isNull(o) || Objects.isNull(o1))
return false;
return o.equals(o1);
}
#Override
public int hashCode(Object o) throws HibernateException {
return o.hashCode();
}
#Override
public Object nullSafeGet(ResultSet resultSet, String[] strings, SharedSessionContractImplementor sharedSessionContractImplementor, Object o) throws HibernateException, SQLException {
String loggedUser = resultSet.getString(strings[0]);
if(resultSet.wasNull())
return null;
String hostName = resultSet.getString(strings[1]);
String hostIp = resultSet.getString(strings[2]);
AuditorDetails currentAuditor = new AuditorDetails(loggedUser, hostName, hostIp);
return currentAuditor;
}
#Override
public void nullSafeSet(PreparedStatement preparedStatement, Object o, int i, SharedSessionContractImplementor sharedSessionContractImplementor) throws HibernateException, SQLException {
if (Objects.isNull(o)){
preparedStatement.setNull(i,Types.VARCHAR);
}
else {
AuditorDetails currentAuditor = (AuditorDetails) o;
preparedStatement.setString(i,currentAuditor.getLoggedUser());
preparedStatement.setString(i+1,currentAuditor.getHostName());
preparedStatement.setString(i+2,currentAuditor.getHostIp());
}
}
#Override
public Object deepCopy(Object o) throws HibernateException {
if (Objects.isNull(o))
return null;
AuditorDetails currentAuditor = (AuditorDetails) o;
return new AuditorDetails(currentAuditor.getLoggedUser(), currentAuditor.getHostName(), currentAuditor.getHostIp());
}
#Override
public boolean isMutable() {
return false;
}
#Override
public Serializable disassemble(Object o) throws HibernateException {
return (Serializable) o;
}
#Override
public Object assemble(Serializable serializable, Object o) throws HibernateException {
return serializable;
}
#Override
public Object replace(Object o, Object o1, Object o2) throws HibernateException {
return o;
}
}
AbstractAuditingEntity:
import com.app.derin.uaa.ext.AuditorDetails;
import com.app.derin.uaa.ext.AuditorDetailsType;
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.hibernate.annotations.ColumnDefault;
import org.hibernate.annotations.Columns;
import org.hibernate.annotations.TypeDef;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import javax.persistence.Column;
import javax.persistence.EntityListeners;
import javax.persistence.MappedSuperclass;
import java.time.Instant;
#TypeDef(name = "AuditorDetails",
typeClass = AuditorDetailsType.class,
defaultForType = AuditorDetails.class)
#MappedSuperclass
#EntityListeners(AuditingEntityListener.class)
public abstract class AbstractAuditingEntity{
#CreatedDate
#JsonIgnore
#Column(name = "created_date", updatable = false)
private Instant createdDate = Instant.now();
#CreatedBy
#Columns(columns = {#Column(name = "created_by", updatable = false),
#Column(name = "created_host_name", updatable = false),
#Column(name = "created_host_ip", updatable = false)})
private AuditorDetails createdBy;
#LastModifiedDate
#Column(name = "modified_date")
#JsonIgnore
private Instant modifiedDate = Instant.now();
#LastModifiedBy
#Columns(columns = {#Column(name = "modified_by"),
#Column(name = "modified_host_name"),
#Column(name = "modified_host_ip")})
private AuditorDetails modifiedBy;
#Column(name = "row_status")
#JsonIgnore
#ColumnDefault("1")
private Integer rowStatus = 1;
protected AbstractAuditingEntity() {
}
public AuditorDetails getModifiedBy() {
return modifiedBy;
}
public Instant getCreatedDate() {
return createdDate;
}
public void setCreatedDate(Instant createdDate) {
this.createdDate = createdDate;
}
public AuditorDetails getCreatedBy() {
return createdBy;
}
public void setCreatedBy(AuditorDetails createdBy) {
this.createdBy = createdBy;
}
public Instant getModifiedDate() {
return modifiedDate;
}
public void setModifiedDate(Instant modifiedDate) {
this.modifiedDate = modifiedDate;
}
public Integer getRowStatus() {
return rowStatus;
}
public void setRowStatus(Integer rowStatus) {
this.rowStatus = rowStatus;
}
}
SpringSecurityAuditorAware:
import com.app.derin.uaa.config.Constants;
import java.util.Optional;
import com.app.derin.uaa.ext.AuditorDetails;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.AuditorAware;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
/**
* Implementation of {#link AuditorAware} based on Spring Security.
*/
#Component
public class SpringSecurityAuditorAware implements AuditorAware<AuditorDetails> {
private final Logger log = LoggerFactory.getLogger(SpringSecurityAuditorAware.class);
#Override
public Optional<AuditorDetails> getCurrentAuditor() {
ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = sra.getRequest();
if(request != null) {
String hostIp = getClientIpAddress(request);
String hostName = "";
AuditorDetails currentAuditor = new AuditorDetails(SecurityUtils.getCurrentUserName().orElse(Constants.SYSTEM_ACCOUNT),
hostName, hostIp);
return Optional.of(currentAuditor);
}
return Optional.of(currentAuditor);
}
private static final String[] IP_HEADER_CANDIDATES = {
"X-Forwarded-For",
"Proxy-Client-IP",
"WL-Proxy-Client-IP",
"HTTP_X_FORWARDED_FOR",
"HTTP_X_FORWARDED",
"HTTP_X_CLUSTER_CLIENT_IP",
"HTTP_CLIENT_IP",
"HTTP_FORWARDED_FOR",
"HTTP_FORWARDED",
"HTTP_VIA",
"REMOTE_ADDR" };
public String getClientIpAddress(HttpServletRequest request) {
for (String header : IP_HEADER_CANDIDATES) {
String ip = request.getHeader(header);
log.info("ip : {}", ip);
if (ip != null && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip)) {
return ip;
}
}
return request.getRemoteAddr();
}
}

Related

How to enum mapping with jpa Spring boot why not save enum value in DB in DB saving enum key

import java.io.Serializable;
import java.util.Date;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Version;
import org.hibernate.annotations.GenericGenerator;
import com.lue.billingsystem.enums.Status;
import com.lue.billingsystem.enums.Types;
#Entity
#Table(name="product_tab")
public class Product implements Serializable{
private static final long serialVersionUID = 8919320309645697466L;
#Id
#Column(name="prod_id",updatable=false)
#GenericGenerator(name="product_tab_genetator",strategy="increment")
#GeneratedValue(generator="product_tab_genetator")
private Long id;
private String name;
#Enumerated(EnumType.STRING)
#Column(name = "type")
private Types type;
#Column(name = "status")
#Enumerated(EnumType.STRING)
private Status status;
#Column(name = "description", length = 200)
private String description;
#OneToMany(mappedBy="product")
private List<Charge> charges;
#Column(name = "create_date", columnDefinition = "DATETIME")
private Date createDate;
#Column(name = "update_date", columnDefinition = "DATETIME")
private Date updateDate;
//#Version
private Integer version;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Types getType() {
return type;
}
public void setType(Types type) {
this.type = type;
}
public Status getStatus() {
return status;
}
public void setStatus(Status status) {
this.status = status;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public List<Charge> getCharges() {
return charges;
}
public void setCharges(List<Charge> charges) {
this.charges = charges;
}
public Date getCreateDate() {
return createDate;
}
public void setCreateDate(Date createDate) {
this.createDate = createDate;
}
public Date getUpdateDate() {
return updateDate;
}
public void setUpdateDate(Date updateDate) {
this.updateDate = updateDate;
}
public Integer getVersion() {
return version;
}
public void setVersion(Integer version) {
this.version = version;
}
}
import org.springframework.http.HttpStatus;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.lue.billingsystem.enums.utils.StatusDeserializer;
import com.lue.billingsystem.exception.BillingException;
#JsonDeserialize(using = StatusDeserializer.class)
public enum Status {
ACTIVE("Active"), INACTIVE("Inactive");
private final String text;
Status(final String text) {
this.text = text;
}
#Override
public String toString() {
return text;
}
public String getText() {
return this.text;
}
public static Status fromText(String text) {
for (Status r : Status.values()) {
if (r.getText().equals(text)) {
System.out.println(r);
return r;
}
}
throw new BillingException("Your Status not valied: "+text +" ", HttpStatus.BAD_REQUEST, 400);
}
}
import java.io.IOException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import com.lue.billingsystem.enums.Status;
public class StatusDeserializer extends JsonDeserializer<Status> {
#Override
public Status deserialize(JsonParser jsonParser, DeserializationContext deserializationContext)
throws IOException, JsonProcessingException {
ObjectCodec oc = jsonParser.getCodec();
JsonNode node = oc.readTree(jsonParser);
if (node == null) {
return null;
}
String text = node.textValue(); // gives "A" from the request
if (text == null) {
return null;
}
//System.out.println(Status.fromText(text) + "---------------");
return Status.fromText(text);
}
}
How to enum mapping with jpa Spring boot why not save enum value in DB in DB saving enum key when i saving product in databse not save status like Active it always save ACTIVE
You just need to pay attention to the enum values when the table is being created.
What are the enum values in the table e.g. in status column, are the values defined as 'Active', 'Inactive' or 'ACTIVE', 'INACTIVE'. That's what will determine the value saved.
If the enum values are defined as 'ACTIVE', 'INACTIVE', if you insert 'active' as the value for status, it will change to 'ACTIVE' inside the database because it inserts based on the pre defined enum values.

Mapped Entity null on #OneToOne with #JoinColumn

I get the mapped entity always null but, FetchType.EAGER is set already. I have a Booking entity class that maps to two other entities - Slot and Subscriber. Both the entities are null when I fetch the booking entity
Booking class
import java.util.Date;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Version;
#Entity
#Table(name = "BOOKING")
public class Booking {
public Booking(){
}
#Id #GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name = "id")
private Integer id;
#Column(name = "title")
private String title;
#Column(name = "descr")
private String desc;
#OneToOne(fetch=FetchType.EAGER)
#JoinColumn(name = "slotid",insertable = false, updatable = false)
private Slot slot;
private Integer slotid;
private Integer subscriberid;
#OneToOne(fetch=FetchType.EAGER)
#JoinColumn(name = "subscriberid",insertable = false, updatable = false)
private User subscriber;
#Column(name = "created")
#Temporal(TemporalType.TIMESTAMP)
private Date created;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
#OneToOne(fetch=FetchType.EAGER)
#JoinColumn(name = "slotid",referencedColumnName="slotid")
public Slot getSlot() {
return slot;
}
public void setSlot(Slot slot) {
this.slot = slot;
}
#OneToOne(fetch=FetchType.EAGER)
#JoinColumn(name = "subscriberid",referencedColumnName="userid")
public User getSubscriber() {
return subscriber;
}
public void setSubscriber(User subscriber) {
this.subscriber = subscriber;
}
public Date getCreated() {
return created;
}
public void setCreated(Date created) {
this.created = created;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public Integer getSlotid() {
return slotid;
}
public void setSlotid(Integer slotid) {
this.slotid = slotid;
}
public Integer getSubscriberid() {
return subscriberid;
}
public void setSubscriberid(Integer subscriberid) {
this.subscriberid = subscriberid;
}
}
Slot class
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Version;
#Entity
#Table(name="SLOT")
public class Slot {
public Slot(){
}
#Id #GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="slotid")
private Integer id;
#OneToOne(fetch=FetchType.EAGER)
#JoinColumn(name="ownerid",insertable = false, updatable = false)
private User user;
#Column(name="startdate")
private Date startdate;
#Column(name="enddate")
private Date enddate;
#Column(name="status")
private String status;
private Integer ownerid;
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "created", nullable = false, updatable=false)
#Version
private Date created;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public User getUser() {
return this.user;
}
public void setUser(User owner) {
this.user = owner;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public Integer getOwnerid() {
return ownerid;
}
public void setOwnerid(Integer ownerid) {
this.ownerid = ownerid;
}
public Date getCreated() {
return created;
}
public void setCreated(Date created) {
this.created = created;
}
public Date getStartdate() {
return startdate;
}
public void setStartdate(Date startdate) {
this.startdate = startdate;
}
public Date getEnddate() {
return enddate;
}
public void setEnddate(Date enddate) {
this.enddate = enddate;
}
}
Subscriber - User class
import java.util.Date;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
#Entity
#Table(name="users")
public class User {
public User(){
}
#Id#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="userid")
private Integer userid = 0;
#Column(name = "name")
private String name;
#Column(name = "mobile")
private String mobile;
#Column(name = "password")
private String password;
#Column(name = "email")
private String email;
#Column(name = "type")
private String userType;
#OneToOne(fetch=FetchType.EAGER)
#JoinColumn(name="cityid",insertable = false, updatable = false)
private City city;
private String cityid;
#OneToOne(fetch=FetchType.EAGER)
#JoinColumn(name="specialityid",insertable = false, updatable = false)
private Speciality speciality;
private Integer specialityid;
#Column(name="medregno")
private String regno;
#Column(name="refcode")
private String referalcode;
public String getRegno() {
return regno;
}
public void setRegno(String regno) {
this.regno = regno;
}
public String getReferalcode() {
return referalcode;
}
public void setReferalcode(String referalcode) {
this.referalcode = referalcode;
}
#Column(name = "gender")
private String gender;
#Column(name = "active")
private boolean active;
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "updated")
private Date updated;
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "created")
private Date created;
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
User other = (User) obj;
if (userid != other.userid)
return false;
return true;
}
public Integer getUserid() {
return userid;
}
public void setUserid(Integer userid) {
this.userid = userid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getUserType() {
return userType;
}
public void setUserType(String userType) {
this.userType = userType;
}
public City getCity() {
return city;
}
public void setCity(City city) {
this.city = city;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public boolean isActive() {
return active;
}
public void setActive(boolean active) {
this.active = active;
}
public Date getCreated() {
return created;
}
public void setCreated(Date created) {
this.created = created;
}
public Date getUpdated() {
return updated;
}
public void setUpdated(Date updated) {
this.updated = updated;
}
public String getCityid() {
return cityid;
}
public void setCityid(String cityid) {
this.cityid = cityid;
}
public Speciality getSpeciality() {
return speciality;
}
public void setSpeciality(Speciality speciality) {
this.speciality = speciality;
}
public Integer getSpecialityid() {
return specialityid;
}
public void setSpecialityid(Integer specialityid) {
this.specialityid = specialityid;
}
}
booking.getSlot() and booking.getSubscriber() returns null
Please let me know if i miss some configuration while mapping
EDIT1
Added code how the entity is getting loaded
public Booking addBooking(String title,String desc,int slotid,int subscriberid,Session session){
Booking booking = new Booking();
booking.setTitle(title);
booking.setDesc(desc);
booking.setSlotid(slotid);
booking.setSubscriberid(subscriberid);
booking.setCreated(new Date());
Integer bookingid = (Integer) session.save(booking);
session.flush();
Booking bookingEntity = (Booking) session.createQuery("From Booking where id = ?").
setParameter(0, bookingid).list().get(0);
return bookingEntity;
}
I am saving the entity and reloading it.
It's not working because Hibernate is retuning the same instance it has already in its 1st level cache, which doesn't have a reference to any of the 2 other entities.
To fix this, you have to do a session.refresh(booking) rather than executing a query.
In your code :
booking.setSlotid(slotid);
booking.setSubscriberid(subscriberid);
You're just setting Integer values and not objects. Instead of this, try to set objects :
booking.setSlot(new Slot(slotid));
booking.setSubscriber(new Subscriber(subscriberid));
But as #Augusto said, the associations you're having in the session (Slot and Subscriber) are not full objects they contain only their ids. That's why you can't get other fields of these objects.

substract two fields in java each time i add a new record

How can i substract two fieldes using jpa;
i want to get soldejours(class contrat) = soldejours(classe contrat) - dureeassitance (classe assitance)
i have to do this operatio each time i persist a new assistance
here's the class Assistance
package model.entitie;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.SecondaryTable;
#Entity
#NamedQueries({ #NamedQuery(name = "Contrat.findAll", query = "select o from Contrat o") })
public class Contrat implements Serializable {
#Column(length = 4000)
private String annee;
#Column(length = 4000)
private String client;
#Id
#Column(name = "ID_CONTRAT", nullable = false, length = 4000)
private String idContrat;
#Column(length = 4000)
private String information;
#Column(name = "NB_JOURS")
private BigDecimal nbJours;
#Column(name = "SOLDE_JOURS")
private BigDecimal soldeJours;
#OneToMany(mappedBy = "contrat",cascade=CascadeType.PERSIST)
private List<Assistance> assistanceList;
public Contrat() {
}
public Contrat(String annee, String client, String idContrat, String information, BigDecimal nbJours,
BigDecimal soldeJours) {
this.annee = annee;
this.client = client;
this.idContrat = idContrat;
this.information = information;
this.nbJours = nbJours;
this.soldeJours = soldeJours;
}
public String getAnnee() {
return annee;
}
public void setAnnee(String annee) {
this.annee = annee;
}
public String getClient() {
return client;
}
public void setClient(String client) {
this.client = client;
}
public String getIdContrat() {
return idContrat;
}
public void setIdContrat(String idContrat) {
this.idContrat = idContrat;
}
public String getInformation() {
return information;
}
public void setInformation(String information) {
this.information = information;
}
public BigDecimal getNbJours() {
return nbJours;
}
public void setNbJours(BigDecimal nbJours) {
this.nbJours = nbJours;
}
public BigDecimal getSoldeJours() {
return soldeJours;
}
public void setSoldeJours(BigDecimal soldeJours) {
this.soldeJours = soldeJours;
}
public List<Assistance> getAssistanceList() {
return assistanceList;
}
public void setAssistanceList(List<Assistance> assistanceList) {
this.assistanceList = assistanceList;
}
public Assistance addAssistance(Assistance assistance) {
getAssistanceList().add(assistance);
assistance.setContrat(this);
return assistance;
}
public Assistance removeAssistance(Assistance assistance) {
getAssistanceList().remove(assistance);
assistance.setContrat(null);
return assistance;
}
}
and this is the class Assistance
package model.entitie;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
#Entity
#NamedQueries({ #NamedQuery(name = "Assistance.findAll", query = "select o from Assistance o") })
public class Assistance implements Serializable {
private static final long serialVersionUID = 7916354262572083045L;
#Column(length = 4000)
private String client;
#Temporal(TemporalType.DATE)
#Column(name = "DATE_CREATION")
private Date dateCreation;
#Column(name = "DUREE_ASSISTANCE")
private BigDecimal dureeAssistance;
#Column(name = "ETAT_ASSISTANCE", length = 4000)
private String etatAssistance;
#Id
#Column(name = "ID_ASSISTANCE", nullable = false, length = 4000)
private String idAssistance;
#Column(name = "ING_AFF", length = 4000)
private String ingAff;
#Column(name = "OUVERT_PAR", length = 4000)
private String ouvertPar;
#Column(name = "SUJET_ASS", length = 4000)
private String sujetAss;
#ManyToOne(cascade= CascadeType.PERSIST)
#JoinColumn(name = "CONTRAT_ID",updatable =true,insertable =true)
private Contrat contrat;
public Assistance() {
}
public Assistance(String client, Contrat contrat, Date dateCreation, BigDecimal dureeAssistance,
String etatAssistance, String idAssistance, String ingAff, String ouvertPar, String sujetAss) {
this.client = client;
this.contrat = contrat;
this.dateCreation = dateCreation;
this.dureeAssistance = dureeAssistance;
this.etatAssistance = etatAssistance;
this.idAssistance = idAssistance;
this.ingAff = ingAff;
this.ouvertPar = ouvertPar;
this.sujetAss = sujetAss;
}
public String getClient() {
return client;
}
public void setClient(String client) {
this.client = client;
}
public Date getDateCreation() {
return dateCreation;
}
public void setDateCreation(Date dateCreation) {
this.dateCreation = dateCreation;
}
public BigDecimal getDureeAssistance() {
return dureeAssistance;
}
public void setDureeAssistance(BigDecimal dureeAssistance) {
this.dureeAssistance = dureeAssistance;
}
public String getEtatAssistance() {
return etatAssistance;
}
public void setEtatAssistance(String etatAssistance) {
this.etatAssistance = etatAssistance;
}
public String getIdAssistance() {
return idAssistance;
}
public void setIdAssistance(String idAssistance) {
this.idAssistance = idAssistance;
}
public String getIngAff() {
return ingAff;
}
public void setIngAff(String ingAff) {
this.ingAff = ingAff;
}
public String getOuvertPar() {
return ouvertPar;
}
public void setOuvertPar(String ouvertPar) {
this.ouvertPar = ouvertPar;
}
public String getSujetAss() {
return sujetAss;
}
public void setSujetAss(String sujetAss) {
this.sujetAss = sujetAss;
}
public Contrat getContrat() {
return contrat;
}
public void setContrat(Contrat contrat) {
this.contrat = contrat;
}
}
Use Entity listeners and Callback methods.
#PrePersist and #PostPersist
#PreUpdate and #PostUpdate
#PreRemove and #PostRemove
#PostLoad
https://docs.jboss.org/hibernate/entitymanager/3.5/reference/en/html/listeners.html

How to update parent class in a jpa single_table inheritance?

I have a JPA inheritance with a class ContactDTO that is extended by UserDTO with Single_Table strategy:
package ch.ffhs.cryptomess.server.dto;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorType;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.ManyToMany;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import javax.persistence.Version;
import org.springframework.transaction.annotation.Transactional;
#Transactional
#Entity(name = "ch.ffhs.cryptomess.server.dto.ContactDTO")
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(name = "discriminator", discriminatorType = DiscriminatorType.STRING)
#DiscriminatorValue(value = "ContactDTO")
#Table(name = "user", uniqueConstraints = #UniqueConstraint(columnNames = {
"username", "discriminator" }))
public class ContactDTO implements Serializable {
private static final long serialVersionUID = 7706720499337697645L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY, generator = "user_id_seq")
#SequenceGenerator(name = "user_id_seq", allocationSize = 1, initialValue = 10)
#Column(name = "id")
protected Long id;
#Version
protected Long version;
#Column(name = "public_key", length = 255)
protected String publicKey;
#Id
#Column(length = 50, updatable = false)
protected String username;
#ManyToMany(mappedBy = "contacts", targetEntity = CommunicationDTO.class)
protected Set<CommunicationDTO> communications = new HashSet<CommunicationDTO>(
0);
#Override
public boolean equals(final Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
final ContactDTO other = (ContactDTO) obj;
if (username == null) {
if (other.username != null)
return false;
} else if (!username.equals(other.username))
return false;
return true;
}
public Set<CommunicationDTO> getCommunications() {
return communications;
}
public Long getId() {
return id;
}
public String getPublicKey() {
return publicKey;
}
public String getUsername() {
return username;
}
public Long getVersion() {
return version;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((username == null) ? 0 : username.hashCode());
return result;
}
public void setCommunications(final Set<CommunicationDTO> communications) {
this.communications = communications;
}
public void setId(final Long id) {
this.id = id;
}
public void setPublicKey(final String publicKey) {
this.publicKey = publicKey;
}
public void setUsername(final String username) {
this.username = username;
}
public void setVersion(final Long version) {
this.version = version;
}
}
and:
package ch.ffhs.cryptomess.shared.dto;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import org.springframework.transaction.annotation.Transactional;
import ch.ffhs.cryptomess.server.dto.ContactDTO;
import com.google.gwt.view.client.ProvidesKey;
#Transactional
#Entity
#DiscriminatorValue(value = "UserDTO")
public class UserDTO extends ContactDTO implements Serializable {
private static final long serialVersionUID = -3078472527069117428L;
#Column(length = 80)
protected String password;
#Column(name = "is_account_non_expired", columnDefinition = "BIT")
protected boolean isAccountNonExpired;
#Column(name = "is_account_locked", columnDefinition = "BIT")
protected boolean isAccountLocked;
#Column(name = "is_credentials_non_expired", columnDefinition = "BIT")
protected boolean isCredentialsNonExpired;
#Column(name = "is_disabled", columnDefinition = "BIT")
protected boolean isDisabled;
/**
* The key provider that provides the unique ID of a contact.
*/
public static final ProvidesKey<UserDTO> KEY_PROVIDER = new ProvidesKey<UserDTO>() {
#Override
public Object getKey(final UserDTO item) {
return item == null ? null : item.getId();
}
};
public String getPassword() {
return password;
}
public boolean isAccountLocked() {
return isAccountLocked;
}
public boolean isAccountNonExpired() {
return isAccountNonExpired;
}
public boolean isAccountNonLocked() {
return !isAccountLocked;
}
public boolean isCredentialsNonExpired() {
return isCredentialsNonExpired;
}
public boolean isDisabled() {
return isDisabled;
}
public boolean isEnabled() {
return !isDisabled;
}
public void setAccountLocked(final boolean isAccountLocked) {
this.isAccountLocked = isAccountLocked;
}
public void setAccountNonExpired(final boolean isAccountNonExpired) {
this.isAccountNonExpired = isAccountNonExpired;
}
public void setAccountNonLocked(final boolean isAccountNonLocked) {
this.isAccountLocked = !isAccountNonLocked;
}
public void setCredentialsNonExpired(final boolean isCredentialsNonExpired) {
this.isCredentialsNonExpired = isCredentialsNonExpired;
}
public void setDisabled(final boolean isDisabled) {
this.isDisabled = isDisabled;
}
public void setEnabled(final boolean isEnabled) {
this.isDisabled = !isEnabled;
}
public void setPassword(final String password) {
this.password = password;
}
}
If I do a merge or create on an UserDTO-enity, I want the ContactDTO-entity to be created/updated as well in the database. Is there any way to achieve this, without handling both entities seperately?
Thank you for helping!

org.hibernate.QueryException: duplicate association path for #ManyToOne Criteria

I have two classes which has a relationship between them. These are
com.edfx.adb.persist.Activity:
package com.edfx.adb.persist.entity;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.Lob;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Transient;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
import org.hibernate.annotations.NaturalId;
#javax.persistence.Entity
#Table(name = "ACTIVITY")
public class Activity extends Entity {
#Transient
private static final long serialVersionUID = 4741665931936809028L;
private String activityId;
private String activityName;
private String activityDescription;
private Customer customer;
private ActivityType activityType;
private boolean active;
private Double mandays;
private Double price;
private String manager;
private List<Participation> participations;
public Activity() {
super();
}
#NaturalId
#Column(name = "ACTIVITY_ID", nullable = false)
public String getActivityId() {
return activityId;
}
public void setActivityId(String activityId) {
this.activityId = activityId;
}
#Lob
#Column(name = "ACTIVITY_NAME", nullable = false)
public String getActivityName() {
return activityName;
}
public void setActivityName(String activityName) {
this.activityName = activityName;
}
#Lob
#Column(name = "ACTIVITY_DESCRIPTION", nullable = false)
public String getActivityDescription() {
return activityDescription;
}
public void setActivityDescription(String activityDescription) {
this.activityDescription = activityDescription;
}
#ManyToOne
#JoinColumn(name = "CUSTOMER_ID", nullable = false)
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
#ManyToOne
#JoinColumn(name = "ACTIVITY_TYPE_ID", nullable = false)
public ActivityType getActivityType() {
return activityType;
}
public void setActivityType(ActivityType activityType) {
this.activityType = activityType;
}
#Column(name = "ACTIVE", nullable = false)
public boolean isActive() {
return active;
}
public void setActive(boolean active) {
this.active = active;
}
#Column(name = "MANDAYS")
public Double getMandays() {
return mandays;
}
public void setMandays(Double mandays) {
this.mandays = mandays;
}
#Column(name = "PRICE")
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
#Column(name = "CUSTOMER_SIDE_MANAGER")
public String getManager() {
return manager;
}
public void setManager(String manager) {
this.manager = manager;
}
#OneToMany(mappedBy = "activity", fetch = FetchType.LAZY)
#Cascade(CascadeType.SAVE_UPDATE)
public List<Participation> getParticipations() {
return participations;
}
public void setParticipations(List<Participation> participations) {
this.participations = participations;
}
}
com.edfx.adb.persist.ActivityType:
package com.edfx.adb.persist.entity;
import javax.persistence.Column;
import javax.persistence.Table;
import javax.persistence.Transient;
#javax.persistence.Entity
#Table(name = "ACTIVITY_TYPE")
public class ActivityType extends Entity {
#Transient
private static final long serialVersionUID = 2322745769010162801L;
private String parent;
private String name;
private String activityId;
public ActivityType() {
}
#Column(name = "PARENT", nullable = false)
public String getParent() {
return parent;
}
public void setParent(String parent) {
this.parent = parent;
}
#Column(name = "NAME", nullable = false)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Column(name = "ACTIVITY_ID", nullable = false)
public String getActivityId() {
return activityId;
}
public void setActivityId(String activityId) {
this.activityId = activityId;
}
}
Both of them extends com.edfx.adb.persist.entity.Entity:
package com.edfx.adb.persist.entity;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
import javax.persistence.Version;
import org.hibernate.proxy.HibernateProxyHelper;
#MappedSuperclass
public class Entity implements Serializable {
#Transient
private static final long serialVersionUID = 7470288121057059283L;
private Long id;
private Date createTimestamp;
private Date lastUpdateTimestamp;
private Long version;
public Entity() {
super();
}
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "ID", updatable = false, nullable = false, unique = true)
public Long getId() {
return id;
}
#SuppressWarnings("unused")
private void setId(Long id) {
this.id = id;
}
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "CREATE_TIMESTAMP")
public Date getCreateTimestamp() {
return createTimestamp;
}
public void setCreateTimestamp(Date createTimestamp) {
this.createTimestamp = createTimestamp;
}
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "LAST_UPDATE_TIMESTAMP")
public Date getLastUpdateTimestamp() {
return lastUpdateTimestamp;
}
public void setLastUpdateTimestamp(Date lastUpdateTimestamp) {
this.lastUpdateTimestamp = lastUpdateTimestamp;
}
#Version
#Column(name = "VERSION")
public Long getVersion() {
return version;
}
#SuppressWarnings("unused")
private void setVersion(Long version) {
this.version = version;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
return prime * result + ((getId() == null) ? super.hashCode() : getId().hashCode());
}
#Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!getClass().equals(HibernateProxyHelper.getClassWithoutInitializingProxy(obj))) {
return false;
}
final Entity other = (Entity) obj;
if (getId() != other.getId()) {
if (getId() == null) {
return false;
}
if (!getId().equals(other.getId())) {
return false;
}
}
return true;
}
}
Now I am using Primefaces datatable to show a List<Activity> in which I have filtering on the field name of ActivityType. ActivityType is associated with Activity by #ManyToOne relationship.
For filtering the List<Activity> I am using:
Criteria criteria = getSessionFactory().getCurrentSession().createCriteria(Activity.class);
criteria.createCriteria("activityType").add(Restrictions.like("name", value.toString(), MatchMode.START));
I am getting:
null: org.hibernate.QueryException: duplicate association path: activityType
at org.hibernate.loader.criteria.CriteriaQueryTranslator.createAssociationPathCriteriaMap(CriteriaQueryTranslator.java:172) [hibernate-core-4.1.8.Final.jar:4.1.8.Final]
at org.hibernate.loader.criteria.CriteriaQueryTranslator.<init>(CriteriaQueryTranslator.java:111) [hibernate-core-4.1.8.Final.jar:4.1.8.Final]
at org.hibernate.loader.criteria.CriteriaLoader.<init>(CriteriaLoader.java:84) [hibernate-core-4.1.8.Final.jar:4.1.8.Final]
at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1602) [hibernate-core-4.1.8.Final.jar:4.1.8.Final]
at org.hibernate.internal.CriteriaImpl.list(CriteriaImpl.java:374) [hibernate-core-4.1.8.Final.jar:4.1.8.Final]
at com.edfx.adb.dao.ActivityDao.loadActivities(ActivityDao.java:54) [classes:]
at com.edfx.adb.service.ActivityService.loadActivities(ActivityService.java:101) [classes:]
This error is not showing always and never after the first load. After filtering the table for 5-6 time, I am having this error.
I am worried that if the mapping and the criteria is right or not. Any suggestion would be very helpful.
I think you need to provide an alias, so you should change your code this way:
Criteria criteria = getSessionFactory().getCurrentSession().createCriteria(Activity.class);
criteria.createCriteria("activityType", "at")
.add(
Restrictions.like("at.name", value.toString(), MatchMode.START));

Categories