I work with a Spring boot app and have the following entities in the App,
#Entity
public class IpAddress {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "IP_ADDR_ID")
private Long id;
#Column(name = "IP_ADDRESS")
#NotEmpty
private String address;
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(name = "IP_ADDR_STATUS",
joinColumns = {
#JoinColumn(name = "IP_ADDRESS_ID", referencedColumnName = "IP_ADDR_ID")
},
inverseJoinColumns = {
#JoinColumn(name = "STATUS_ID", referencedColumnName = "S_ID")
})
private List<HttpInfoMessage> httpInfoMessages = new ArrayList<>();
public IpAddress() {
}
public IpAddress(String address) {
this.address = address;
}
public IpAddress(String address, List<HttpInfoMessage> httpInfoMessages) {
this.address = address;
this.httpInfoMessages = httpInfoMessages;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public List<HttpInfoMessage> getHttpInfoMessages() {
return httpInfoMessages;
}
public void setHttpInfoMessages(List<HttpInfoMessage> httpInfoMessages) {
this.httpInfoMessages = httpInfoMessages;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof IpAddress)) return false;
IpAddress ipAddress = (IpAddress) o;
if (!getId().equals(ipAddress.getId())) return false;
return getAddress().equals(ipAddress.getAddress());
}
#Override
public int hashCode() {
int result = getId().hashCode();
result = 31 * result + getAddress().hashCode();
return result;
}
#Override
public String toString() {
return "IpAddress{" +
"id=" + id +
", address='" + address + '\'' +
'}';
}
}
And, I have the second entity here,
#Entity
public class HttpInfoMessage {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "S_ID")
private Long sId;
#Column(name = "STATUS_ID")
private Long statusId;
#Column(name = "STATUS")
#NotEmpty
private String status;
public HttpInfoMessage() {
}
public HttpInfoMessage(String status) {
this.status = status;
}
public HttpInfoMessage(Long statusId, String status) {
this.statusId = statusId;
this.status = status;
}
public HttpInfoMessage(Long statusId, String status, List<IpAddress> ipAddresses) {
this.statusId = statusId;
this.status = status;
this.ipAddresses = ipAddresses;
}
public Long getsId() {
return sId;
}
public void setsId(Long sId) {
this.sId = sId;
}
public Long getStatusId() {
return statusId;
}
public void setStatusId(Long statusId) {
this.statusId = statusId;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
#JsonIgnore
#ManyToMany(cascade = CascadeType.ALL, mappedBy = "httpInfoMessages")
private List<IpAddress> ipAddresses = new ArrayList<>();
public List<IpAddress> getIpAddresses() {
return ipAddresses;
}
public void setIpAddresses(List<IpAddress> ipAddresses) {
this.ipAddresses = ipAddresses;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof HttpInfoMessage)) return false;
HttpInfoMessage httpInfoMessage1 = (HttpInfoMessage) o;
if (!getStatusId().equals(httpInfoMessage1.getStatusId())) return false;
return getStatus().equals(httpInfoMessage1.getStatus());
}
#Override
public int hashCode() {
int result = getStatusId().hashCode();
result = 31 * result + getStatus().hashCode();
return result;
}
#Override
public String toString() {
return "Status{" +
"statusId=" + statusId +
", status='" + status + '\'' +
'}';
}
}
When I persist a List in the database, It creates 3 tables,
The Ip Address table, namely ip_address,
The Http message info table, namely http_info_message,
And, the last table namely ip_addr_status maps the IP address ID with the Http Info Message ID,
I guess it good to show the formation of the IpAddress entity,
List<HttpInfoMessage> httpInfoMessages = new ArrayList<>();
for(int i=1;i<=10;i++){
HttpInfoMessage httpInfoMessage = new HttpInfoMessage(404L, "FORBIDDEN_WEB_PAGE");
httpInfoMessages.add(httpInfoMessage);
}
Then add the Http messages to the IpAddress,
IpAddress ip = new IpAddress("177.132.239.67", httpInfoMessages)
In the ip_addr_status table, I would like to add 3 more columns from the fields of address, statusId and status.
How to do that?
If nothing else succeeds you can create this join table as separate entity. See accepted answer:
Mapping many-to-many association table with extra column(s)
Related
I can’t set the discipline values for my semester, when I work out the controller, I get all the data I need, but I can’t connect them, can anyone tell me with an experienced eye what is the reason? I am getting this kind of error:
Request processing failed; nested exception is
org.hibernate.property.access.spi.PropertyAccessException: Error accessing field [private int com.kushnirmark.spring.project.entity.Discipline.id] by reflection for persistent property [com.kushnirmark.spring.project.entity.Discipline#id] : Higher mathematics
Here is my entity Semestr:
package com.kushnirmark.spring.project.entity;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
#Entity
#Table(name = "semestr")
public class Semestr {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int id;
#Column(name = "name")
private String name;
#Column(name = "duration")
private String duration;
#Column(name = "status")
private boolean status = true;
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(name = "semestr_discipline",
joinColumns = #JoinColumn(name = "id_semestr"),
inverseJoinColumns = #JoinColumn(name = "id_discipline")
)
private List<Discipline> disciplineList;
public void addDisciplineToSemester(Discipline discipline) {
if (disciplineList == null) {
disciplineList = new ArrayList<>();
}
disciplineList.add(discipline);
}
public Semestr() {
}
public Semestr(int id, String name, String duration, boolean status) {
this.id = id;
this.name = name;
this.duration = duration;
this.status = status;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDuration() {
return duration;
}
public void setDuration(String duration) {
this.duration = duration;
}
public boolean isStatus() {
return status;
}
public void setStatus(boolean status) {
this.status = status;
}
public List<Discipline> getDisciplineList() {
return disciplineList;
}
public void setDisciplineList(List<Discipline> disciplineList) {
this.disciplineList = disciplineList;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Semestr semestr = (Semestr) o;
if (id != semestr.id) return false;
if (status != semestr.status) return false;
if (name != null ? !name.equals(semestr.name) : semestr.name != null) return false;
return duration != null ? duration.equals(semestr.duration) : semestr.duration == null;
}
#Override
public int hashCode() {
int result = id;
result = 31 * result + (name != null ? name.hashCode() : 0);
result = 31 * result + (duration != null ? duration.hashCode() : 0);
result = 31 * result + (status ? 1 : 0);
return result;
}
#Override
public String toString() {
return "Semestr{" +
"id=" + id +
", name='" + name + '\'' +
", duration='" + duration + '\'' +
", status=" + status +
'}';
}
}
Controller :
#RequestMapping("/saveNewSemester")
public String saveNewSemester(#ModelAttribute("semestr") Semestr semestr,
#RequestParam(name = "AllDiscipline") String[] AllDiscipline,
Model model) {
List<Integer> list = Arrays.stream(AllDiscipline).map(Integer::parseInt).collect(Collectors.toList());
List<Discipline> disciplineSemestrList = service.getDisciplineList(list);
semestr.setDisciplineList(disciplineSemestrList);
service.saveNewSemester(semestr);
return "redirect:/semestr";
}
Here is my entity Discipline :
package com.kushnirmark.spring.project.entity;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
#Entity
#Table(name = "discipline")
public class Discipline {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int id;
#Column(name = "discipline")
private String discipline;
#Column(name = "status")
private boolean status = true;
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(name = "semestr_discipline",
joinColumns = #JoinColumn(name = "id_discipline"),
inverseJoinColumns = #JoinColumn(name = "id_semestr")
)
private List<Semestr> semestrList;
public void addSemesterToDiscipline(Semestr semestr) {
if (semestrList == null) {
semestrList = new ArrayList<>();
}
semestrList.add(semestr);
}
public Discipline() {
}
public Discipline(int id, String discipline, boolean status) {
this.id = id;
this.discipline = discipline;
this.status = status;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getDiscipline() {
return discipline;
}
public void setDiscipline(String discipline) {
this.discipline = discipline;
}
public boolean isStatus() {
return status;
}
public void setStatus(boolean status) {
this.status = status;
}
public List<Semestr> getSemestrList() {
return semestrList;
}
public void setSemestrList(List<Semestr> semestrList) {
this.semestrList = semestrList;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Discipline that = (Discipline) o;
return id == that.id &&
status == that.status &&
Objects.equals(discipline, that.discipline);
}
#Override
public int hashCode() {
return Objects.hash(id, discipline, status);
}
#Override
public String toString() {
return "Discipline{" +
"id=" + id +
", discipline='" + discipline + '\'' +
", status=" + status +
'}';
}
}
I have this error in spring boot:
attempted to assign id from null one-to-one property [com.endoorment.models.entity.ActionLang.action]
My code:
#Embeddable
public class ActionLangId implements Serializable {
private static final long serialVersionUID = 1 L;
#NotNull
#Column(name = "actions_id")
private Integer actionId;
#NotNull
#Column(name = "langs_id")
private Integer langId;
public ActionLangId() {}
public ActionLangId(Integer actionId, Integer langId) {
super();
this.actionId = actionId;
this.langId = langId;
}
public Integer getActionId() {
return actionId;
}
public void setActionId(Integer actionId) {
this.actionId = actionId;
}
public Integer getLangId() {
return langId;
}
public void setLangId(Integer langId) {
this.langId = langId;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass())
return false;
ActionLangId that = (ActionLangId) o;
return Objects.equals(actionId, that.actionId) &&
Objects.equals(langId, that.langId);
}
#Override
public int hashCode() {
return Objects.hash(actionId, langId);
}
}
#Entity
#Table(name = "actions_langs")
public class ActionLang {
#EmbeddedId
private ActionLangId id;
#ManyToOne(fetch = FetchType.LAZY)
#MapsId("actionId")
#JoinColumn(name = "actions_id")
private Action action;
#ManyToOne(fetch = FetchType.LAZY)
#MapsId("langId")
#JoinColumn(name = "langs_id")
private Lang lang;
#NotNull(message = "null")
#Size(max = 45, message = "short")
private String name;
public ActionLang() {}
public ActionLang(ActionLangId actionlangid, String name) {
this.id = actionlangid;
this.name = name;
}
public ActionLangId getId() {
return id;
}
public void setId(ActionLangId id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public String toString() {
return "ActionLang [id=" + id + ", name=" + name + "]";
}
}
Service:
#Transactional
public ActionLang saveAction(Integer idlang, String name) {
Integer id = actionRepository.findActionId();
Action action = new Action(id);
actionRepository.save(action);
ActionLang actionlang = new ActionLang(new ActionLangId(id, idlang), name);
actionlangRepository.save(actionlang);
return actionlang;
}
Structure actionlang: {
"id": {
"actionId": 2,
"langId": 1
},
"name": "hkjhlhklhkllñkñl"
Thanks
My solution,
Entity Action:
#Entity
#Table(name = "actions")
public class Action {
#Id
private Integer id;
#OneToMany(mappedBy = "action")
private List<ActionLang> actionlang = new ArrayList<>();
public Action() { }
public Action(Integer id) {this.id = id;}
public Integer getId() {return id;}
public void setId(Integer id) {this.id = id;}
public List<ActionLang> getActionLang() {return actionlang;}
public void addActionLang(ActionLang actionlang) {
this.actionlang.add(actionlang);
}
public void removeActionLang(ActionLang actionlang) {
this.actionlang.remove(actionlang);
}
#Override
public String toString() {return "id: " + id ;}
}
Entity ActionLang,
#Entity
#Table(name = "actions_langs")
public class ActionLang {
#EmbeddedId
private ActionLangId id;
#ManyToOne(fetch = FetchType.LAZY)
#MapsId("actionId")
#JoinColumn(name = "actions_id", nullable = false)
#OnDelete(action = OnDeleteAction.CASCADE)
#JsonIgnore
private Action action;
#ManyToOne(fetch = FetchType.LAZY)
#MapsId("langId")
#JoinColumn(name = "langs_id", nullable = false)
#OnDelete(action = OnDeleteAction.CASCADE)
#JsonIgnore
private Lang lang;
#NotNull(message="null")
#Size(max = 45, message="short")
private String name;
public ActionLang() {}
public ActionLang(ActionLangId actionlangid, String name) {
this.id = actionlangid;
this.name = name;
}
public ActionLangId getId() {return id;}
public String getName() {return name;}
public void setName(String name) {this.name = name;}
public void setId(ActionLangId id) {this.id = id;}
public Action getAction() {return action;}
public void setAction(Action action) {this.action = action;}
public Lang getLang() {return lang;}
public void setLang(Lang lang) { this.lang = lang; }
#Override
public String toString() {return "ActionLang [id=" + id + ", name=" + name + "]"; }
}
Service
#Component
public class ActionDAOService {
#Autowired
private IActionDao actionRepository;
#Autowired
private IActionLangDao actionlangRepository;
#Transactional
public Action saveAction(Integer idlang, String name){
Lang lang = new Lang();
lang.setId(idlang);
Integer id = actionRepository.findActionId();
if(id == null) {
id=(Integer) 1;
}
Action action = new Action(id);
actionRepository.save(action);
ActionLang actionlang = new ActionLang(new ActionLangId(id, idlang),name);
action.addActionLang(actionlang);
actionlang.setAction(action);
actionlang.setLang(lang);
actionlangRepository.save(actionlang);
return action;
}
}
I have modified service and I have the same error
#Transactional
public Action saveAction(Integer idlang, String name){
Integer id = actionRepository.findActionId();
if(id == null) {id=(Integer) 1;}
Action action = new Action(id);
ActionLang actionlang = new ActionLang(new ActionLangId(id, idlang),name);
action.getActionlang().add(actionlang);
actionRepository.save(action);
return action;
}
And the structure of action is this:
{
"id": 2,
"actionlang": [
{
"id": {
"actionId": 2,
"langId": 1
},
"name": "hkjhlhklhkllñkñl"
}
]
}
Entity action
#Entity
#Table(name = "actions")
public class Action {
#Id
private Integer id;
#OneToMany(mappedBy = "action", cascade = CascadeType.ALL, orphanRemoval = true)
private List<ActionLang> actionlang = new ArrayList<>();
public Action() {
}
public Action(Integer id) {
super();
this.id = id;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public List<ActionLang> getActionlang() {
return actionlang;
}
#Override
public String toString() {
return "Action [id=" + id + ", actionlang=" + actionlang + ", getId()=" + getId() + ", getActionlang()="
+ getActionlang() + ", getClass()=" + getClass() + ", hashCode()=" + hashCode() + ", toString()="
+ super.toString() + "]";
}
}
I'm using JHipster and I'm running the following curl command:
POST/api/gang-users
with body:
{
"role": "member",
"gang": "3",
"user": "1"
}
but I get the following error:
JSON parse error: Cannot construct instance of
com.getgreetapp.greetapp.domain.User (although at least one Creator
exists): no String-argument constructor/factory method to deserialize
from String value ('1'); nested exception is
com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot
construct instance of com.getgreetapp.greetapp.domain.User (although
at least one Creator exists): no String-argument constructor/factory
method to deserialize from String value ('1')\n at [Source:
(PushbackInputStream); line: 4, column: 10] (through reference chain:
com.getgreetapp.greetapp.domain.GangUser[\"user\"])
GangUserResource createGangUser
#PostMapping("/gang-users")
#Timed
public ResponseEntity<GangUser> createGangUser(#Valid #RequestBody GangUser gangUser) throws URISyntaxException {
log.debug("REST request to save GangUser : {}", gangUser);
if (gangUser.getId() != null) {
throw new BadRequestAlertException("A new gangUser cannot already have an ID", ENTITY_NAME, "idexists");
}
User user = userRepository.findById(gangUser.getUser());
GangUser result = gangUserRepository.save(gangUser);
return ResponseEntity.created(new URI("/api/gang-users/" + result.getId()))
.headers(HeaderUtil.createEntityCreationAlert(ENTITY_NAME, result.getId().toString()))
.body(result);
}
GangUser
package com.getgreetapp.greetapp.domain;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import javax.persistence.*;
import javax.validation.constraints.*;
import java.io.Serializable;
import java.util.Objects;
/**
* A GangUser.
*/
#Entity
#Table(name = "gang_user")
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class GangUser implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#NotNull
#Column(name = "jhi_role", nullable = false)
private String role;
#ManyToOne
private Gang gang;
#ManyToOne
private User user;
public GangUser() {
}
public GangUser(String role, Gang gang, User user)
{
this.role = role;
this.gang = gang;
this.user = user;
}
// jhipster-needle-entity-add-field - JHipster will add fields here, do not remove
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getRole() {
return role;
}
public GangUser role(String role) {
this.role = role;
return this;
}
public void setRole(String role) {
this.role = role;
}
public Gang getGang() {
return gang;
}
public GangUser gang(Gang gang) {
this.gang = gang;
return this;
}
public void setGang(Gang gang) {
this.gang = gang;
}
public User getUser() {
return user;
}
public GangUser user(User user) {
this.user = user;
return this;
}
public void setUser(User user) {
this.user = user;
}
// jhipster-needle-entity-add-getters-setters - JHipster will add getters and setters here, do not remove
#Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
GangUser gangUser = (GangUser) o;
if (gangUser.getId() == null || getId() == null) {
return false;
}
return Objects.equals(getId(), gangUser.getId());
}
#Override
public int hashCode() {
return Objects.hashCode(getId());
}
#Override
public String toString() {
return "GangUser{" +
"id=" + getId() +
", role='" + getRole() + "'" +
"}";
}
}
User
package com.getgreetapp.greetapp.domain;
import com.getgreetapp.greetapp.config.Constants;
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.annotations.BatchSize;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import javax.validation.constraints.Email;
import javax.persistence.*;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Locale;
import java.util.Objects;
import java.util.Set;
import java.time.Instant;
/**
* A user.
*/
#Entity
#Table(name = "jhi_user")
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class User extends AbstractAuditingEntity implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#NotNull
#Pattern(regexp = Constants.LOGIN_REGEX)
#Size(min = 1, max = 50)
#Column(length = 50, unique = true, nullable = false)
private String login;
#JsonIgnore
#NotNull
#Size(min = 60, max = 60)
#Column(name = "password_hash", length = 60, nullable = false)
private String password;
#Size(max = 50)
#Column(name = "first_name", length = 50)
private String firstName;
#Size(max = 50)
#Column(name = "last_name", length = 50)
private String lastName;
#Email
#Size(min = 5, max = 254)
#Column(length = 254, unique = true)
private String email;
#NotNull
#Column(nullable = false)
private boolean activated = false;
#Size(min = 2, max = 6)
#Column(name = "lang_key", length = 6)
private String langKey;
#Size(max = 256)
#Column(name = "image_url", length = 256)
private String imageUrl;
#Size(max = 20)
#Column(name = "activation_key", length = 20)
#JsonIgnore
private String activationKey;
#Size(max = 20)
#Column(name = "reset_key", length = 20)
#JsonIgnore
private String resetKey;
#Column(name = "reset_date")
private Instant resetDate = null;
#JsonIgnore
#ManyToMany
#JoinTable(
name = "jhi_user_authority",
joinColumns = {#JoinColumn(name = "user_id", referencedColumnName = "id")},
inverseJoinColumns = {#JoinColumn(name = "authority_name", referencedColumnName = "name")})
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
#BatchSize(size = 20)
private Set<Authority> authorities = new HashSet<>();
public User() {}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getLogin() {
return login;
}
// Lowercase the login before saving it in database
public void setLogin(String login) {
this.login = StringUtils.lowerCase(login, Locale.ENGLISH);
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
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 getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getImageUrl() {
return imageUrl;
}
public void setImageUrl(String imageUrl) {
this.imageUrl = imageUrl;
}
public boolean getActivated() {
return activated;
}
public void setActivated(boolean activated) {
this.activated = activated;
}
public String getActivationKey() {
return activationKey;
}
public void setActivationKey(String activationKey) {
this.activationKey = activationKey;
}
public String getResetKey() {
return resetKey;
}
public void setResetKey(String resetKey) {
this.resetKey = resetKey;
}
public Instant getResetDate() {
return resetDate;
}
public void setResetDate(Instant resetDate) {
this.resetDate = resetDate;
}
public String getLangKey() {
return langKey;
}
public void setLangKey(String langKey) {
this.langKey = langKey;
}
public Set<Authority> getAuthorities() {
return authorities;
}
public void setAuthorities(Set<Authority> authorities) {
this.authorities = authorities;
}
#Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
User user = (User) o;
return !(user.getId() == null || getId() == null) && Objects.equals(getId(), user.getId());
}
#Override
public int hashCode() {
return Objects.hashCode(getId());
}
#Override
public String toString() {
return "User{" +
"login='" + login + '\'' +
", firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
", email='" + email + '\'' +
", imageUrl='" + imageUrl + '\'' +
", activated='" + activated + '\'' +
", langKey='" + langKey + '\'' +
", activationKey='" + activationKey + '\'' +
"}";
}
}
Gang
package com.getgreetapp.greetapp.domain;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import javax.persistence.*;
import javax.validation.constraints.*;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Objects;
/**
* A Gang.
*/
#Entity
#Table(name = "gang")
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class Gang implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#NotNull
#Column(name = "name", nullable = false)
private String name;
#NotNull
#Column(name = "description", nullable = false)
private String description;
#NotNull
#Column(name = "longitude", precision = 10, scale = 2, nullable = false)
private BigDecimal longitude;
#NotNull
#Column(name = "latitude", precision = 10, scale = 2, nullable = false)
private BigDecimal latitude;
#NotNull
#Column(name = "membership_approval", nullable = false)
private String membershipApproval;
#NotNull
#Column(name = "privacy", nullable = false)
private String privacy;
public Gang() {}
// jhipster-needle-entity-add-field - JHipster will add fields here, do not remove
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public Gang name(String name) {
this.name = name;
return this;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public Gang description(String description) {
this.description = description;
return this;
}
public void setDescription(String description) {
this.description = description;
}
public BigDecimal getLongitude() {
return longitude;
}
public Gang longitude(BigDecimal longitude) {
this.longitude = longitude;
return this;
}
public void setLongitude(BigDecimal longitude) {
this.longitude = longitude;
}
public BigDecimal getLatitude() {
return latitude;
}
public Gang latitude(BigDecimal latitude) {
this.latitude = latitude;
return this;
}
public void setLatitude(BigDecimal latitude) {
this.latitude = latitude;
}
public String getMembershipApproval() {
return membershipApproval;
}
public Gang membershipApproval(String membershipApproval) {
this.membershipApproval = membershipApproval;
return this;
}
public void setMembershipApproval(String membershipApproval) {
this.membershipApproval = membershipApproval;
}
public String getPrivacy() {
return privacy;
}
public Gang privacy(String privacy) {
this.privacy = privacy;
return this;
}
public void setPrivacy(String privacy) {
this.privacy = privacy;
}
// jhipster-needle-entity-add-getters-setters - JHipster will add getters and setters here, do not remove
#Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Gang gang = (Gang) o;
if (gang.getId() == null || getId() == null) {
return false;
}
return Objects.equals(getId(), gang.getId());
}
#Override
public int hashCode() {
return Objects.hashCode(getId());
}
#Override
public String toString() {
return "Gang{" +
"id=" + getId() +
", name='" + getName() + "'" +
", description='" + getDescription() + "'" +
", longitude=" + getLongitude() +
", latitude=" + getLatitude() +
", membershipApproval='" + getMembershipApproval() + "'" +
", privacy='" + getPrivacy() + "'" +
"}";
}
}
In my humble opinion, there are a couple of things to check.
First, it isn't recommended to use the same object to store data in your database and response a request. The data object could be GangUser, User and Gang, while the response objects GangUserApi, UserApi, and GangApi. With this approach, you'll be able to amend a layer without modifying another.
Second, your service is expecting a GangUser with a User inside. The same User Object that you use to store it in the database. You're just sending a String ("1") instead of an object there.
A quick solution could be modifying the JSON:
{
"role": "member",
"gang": "3",
"user": {
"id":"1"
}
}
But I would like to know if you understand what was going on. That is more important than just give you a quick solution.
Cheers.
I work with a Java/ Spring web-app and it contains 3 entities. The MySQL schema is provided below,
As we see, there are 3 entities and respective table of users, status and wallet_info. The 3 entities are provided below,
#Entity
#Table(name = "wallet_info")
public class WalletInfo {
#Id
#Column(name = "id", unique = true, nullable = false)
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#NotNull
#Column(name = "code")
private String code;
#NotNull
#Column(name = "address")
private String address;
#NotNull
#Column(name = "currency")
private String currency;
#OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy = "wallet_id")
Set<Status> statuses = new HashSet<>(0);
public Long getId() {
return id;
}
public WalletInfo(#NotNull String name, #NotNull String address, #NotNull String currency) {
this.code = name;
this.address = address;
this.currency = currency;
}
public WalletInfo(#NotNull String name, #NotNull String address) {
this.code = name;
this.address = address;
}
public WalletInfo() {
}
public void setId(Long id) {
this.id = id;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getCurrency() {
return currency;
}
public void setCurrency(String currency) {
this.currency = currency;
}
public Set<Status> getStatuses() {
return statuses;
}
public void setStatuses(Set<Status> statuses) {
this.statuses = statuses;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof WalletInfo)) return false;
WalletInfo that = (WalletInfo) o;
if (!getId().equals(that.getId())) return false;
if (!getCode().equals(that.getCode())) return false;
if (!getAddress().equals(that.getAddress())) return false;
return getCurrency().equals(that.getCurrency());
}
#Override
public int hashCode() {
int result = getId().hashCode();
result = 31 * result + getCode().hashCode();
result = 31 * result + getAddress().hashCode();
result = 31 * result + getCurrency().hashCode();
return result;
}
#Override
public String toString() {
return "WalletInfo{" +
"id=" + id +
", code='" + code + '\'' +
", address='" + address + '\'' +
", currency='" + currency + '\'' +
'}';
}
}
#Entity
#Table(name = "users")
public class User {
#Id
#Column(name = "id", unique = true, nullable = false)
#NotNull
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#NotNull
#Column(name = "name")
#Size(min = 5, max = 45, message = "Name must be between 5 and 45 characters.")
private String name;
#OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "user_id")
Set<Status> statuses = new HashSet<Status>(0);
public User() {
}
public User(int id, String name) {
super();
this.id = id;
this.name = name;
}
public User(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<Status> getStatuses() {
return statuses;
}
public void setStatuses(Set<Status> statuses) {
this.statuses = statuses;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof User)) return false;
User user = (User) o;
if (getId() != user.getId()) return false;
return getName().equals(user.getName());
}
#Override
public int hashCode() {
int result = getId();
result = 31 * result + getName().hashCode();
return result;
}
#Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
#Entity
#Table(name = "status")
public class Status {
#Id
#Column(name = "id", unique = true, nullable = false)
#NotNull
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#NotNull
#Column(name = "balance")
private float balance;
#NotNull
#Column(name = "address")
#Size(min = 5, max = 90, message = "Address must be between 5 and 90 characters.")
private String address;
#NotNull
#Column(name = "transaction")
#Size(min = 5, max = 90, message = "Transaction history must be between 5 and 90 characters.")
private String transaction;
#NotNull
#Column(name = "user_id")
#JoinColumn(table = "user", name = "id", nullable = false)
private int user_id;
#NotNull
#JoinColumn(name = "id", table = "wallet_id", nullable = false)
#Column(name = "wallet_id")
private long wallet_id;
public Status() {
}
public Status(float balance, String transaction, String address, int user_id) {
this.user_id = user_id;
this.balance = balance;
this.address = address;
this.transaction = transaction;
}
public Status(int id, int user_id, float balance, String address, String transaction) {
super();
this.id = id;
this.user_id = user_id;
this.balance = balance;
this.address = address;
this.transaction = transaction;
}
public int getId() {
return id;
}
public int getUser_id() {
return user_id;
}
public float getBalance() {
return balance;
}
public String getAddress() {
return address;
}
public String getTransaction() {
return transaction;
}
public long getWallet_id() {
return wallet_id;
}
public void setId(int id) {
this.id = id;
}
public void setUser_id(int user_id) {
this.user_id = user_id;
}
public void setBalance(float balance) {
this.balance = balance;
}
public void setAddress(String address) {
this.address = address;
}
public void setTransaction(String transaction) {
this.transaction = transaction;
}
public void setWallet_id(long wallet_id) {
this.wallet_id = wallet_id;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Status)) return false;
Status status = (Status) o;
if (id != status.id) return false;
if (user_id != status.user_id) return false;
if (Float.compare(status.balance, balance) != 0) return false;
if (!address.equals(status.address)) return false;
return transaction.equals(status.transaction);
}
#Override
public int hashCode() {
int result = id;
result = 31 * result + user_id;
result = 31 * result + (balance != +0.0f ? Float.floatToIntBits(balance) : 0);
result = 31 * result + address.hashCode();
result = 31 * result + transaction.hashCode();
return result;
}
#Override
public String toString() {
return "Status{" +
"id=" + id +
", user_id=" + user_id +
", balance=" + balance +
", address='" + address + '\'' +
", transaction='" + transaction + '\'' +
'}';
}
}
When I command using the cURL curl -X GET http://localhost:8080/rest/wallet/wallets | json, I get the outoput like,
[
{
"id": 63,
"code": "BTC",
"address": "n2F2QEKk6Fqqk2yMTope5MYp1RtpT949ke",
"currency": "Bitcoin",
"statuses": []
},
{
"id": 64,
"code": "BTC",
"address": "mrkdfp6qoVN3YiyJhq6nXPvgr3f7YpkS9j",
"currency": "Bitcoin",
"statuses": []
},
{
"id": 65,
"code": "BTC",
"address": "n3VGaHLFx8KkpNDNHsGGcHWgMWyUoA3Qdm",
"currency": "Bitcoin",
"statuses": []
},
// some data
]
There are no errors in the terminal, but the statuses comes as the empty list. In the WalletInfo class, when I change the FetchType of LAZY
#OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "wallet_id")
Set<Status> statuses = new HashSet<>(0);
I get the error message of,
100 404 0 404 0 0 760 0 --:--:-- --:--:-- --:--:-- 760
json: error: input is not JSON: Expected ':' instead of '}' at line 7, column 1:
} ]{
^
[ {
"id" : 1,
"code" : "BTC",
"address" : "mp51mPC38Wtcmybdyd9MPEB2bKnw6eYbCs",
"currency" : "Bitcoin",
"statuses"
} ]{
"msg" : "failed to lazily initialize a collection of role: mobi.puut.entities.WalletInfo.statuses, could not initialize proxy - no Session (through reference chain: java.util.ArrayList[0]->mobi.puut.entities.WalletInfo[\"statuses\"])",
"date" : "2017-09-06T03:53:052Z"
}
Why the FetchType.LAZY and FetchType.EAGER is making this difference?
this is my first post, so please bear with me if i do make any errors.
I get an error " java.lang.IllegalStateException: During synchronization a new object was found through a relationship that was not marked cascade PERSIST"
whenever i want to query(add,edit,delete) the database.
The tables related are sponsors and donations. There is a one to many relationship between them. Classes below:
Sponsors
#Entity
#Table(name = "SPONSORS")
#NamedQueries({
#NamedQuery(name = "Sponsors.findAll", query = "SELECT s FROM Sponsors s")})
public class Sponsors implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#Column(name = "SPONSORID")
private Short sponsorid;
#Basic(optional = false)
#Column(name = "NAME")
private String name;
#Basic(optional = false)
#Column(name = "SURNAME")
private String surname;
#Basic(optional = false)
#Column(name = "ADDRESS")
private String address;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "sponsorid")
private List<Donations> donationsList;
public Sponsors() {
}
public Sponsors(Short sponsorid) {
this.sponsorid = sponsorid;
}
public Sponsors(Short sponsorid, String name, String surname, String address) {
this.sponsorid = sponsorid;
this.name = name;
this.surname = surname;
this.address = address;
}
public Short getSponsorid() {
return sponsorid;
}
public void setSponsorid(Short sponsorid) {
this.sponsorid = sponsorid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public List<Donations> getDonationsList() {
return donationsList;
}
public void setDonationsList(List<Donations> donationsList) {
this.donationsList = donationsList;
}
#Override
public int hashCode() {
int hash = 0;
hash += (sponsorid != null ? sponsorid.hashCode() : 0);
return hash;
}
#Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Sponsors)) {
return false;
}
Sponsors other = (Sponsors) object;
if ((this.sponsorid == null && other.sponsorid != null) || (this.sponsorid != null && !this.sponsorid.equals(other.sponsorid))) {
return false;
}
return true;
}
#Override
public String toString() {
return "Pat.Sponsors[ sponsorid=" + sponsorid + " ]";
}
}
Donations:
#Entity
#Table(name = "DONATIONS")
#NamedQueries({
#NamedQuery(name = "Donations.findAll", query = "SELECT d FROM Donations d")})
public class Donations implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#Column(name = "DONATIONID")
private Short donationid;
#Basic(optional = false)
#Column(name = "DONATIONDATE")
#Temporal(TemporalType.DATE)
private Date donationdate;
// #Max(value=?) #Min(value=?)//if you know range of your decimal fields consider using these annotations to enforce field validation
#Column(name = "DONATIONAMOUNT")
private Double donationamount;
#JoinColumn(name = "SPONSORID", referencedColumnName = "SPONSORID")
#ManyToOne(optional = false)
private Sponsors sponsorid;
public Donations() {
}
public Donations(Short donationid) {
this.donationid = donationid;
}
public Donations(Short donationid, Date donationdate) {
this.donationid = donationid;
this.donationdate = donationdate;
}
public Short getDonationid() {
return donationid;
}
public void setDonationid(Short donationid) {
this.donationid = donationid;
}
public Date getDonationdate() {
return donationdate;
}
public void setDonationdate(Date donationdate) {
this.donationdate = donationdate;
}
public Double getDonationamount() {
return donationamount;
}
public void setDonationamount(Double donationamount) {
this.donationamount = donationamount;
}
public Sponsors getSponsorid() {
return sponsorid;
}
public void setSponsorid(Sponsors sponsorid) {
this.sponsorid = sponsorid;
}
#Override
public int hashCode() {
int hash = 0;
hash += (donationid != null ? donationid.hashCode() : 0);
return hash;
}
#Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Donations)) {
return false;
}
Donations other = (Donations) object;
if ((this.donationid == null && other.donationid != null) || (this.donationid != null && !this.donationid.equals(other.donationid))) {
return false;
}
return true;
}
#Override
public String toString() {
return "Pat.Donations[ donationid=" + donationid + " ]";
}
}
The field
#ManyToOne(optional = false)
private Sponsors sponsorid;
in the Donations entity is not configured for cascading. Try changing it to:
#ManuToOne(optional = false, cascade = CascadeType.ALL)
private Sponsors sponsorid;