I am new to JPA and I am trying to persist an Entity that will run through 3 stages New, Processing and Completed. I want the below timestamps to be updated accordingly
#Entity
#Table(name = "feedertable")
#JsonIgnoreProperties(value = { "processStatus" })
public class FeederTable {
#Id
#GeneratedValue(strategy= GenerationType.AUTO)
private String id;
private String orderID;
private String status;
#Column(name="CREATEDDATETIME",nullable = false)
private Timestamp createdDateTime;
#Column(name="PROCESSSTATUS",nullable = false)
private String processStatus;
#Column(name="HOSTNAME",nullable = true)
private String hostName;
//#Temporal(TemporalType.TIMESTAMP)
#Column(name="PROCESSINGDATETIME",nullable = false)
private Timestamp processingDateTime;
#Column(name="COMPLETEDDATETIME",nullable = false)
private Timestamp completedDateTime; public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getOrderID() {
return orderID;
}
public void setOrderID(String orderID) {
this.orderID = orderID;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public Timestamp getCreatedDateTime() {
return createdDateTime;
}
public void setCreatedDateTime(Timestamp createdDateTime) {
this.createdDateTime = createdDateTime;
}
public String getProcessStatus() {
return processStatus;
}
public void setProcessStatus(String processStatus) {
this.processStatus = processStatus;
}
public String getHostName() {
return hostName;
}
public void setHostName(String hostName) {
this.hostName = hostName;
}
public Timestamp getProcessingDateTime() {
return processingDateTime;
}
public void setProcessingDateTime(Timestamp processingDateTime) {
this.processingDateTime = processingDateTime;
}
public Timestamp getCompletedDateTime() {
return completedDateTime;
}
public void setCompletedDateTime(Timestamp completedDateTime) {
this.completedDateTime = completedDateTime;
}
#Override
public String toString() {
return "FeederTable{" +
"id='" + id + '\'' +
", orderID='" + orderID + '\'' +
", status='" + status + '\'' +
", createdDateTime=" + createdDateTime +
", processStatus='" + processStatus + '\'' +
", hostName='" + hostName + '\'' +
", processingDateTime=" + processingDateTime +
", completedDateTime=" + completedDateTime +
'}';
}
Persist in JPARepository:
FeederTable feederTable = new FeederTable();
feederTable.setOrderID(orderId);
feederTable.setStatus(status);
feederTable.setCreatedDateTime(new Timestamp(format.getTime())); feederTable.setProcessStatus("New");
feederTable.setHostName(hostname);
feederTable.setCompletedDateTime(null);
feederTable.setProcessingDateTime(null);
repository.save(feederTable);
However when first time the Entity is persisted, All the Timestamps are populated. I want the PROCESSINGDATETIME and COMPLETEDDATETIME as null and populate it only when it reaches corresponding status. Any idea how to acheive it?.
I did a similar thing in my project using #PrePersist and #PreUpdate annotations.
There are other lifecycle hooks that you can use. Read about them here.
MyEntity{
#Temporal(TemporalType.TIMESTAMP)
private Date creationDate;
#Temporal(TemporalType.TIMESTAMP)
private Date updationDate;
#PrePersist
public void onCreate() {
creationDate = new Date();
}
#PreUpdate
public void onUpdate() {
updationDate = new Date();
}
}
Did I understand your question correctly? Is this what you were looking for?
Related
I have multiple Entities mapped to my MySQL database and I can map those entities into relevant objects using Spring's CrudRepository. The three entities are: Snapshot, Market, and Contract
Each Snapshot contains a unique id, a timestamp, and a List of Market objects
Each Market contains a unique primary key id, a nonUniquemarketId, name, url, ...., and List of Contract objects.
Each Contract contains fields regarding pricing information.
The nonUniqueMarketId is an id given by the API I am getting data from. It only occurs once in each Snapshot's List of Market objects
I am wondering if it is possible to get the List of Contracts from a specific Market in List of Markets from a specific Snapshot. That is, if I have a Snapshot's timestamp and a nonUniqueMarketId, is it possible to write a query that looks at all the Snapshots in the DB, gets the one with the given timestamp, then looks at that Snapshot's List of Markets and either gets that Market whose nonUniqueMarketId is given or the List of Contracts field in it?
More generally, I know what Snapshot I want and what Market I want, is it possible to get that specific Market given those two parameters?
Snapshot.java
package com.axlor.predictionassistantanalyzer.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import javax.persistence.*;
import java.util.List;
#Entity
public class Snapshot{
#Id
private Integer hashId;
#JsonProperty("markets")
#ElementCollection(fetch=FetchType.EAGER)
#OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER) //ALL, not persist
private List<Market> markets;
private long timestamp;
public Snapshot(List<Market> markets, long timestamp, Integer hashId) {
this.markets = markets;
this.timestamp = timestamp;
this.hashId = hashId;
}
public Snapshot() {
}
public void setMarkets(List<Market> markets){
this.markets = markets;
}
public List<Market> getMarkets(){
return markets;
}
public long getTimestamp() {
return timestamp;
}
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
public Integer getHashId() {
return hashId;
}
public void setHashId(Integer hashId) {
this.hashId = hashId;
}
#Override
public String toString() {
return "Snapshot{" +
"hashId=" + hashId +
", markets=" + markets +
", timestamp=" + timestamp +
'}';
}
}
Market.java
package com.axlor.predictionassistantanalyzer.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import javax.persistence.*;
import java.util.List;
#Entity
public class Market {
#Id
#GeneratedValue
private Integer marketUniqueID;
#JsonProperty("timeStamp")
private String timeStamp;
#Transient
#JsonProperty("image")
private String image;
#JsonProperty("name")
private String name;
#JsonProperty("id")
private int id;
#Transient
#JsonProperty("shortName")
private String shortName;
#ElementCollection(fetch=FetchType.EAGER)
#OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER) //ALL, not persist
#JsonProperty("contracts")
private List<Contract> contracts;
#JsonProperty("url")
private String url;
#JsonProperty("status")
private String status;
public Market(String timeStamp, String image, String name, int id, String shortName, List<Contract> contracts, String url, String status) {
this.timeStamp = timeStamp;
this.image = image;
this.name = name;
this.id = id;
this.shortName = shortName;
this.contracts = contracts;
this.url = url;
this.status = status;
}
public Market() {
}
public Integer getMarketUniqueID() {
return marketUniqueID;
}
public void setMarketUniqueID(Integer marketUniqueID) {
this.marketUniqueID = marketUniqueID;
}
public String getTimeStamp() {
return timeStamp;
}
public void setTimeStamp(String timeStamp) {
this.timeStamp = timeStamp;
}
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getShortName() {
return shortName;
}
public void setShortName(String shortName) {
this.shortName = shortName;
}
public List<Contract> getContracts() {
return contracts;
}
public void setContracts(List<Contract> contracts) {
this.contracts = contracts;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
#Override
public String toString() {
return "\n\nMarket{" +
"marketUniqueID='" + marketUniqueID + '\'' +
", timeStamp='" + timeStamp + '\'' +
", image='" + image + '\'' +
", name='" + name + '\'' +
", id=" + id +
", shortName='" + shortName + '\'' +
", contracts=" + contracts +
", url='" + url + '\'' +
", status='" + status + '\'' +
"\n}";
}
}
Contract.java
package com.axlor.predictionassistantanalyzer.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Transient;
#Entity
public class Contract {
/*
Why do we need contractUniqueID?:
See explanation in Market.java
Basically, the JsonProperty 'id' field cannot be used as a primary key in the database. We need to create one, so we generate it here.
*/
#Id
#GeneratedValue
private Integer contractUniqueID;
#Transient
#JsonProperty("image")
private String image;
#JsonProperty("lastClosePrice")
private double lastClosePrice;
#JsonProperty("bestBuyNoCost")
private double bestBuyNoCost;
#JsonProperty("bestSellNoCost")
private double bestSellNoCost;
#Transient
#JsonProperty("displayOrder")
private int displayOrder; //not sure what this even is supposed to do lol
#JsonProperty("dateEnd")
private String dateEnd;
#JsonProperty("bestSellYesCost")
private double bestSellYesCost;
#JsonProperty("bestBuyYesCost")
private double bestBuyYesCost;
#JsonProperty("lastTradePrice")
private double lastTradePrice;
#JsonProperty("name")
private String name;
#JsonProperty("id")
private int id;
#Transient
#JsonProperty("shortName")
private String shortName;
#JsonProperty("status")
private String status;
public Contract(String image, double lastClosePrice, double bestBuyNoCost, double bestSellNoCost, int displayOrder, String dateEnd, double bestSellYesCost, double bestBuyYesCost, double lastTradePrice, String name, int id, String shortName, String status) {
this.image = image;
this.lastClosePrice = lastClosePrice;
this.bestBuyNoCost = bestBuyNoCost;
this.bestSellNoCost = bestSellNoCost;
this.displayOrder = displayOrder;
this.dateEnd = dateEnd;
this.bestSellYesCost = bestSellYesCost;
this.bestBuyYesCost = bestBuyYesCost;
this.lastTradePrice = lastTradePrice;
this.name = name;
this.id = id;
this.shortName = shortName;
this.status = status;
}
public Contract() {
}
public Integer getContractUniqueID() {
return contractUniqueID;
}
public void setContractUniqueID(Integer contractUniqueID) {
this.contractUniqueID = contractUniqueID;
}
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
public double getLastClosePrice() {
return lastClosePrice;
}
public void setLastClosePrice(double lastClosePrice) {
this.lastClosePrice = lastClosePrice;
}
public double getBestBuyNoCost() {
return bestBuyNoCost;
}
public void setBestBuyNoCost(double bestBuyNoCost) {
this.bestBuyNoCost = bestBuyNoCost;
}
public double getBestSellNoCost() {
return bestSellNoCost;
}
public void setBestSellNoCost(double bestSellNoCost) {
this.bestSellNoCost = bestSellNoCost;
}
public int getDisplayOrder() {
return displayOrder;
}
public void setDisplayOrder(int displayOrder) {
this.displayOrder = displayOrder;
}
public String getDateEnd() {
return dateEnd;
}
public void setDateEnd(String dateEnd) {
this.dateEnd = dateEnd;
}
public double getBestSellYesCost() {
return bestSellYesCost;
}
public void setBestSellYesCost(double bestSellYesCost) {
this.bestSellYesCost = bestSellYesCost;
}
public double getBestBuyYesCost() {
return bestBuyYesCost;
}
public void setBestBuyYesCost(double bestBuyYesCost) {
this.bestBuyYesCost = bestBuyYesCost;
}
public double getLastTradePrice() {
return lastTradePrice;
}
public void setLastTradePrice(double lastTradePrice) {
this.lastTradePrice = lastTradePrice;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getShortName() {
return shortName;
}
public void setShortName(String shortName) {
this.shortName = shortName;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
#Override
public String toString() {
return "Contract{" +
"contractUniqueID='" + contractUniqueID + '\'' +
", image='" + image + '\'' +
", lastClosePrice=" + lastClosePrice +
", bestBuyNoCost=" + bestBuyNoCost +
", bestSellNoCost=" + bestSellNoCost +
", displayOrder=" + displayOrder +
", dateEnd='" + dateEnd + '\'' +
", bestSellYesCost=" + bestSellYesCost +
", bestBuyYesCost=" + bestBuyYesCost +
", lastTradePrice=" + lastTradePrice +
", name='" + name + '\'' +
", id=" + id +
", shortName='" + shortName + '\'' +
", status='" + status + '\'' +
'}';
}
}
I am trying to develop Web services using Spring boot, Hibernate with database MySql. I am using stored procedure to retrieve the list. The response that i get is not in the form of valid json format.
[
2,
"7598149597",
"2019-09-02T05:10:43.000+0000",
"Digital Marketing",
"2015002",
"Rohit",
"Ramakrishnan",
"C",
"2019-09-02T05:10:43.000+0000"
]
This is how i get the response it should actually be like
{
"id": 2,
"first_name": "Rohit",
"middle_name": "C",
"last_name": "Ramakrishnan",
"employee_id": "2015002",
"designation": "Digital Marketing",
"contact_number": "7598149597",
"create_date": "2019-09-02T05:10:43.000+0000",
"update_date": "2019-09-02T05:10:43.000+0000"
}
The Entity class has toString Method that returns
#Override
public String toString() {
// TODO Auto-generated method stub
return "Employee [id=" + id + ", first_name=" + first_name + ", middle_name=" + middle_name + ", last_name=" + last_name + ", employee_id="+ employee_id + ", designation=" + designation + ", contact_number=" + contact_number + ", create_date=" + create_date + ", update_date=" + update_date +"]";
}
The repository class looks like this
#Repository
public class EmployeeDetailsDao {
#Autowired
EntityManager em;
/**
* Retrieve List
* #return
*/
#SuppressWarnings("unchecked")
public Iterable<EmployeeDetailsSP> getEmployeeList(){
return em.createStoredProcedureQuery("find_all_employees").getResultList();
}
The controller class looks like this
#RestController
#RequestMapping(value = "/sp/emloyee")
public class EmployeeDetailControllerSP {
#Autowired
EmployeeDetailsDao employeeDetailsDao;
private static final Logger log = LoggerFactory.getLogger(EmployeeDetailControllerSP.class);
/**
* Retrieve List
*
* #return
*/
#GetMapping("retrieve_list")
public Iterable<EmployeeDetailsSP> retrieveList() {
log.debug("retrieve_list");
return employeeDetailsDao.getEmployeeList();
}
EmployeeDetailsSP
#Entity
#Table(name = "employee_details")
#NamedStoredProcedureQueries(value = {
#NamedStoredProcedureQuery(name = "FindEmployeeList", procedureName = "find_all_employees"),
#NamedStoredProcedureQuery(name = "FindEmployeeDetails", procedureName = "find_employee_by_id", parameters = {
#StoredProcedureParameter(mode = ParameterMode.IN, name = "emp_id", type = Integer.class) }),
#NamedStoredProcedureQuery(name = "CheckDuplicateEmployee", procedureName = "check_duplicate", parameters = {
#StoredProcedureParameter(mode = ParameterMode.IN, name = "emp_id", type = Integer.class),
#StoredProcedureParameter(mode = ParameterMode.OUT, name = "emp_count", type = Integer.class) }) })
public class EmployeeDetailsSP {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#NotBlank
private String first_name;
private String middle_name;
#NotBlank
private String last_name;
#NotBlank
private String employee_id;
#NotBlank
private String designation;
#NotBlank
private String contact_number;
#Column(nullable = false, updatable = false)
#Temporal(TemporalType.TIMESTAMP)
#CreatedDate
private Date create_date;
#Column(nullable = false)
#Temporal(TemporalType.TIMESTAMP)
#LastModifiedDate
private Date update_date;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getFirst_name() {
return first_name;
}
public void setFirst_name(String first_name) {
this.first_name = first_name;
}
public String getMiddle_name() {
return middle_name;
}
public void setMiddle_name(String middle_name) {
this.middle_name = middle_name;
}
public String getLast_name() {
return last_name;
}
public void setLast_name(String last_name) {
this.last_name = last_name;
}
public String getEmployee_id() {
return employee_id;
}
public void setEmployee_id(String employee_id) {
this.employee_id = employee_id;
}
public String getDesignation() {
return designation;
}
public void setDesignation(String designation) {
this.designation = designation;
}
public String getContact_number() {
return contact_number;
}
public void setContact_number(String contact_number) {
this.contact_number = contact_number;
}
public Date getCreate_date() {
return create_date;
}
public void setCreate_date(Date create_date) {
this.create_date = create_date;
}
public Date getUpdate_date() {
return update_date;
}
public void setUpdate_date(Date update_date) {
this.update_date = update_date;
}
#Override
public String toString() {
// TODO Auto-generated method stub
return "Employee [id=" + id + ", first_name=" + first_name + ", middle_name=" + middle_name + ", last_name=" + last_name + ", employee_id="+ employee_id + ", designation=" + designation + ", contact_number=" + contact_number + ", create_date=" + create_date + ", update_date=" + update_date +"]";
}
I have my entity class called employee and I want to soft delete my entity when I select and press delete button. I can able to select multiple employees as well, So in Java I used List of employee Entities and I want to update whole list into database table if I use merge of entityManager I can able to update only one row i.e only one entity so how do I solve this problem?
Here is some sample code.
#Entity
#Table(name="EmpInfo",schema="Auth")
public class EmpInfo{
#Id
#Column(name="EmpId")
private String userId;
#Column(name="EmailId")
private String emailId;
#Column(name="FirstName")
private String firstName;
#Column(name="LastName")
private String lastName;
#Column(name="MiddleName")
private String middleName;
#Column(name="UserAttributes")
private String userAttributes;
#Column(name="AddedDate")
private Timestamp addedDate;
#Column(name="ModifiedDate")
private Timestamp modifiedDate;
#Column(name="LastLoginDate")
private Timestamp lastLoginDate;
#Column(name="IsDeleted")
private int isDeleted;
#Column(name="AddedBy")
private String addedBy;
#Transient
private String addedByEmailId;
public String getAddedByEmailId() {
return addedByEmailId;
}
public void setAddedByEmailId(String addedByEmailId) {
this.addedByEmailId = addedByEmailId;
}
public EmpInfo() {
// TODO Auto-generated constructor stub
}
public EmpInfo(EmpInfo uInfo){
super();
this.userId=uInfo.userId;
this.emailId=uInfo.emailId;
this.firstName=uInfo.firstName;
this.lastName=uInfo.lastName;
this.middleName=uInfo.middleName;
this.userAttributes=uInfo.userAttributes;
this.addedDate=uInfo.addedDate;
this.lastLoginDate=uInfo.lastLoginDate;
this.modifiedDate=uInfo.modifiedDate;
this.addedBy=uInfo.addedBy;
this.roles=uInfo.roles;
}
public List<RoleName> getRoles() {
return roles;
}
public void setRoles(List<RoleName> roles) {
this.roles = roles;
}
public int getIsDeleted() {
return isDeleted;
}
public void setIsDeleted(int isDeleted) {
this.isDeleted = isDeleted;
}
public Date getAddedDate() {
return addedDate;
}
public void setAddedDate(Timestamp addedDate) {
this.addedDate = addedDate;
}
public Date getModifiedDate() {
return modifiedDate;
}
public void setModifiedDate(Timestamp modifiedDate) {
this.modifiedDate = modifiedDate;
}
public Date getLastLoginDate() {
return lastLoginDate;
}
public void setLastLoginDate(Timestamp lastLoginDate) {
this.lastLoginDate = lastLoginDate;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getEmailId() {
return emailId;
}
public void setEmailId(String emailId) {
this.emailId = emailId;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getMiddleName() {
return middleName;
}
public void setMiddleName(String middleName) {
this.middleName = middleName;
}
public String getUserAttributes() {
return userAttributes;
}
public void setUserAttributes(String userAttributes) {
this.userAttributes = userAttributes;
}
public String getAddedBy() {
return addedBy;
}
public void setAddedBy(String addedBy) {
this.addedBy = addedBy;
}
#Override
public String toString() {
return "EmpInfo [userId=" + userId + ", emailId=" + emailId + ", firstName=" + firstName + ", lastName="
+ lastName + ", middleName=" + middleName + ", userAttributes=" + userAttributes + ", addedDate="
+ addedDate + ", modifiedDate=" + modifiedDate + ", lastLoginDate=" + lastLoginDate + ", isDeleted="
+ isDeleted + ", addedBy=" + addedBy + "]";
}
}
public interface EmpInfoRepository extends JpaRepository<EmpInfo, String> {
}
use this to save list of entities as follows
#Autowired
private EmpInfoRepository empInfoRepository;
empInfoRepository.save(listOfEntity)
Since there is no custom implementation defined, implementation done by SimpleJpaRepository will be used, which will update the entities according to the #Id annotated field
I work on a Java Spring boot app where I get the error of Hot-swap failed and schema change is not implemented and the operation is not supported by the VM. Afterward, the table is truncated and have no data at all.
I have 2 models provided below,
#Entity
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "name")
#NotNull
#NotEmpty
private String name;
#Column(name = "countryName")
#NotNull
#NotEmpty
private String countryName;
#Column(name = "currencyName")
#NotNull
#NotEmpty
private String currencyName;
/*
* total steps is for the keepign the history of the user movement
* */
#Column(name = "totalSteps")
#Min(value = 0L, message = "The value must be positive")
private int totalSteps;
/*
* current steps is for providing the user reward. We will need to set
* it to zero after processing the user payment
* */
#Column(name = "currentSteps")
#Min(value = 0L, message = "The value must be positive")
private int currentSteps;
#OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
private List<RewardList> rewardLists = new ArrayList<>();
public User() {
}
public User(#NotNull #NotEmpty String name, #NotNull #NotEmpty String countryName) {
this.name = name;
this.countryName = countryName;
}
public User(#NotNull #NotEmpty String name, #NotNull #NotEmpty String countryName, #Min(value = 0L, message = "The value must be positive") int totalSteps) {
this.name = name;
this.countryName = countryName;
this.totalSteps = totalSteps;
}
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 String getCountryName() {
return countryName;
}
public String getCurrencyName() {
return currencyName;
}
public void setCurrencyName(String currencyName) {
this.currencyName = currencyName;
}
public void setCountryName(String countryName) {
this.countryName = countryName;
}
public int getTotalSteps() {
return totalSteps;
}
public void setTotalSteps(int totalSteps) {
this.totalSteps = totalSteps;
}
public int getCurrentSteps() {
return currentSteps;
}
public void setCurrentSteps(int currentSteps) {
this.currentSteps = currentSteps;
}
public List<RewardList> getRewardLists() {
return rewardLists;
}
public void setRewardLists(RewardList rl) {
this.rewardLists.add(rl);
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof User)) return false;
User user = (User) o;
return getTotalSteps() == user.getTotalSteps() &&
getCurrentSteps() == user.getCurrentSteps() &&
getId().equals(user.getId()) &&
getName().equals(user.getName()) &&
getCountryName().equals(user.getCountryName()) &&
getRewardLists().equals(user.getRewardLists());
}
#Override
public int hashCode() {
return Objects.hash(getId(), getName(), getCountryName(), getTotalSteps(), getCurrentSteps(), getRewardLists());
}
#Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", countryName='" + countryName + '\'' +
", totalSteps=" + totalSteps +
", currentSteps=" + currentSteps +
'}';
}
}
#Entity
public class RewardList {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "reward")
#Min(value = 0L, message = "The value must be positive")
private double reward;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "user_id", nullable = false)
private User user;
public RewardList() {
}
public RewardList(User user) {
this.user = user;
}
public RewardList(#Min(value = 0L, message = "The value must be positive") double reward) {
this.reward = reward;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public double getReward() {
return reward;
}
public void setReward(double reward) {
this.reward = reward;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof RewardList)) return false;
RewardList list = (RewardList) o;
return Double.compare(list.getReward(), getReward()) == 0 &&
getId().equals(list.getId()) &&
getUser().equals(list.getUser());
}
#Override
public int hashCode() {
return Objects.hash(getId(), getReward(), getUser());
}
#Override
public String toString() {
return "RewardList{" +
"id=" + id +
", reward=" + reward +
", user=" + user +
'}';
}
}
The end-point where I have this issue provided below,
// $ curl -X PUT http://localhost:8080/api/v1/users/calculateReward?userId=1 | jq
#PutMapping("/calculateReward")
public ResponseEntity<Object> calculateReward(#RequestParam("userId") Long userId) {
Optional<User> optional = userService.findById(userId);
if (!optional.isPresent()) {
return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
}
User user = optional.get();
double reward = user.getCurrentSteps() * Parameters.REWARD_PER_STEPS_EUR;
RewardList list = new RewardList();
list.setUser(user);
list.setReward(reward);
rewardListService.save(list);
user.setCurrentSteps(0);
user.setRewardLists(list);
userService.save(user);
JSONObject json = new JSONObject();
double convertionRateToEuro = currencyMap.get(user.getCurrencyName());
double rewardConverted = reward * convertionRateToEuro;
json.put("name", user.getName());
json.put("currency", user.getCurrencyName());
json.put("reward", rewardConverted);
return ResponseEntity.status(HttpStatus.CREATED).body(json);
}
Does anyone know what is going on and can provide a solution?
Thank you.
I find the reason and below I provide a solution. We will need to save the models based on the hierarchy. HotSwap doesn't support adding methods or hierarchy changes as indicated by the error messages. It's the limitation of Java HotSwap, not IntelliJ IDEA. The proper way of code sequence will be,
User user = optional.get();
RewardList list = new RewardList();
list.setUser(user);
list.setReward(reward);
user.setCurrentSteps(0);
user.setRewardLists(list);
// first save the User
userService.save(user);
// Then, save the RewardList as it has one to many relations
rewardListService.save(list);
Using Hibernate 3.6.0
I'm having a real hard time understanding hibernate. I keep running into this issue with lazy initialization exception.
I have an Event entity with a one-to-many relationship with RSVP. When a run a test get back a list of events it works. But when I'm making the call in my controller in order to return it as json, I run into this lazy init error.
This is my event class
#Entity
#Table(name = "EVENT")
public class Event implements Serializable {
#SequenceGenerator(name="event", sequenceName="EVENT_PK_SEQ")
#GeneratedValue(generator="event",strategy=GenerationType.SEQUENCE)
#Id
#Column(name = "EVENT_ID")
private int id;
#Column(name = "DATE_TIME")
private Date date;
#Column(name = "EVENT_NAME")
private String name;
#Column(name = "EVENT_PARTICIPANT_LIMIT")
private int limit;
#Column(name = "EVENT_VISIBILITY")
private boolean visibilty;
#Column(name = "EVENT_LOCATION")
private String location;
#Column(name = "EVENT_DESCRIPTION")
private String description;
#OneToOne(cascade=CascadeType.REMOVE, fetch= FetchType.EAGER)
private User author;
private Date create_date;
#OneToOne(cascade=CascadeType.REMOVE, fetch= FetchType.EAGER)
private EventType eventType;
#OneToOne(cascade=CascadeType.REMOVE, fetch= FetchType.EAGER)
private EventClass eventClass;
#OneToMany(cascade = CascadeType.ALL)
private Set<RSVP> rsvps = new HashSet<RSVP>();
#ManyToMany(mappedBy="event")
private Set<Group> groups = new HashSet<Group>();
public Event(int id, Date date, String name, int limit, boolean visibilty, String location, String description,
User author, Date create_date, EventType eventType, EventClass eventClass) {
super();
this.id = id;
this.date = date;
this.name = name;
this.limit = limit;
this.visibilty = visibilty;
this.location = location;
this.description = description;
this.author = author;
this.create_date = create_date;
this.eventType = eventType;
this.eventClass = eventClass;
}
public Event(){
super();
}
#Override
public String toString() {
return "Event [id=" + id + ", date=" + date + ", name=" + name + ", limit=" + limit + ", visibilty=" + visibilty
+ ", location=" + location + ", description=" + description + ", author=" + author + ", create_date="
+ create_date + ", eventType=" + eventType + ", eventClass=" + eventClass + ", rsvps=" + rsvps
+ ", groups=" + groups + "]";
}
public User getAuthor() {
return author;
}
public void setAuthor(User author) {
this.author = author;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getLimit() {
return limit;
}
public void setLimit(int limit) {
this.limit = limit;
}
public boolean isVisibilty() {
return visibilty;
}
public void setVisibilty(boolean visibilty) {
this.visibilty = visibilty;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Date getCreate_date() {
return create_date;
}
public void setCreate_date(Date create_date) {
this.create_date = create_date;
}
public EventType getEventType() {
return eventType;
}
public void setEventType(EventType eventType) {
this.eventType = eventType;
}
public EventClass getEventClass() {
return eventClass;
}
public void setEventClass(EventClass eventClass) {
this.eventClass = eventClass;
}
public Set<RSVP> getRsvps() {
return rsvps;
}
public void setRsvps(Set<RSVP> rsvps) {
this.rsvps = rsvps;
}
public Set<Group> getGroups() {
return groups;
}
public void setGroups(Set<Group> groups) {
this.groups = groups;
}
}
My RSVP
#Entity
#Table(name="RSVP")
public class RSVP {
#Id
#Column(name="RSVP_ID")
#SequenceGenerator(name="rsvp", sequenceName="RSVP_PK_SEQ")
#GeneratedValue(generator="rsvp",strategy=GenerationType.SEQUENCE)
private int rsvpId;
#OneToOne(cascade=CascadeType.REMOVE, fetch= FetchType.EAGER)
#JoinColumn(name="STATUS_ID")
private RSVPStatus status;
#ManyToOne(cascade=CascadeType.REMOVE)
#JoinColumn(name="USER_ID")
private User user;
#ManyToOne(fetch=FetchType.EAGER)
#JoinColumn(name="EVENT_ID")
private Event event;
public RSVP(int rsvpId, RSVPStatus status, User user, Event event) {
super();
this.rsvpId = rsvpId;
this.status = status;
this.user = user;
this.event = event;
}
public RSVP() {
}
#Override
public String toString() {
return "RSVP [rsvpId=" + rsvpId + ", status=" + status + ", user=" + user + ", event=" + event + "]";
}
public int getRsvpId() {
return rsvpId;
}
public void setRsvpId(int rsvpId) {
this.rsvpId = rsvpId;
}
public RSVPStatus getStatus() {
return status;
}
public void setStatus(RSVPStatus status) {
this.status = status;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public Event getEvent() {
return event;
}
public void setEvent(Event event) {
this.event = event;
}
}
MY controller
public class MyController {
private static SessionFactory sf = HibernateUtils.getSessionFactory();
private DataFacade df = new DataFacade(sf);
#RequestMapping(value="home", method=RequestMethod.GET,
consumes= MediaType.APPLICATION_JSON_VALUE)
#ResponseBody
public ResponseEntity<List<Event>> getUserCal(){
DataFacade df = new DataFacade(sf);
List<Event> events= df.getAllEventsByAuthor(1);
for(Event e:events){
System.out.println(e);
}
return new ResponseEntity<List<Event>>(events,HttpStatus.OK);
}
}
Your RSVP collection is fetched lazily. (If you don't specify a fetch type, the default is lazy). You need to change it to eager if you are planning to access it after the Hibernate session is closed:
#OneToMany(cascade = CascadeType.ALL, fetch= FetchType.EAGER)
private Set<RSVP> rsvps = new HashSet<RSVP>();