When trying to serialize a Category I get a stackoverflow.
Exception
Warning: StandardWrapperValve[dispatcher]: Servlet.service() for
servlet dispatcher threw exception java.lang.StackOverflowError at
java.lang.ClassLoader.defineClass1(Native Method) at
java.lang.ClassLoader.defineClass(ClassLoader.java:760) at
org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.findClass(BundleWiringImpl.java:2279)
at
org.apache.felix.framework.BundleWiringImpl.findClassOrResourceByDelegation(BundleWiringImpl.java:1501)
at
org.apache.felix.framework.BundleWiringImpl.access$400(BundleWiringImpl.java:75)
at
org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.loadClass(BundleWiringImpl.java:1955)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357) at
com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:660)
at
com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:152)
at
com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serializeContents(IndexedListSerializer.java:100)
at
com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serializeContents(IndexedListSerializer.java:21)
at
com.fasterxml.jackson.databind.ser.std.AsArraySerializerBase.serialize(AsArraySerializerBase.java:183)
at
com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:541)
at
com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:644)
at
com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:152)
Category.java
#Entity
public class Category implements DataObject, Serializable {
#Id
#GeneratedValue
private Long id;
private String title;
private String description;
#ManyToOne #JsonIgnore
private Category parent;
#Override
public long getId() {
return id;
}
#Override
public void setId(long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Category getParent() {
return null;//return parent;
}
public void setParent(Category parent) {
// this.parent = parent;
}
public boolean isMainCategory()
{
return true;// return this.parent == null;
}
/**
* Returns the chain of parent categories with the main category on index 0
* #return Chain of categories
*/
public List<Category> getParentChain()
{
List<Category> cats = new ArrayList<>();
Category current = this;
while(!current.isMainCategory())
{
cats.add(current);
current = current.getParent();
}
cats.add(current);
Collections.reverse(cats);
return cats;
}
#Override
public String toString()
{
return this.title;
}
#Override
public boolean equals(Object o)
{
if(!(o instanceof Category))return false;
Category c = (Category)o;
return c.title.equals(this.title);
}
#Override
public int hashCode()
{
return super.hashCode();
}
}
Rest Controller function
#RequestMapping(value="/{id}", method=RequestMethod.GET)
public ResponseEntity<Category> get(#PathVariable("id") long categoryId)
{
Category c = service.getCategoryRepository().ReadValue(categoryId);
if(c == null)
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
return new ResponseEntity<>(c,HttpStatus.OK);
}
Note
Even when I replace return new ResponseEntity<>(c,HttpStatus.OK); with return new ResponseEntity<>(new Category(),HttpStatus.OK); I will get a stackoverflow whilist none of the fields contain a value.
It works fine with my other classes it's only this class that causes a stackoverflow.
Sure thing, #JsonIgnore does the job. But what if we need ignored field in our JSON output?
The solution is very simple.
We annotate our 'guilty' field by #JsonManagedReference annotation on the one side of our relation (which means our #ManyToMany annotation).
And #JsonBackReference on the other side of relation (where #OneToMany has been placed).
And that's it. No more recursive loops.
Probably if you comment private Category parent; you will not have the StackOverflow. I've got the same problem in a project with circular dependencies.
The best way to solve this problem is to use the id of the parent instead of the Class like:
private Long parentId;
Edit:
The problem is with getParentChain() that is trying to be serialized. By adding #JsonIgnore before the method the problem was resolved.
One annotation solves your problem.
Add following annotation on class.
#JsonIdentityInfo(
generator = ObjectIdGenerators.PropertyGenerator.class,
property = "id")
Other way is to annotate on Collections #JsonManagedReference for forward direction and #JsonBackReference. for backward direction in mapping.
example:
public class User{
#JsonManagedReference
#OneToMany(mappedBy = "user")
Set<Address> s = new Hashset<>();
}
public class Address{
#JsonBackReference
#ManyToOne
#JoinColumn
User user;
}
This is what i do to avoid this recursive hell.
Add #JsonIgnore to every single #OneToMany(mappedBy="xxxx") in your JPA Entities
JsonIgnore is from jackson-annotations
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.10.0</version>
</dependency>
JPA Entity example:
package model;
import java.io.Serializable;
import javax.persistence.*;
import javax.xml.bind.annotation.XmlRootElement;
import com.fasterxml.jackson.annotation.JsonIgnore;
import java.util.List;
/**
* The persistent class for the categoria database table.
*
*/
#Entity
#NamedQuery(name="Categoria.findAll", query="SELECT c FROM Categoria c")
#XmlRootElement(name = "categoria")
public class Categoria implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name="categoria_id")
private int categoriaId;
private String descripcion;
#JsonIgnore
//bi-directional many-to-one association to Establecimiento
#OneToMany(mappedBy="categoria")
private List<Establecimiento> establecimientos;
public Categoria() {
}
public int getCategoriaId() {
return this.categoriaId;
}
public void setCategoriaId(int categoriaId) {
this.categoriaId = categoriaId;
}
public String getDescripcion() {
return this.descripcion;
}
public void setDescripcion(String descripcion) {
this.descripcion = descripcion;
}
public List<Establecimiento> getEstablecimientos() {
return this.establecimientos;
}
public void setEstablecimientos(List<Establecimiento> establecimientos) {
this.establecimientos = establecimientos;
}
public Establecimiento addEstablecimiento(Establecimiento establecimiento) {
getEstablecimientos().add(establecimiento);
establecimiento.setCategoria(this);
return establecimiento;
}
public Establecimiento removeEstablecimiento(Establecimiento establecimiento) {
getEstablecimientos().remove(establecimiento);
establecimiento.setCategoria(null);
return establecimiento;
}
}
Related
I have the following classes:
#Entity(name = "focusoc_orbit")
#Data
public class OrbitAdapter extends Adapter{
#Id
private String id;
...
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
...
}
And,
#Entity(name = "focusoc_conjunction")
#Data
public class ConjunctionAdapter extends Adapter {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#ManyToOne
#JoinColumn(name = "target_id")
private OrbitAdapter target;
#ManyToOne
#JoinColumn(name = "chaser_id")
private OrbitAdapter chaser;
...
public OrbitAdapter getTarget(){
return target;
}
public void setTarget(OrbitAdapter target){
this.target = target;
}
public String getChaserId(){
return chaserId;
}
public void setChaser(OrbitAdapter chaser){
this.chaser = chaser;
}
...
}
Also I defined the Repository:
public interface ConjunctionRepository extends PagingAndSortingRepository<ConjunctionAdapter, Long> {
public ConjunctionAdapter findByTargetAndChaserAndTimeOfCloseApproach(String target, String chaser, Date timeOfCloseApproach);
}
When I try to make the call,
ConjunctionAdapter c = conjunctionRepository.findByTargetAndChaserAndTimeOfCloseApproach(targetId, chaserId, timeOfCloseApproach());
It returns the error:
org.hibernate.property.access.spi.PropertyAccessException: Error
accessing field [private java.lang.String
gcs.fds.focusoc.adapter.OrbitAdapter.id] by reflection for persistent
property [gcs.fds.focusoc.adapter.OrbitAdapter#id] : 02035A"
I tried a lot of differents solutions that I found but it does not work for me. Any help?
I solved it !
Changing the annotation #Data of the classes for #Table with the table name. So,
#Entity
#Table(name = "focusoc_orbit")
public class OrbitAdapter extends Adapter{
#Id
private String id;
...
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
...
}
And,
#Entity
#Table(name = "focusoc_conjunction")
public class ConjunctionAdapter extends Adapter {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#ManyToOne
#JoinColumn(name = "target_id")
private OrbitAdapter target;
#ManyToOne
#JoinColumn(name = "chaser_id")
private OrbitAdapter chaser;
...
public OrbitAdapter getTarget(){
return target;
}
public void setTarget(OrbitAdapter target){
this.target = target;
}
public String getChaserId(){
return chaserId;
}
public void setChaser(OrbitAdapter chaser){
this.chaser = chaser;
}
...
}
And doing this it returns me the error,
java.lang.IllegalArgumentException: Parameter value [02035A] did not
match expected type [gcs.fds.focusoc.adapter.OrbitAdapter (n/a)]
So I added the annotation #Query into the Repository to specify which things has to be searched in the database,
public interface ConjunctionRepository extends PagingAndSortingRepository<ConjunctionAdapter, Long> {
#Query("SELECT c FROM ConjunctionAdapter c WHERE c.target.id = :target AND c.chaser.id = :chaser AND c.timeOfCloseApproach = :timeOfCloseApproach")
public ConjunctionAdapter findByTargetAndChaserAndTimeOfCloseApproach(String target, String chaser, Date timeOfCloseApproach);
}
And solved!
I have a class called jobprofile, which contains the following OneToMany Relation:
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "profile")
private List<JobLanguageProficiency> jobLanguageProficiency;
The referenced class "JobLanguageProficiency" looks like this:
package ch.alv.jobmatch.entity.aux;
import ch.alv.jobmatch.entity.job.Jobprofile;
import javax.persistence.*;
#Entity
#Table(name = "job_language_proficiency")
public class JobLanguageProficiency {
#Id
private int id;
#ManyToOne
#JoinColumn(name = "jobprofile_jobprofile_id")
private Jobprofile profile;
#OneToOne
private Languages languages;
#OneToOne
private LangProficiency langProficiency;
public Languages getLanguages() {
return languages;
}
public void setLanguages(Languages languages) {
this.languages = languages;
}
public LangProficiency getLangProficiency() {
return langProficiency;
}
public void setLangProficiency(LangProficiency langProficiency) {
this.langProficiency = langProficiency;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Jobprofile getProfile() {
return profile;
}
public void setProfile(Jobprofile profile) {
this.profile = profile;
}
}
Basically, it just contains two references to a language, and a proficiency for it.
When I try to create/persist a jobprofile, it fails as soon as it tries to insert the language data in the database.
This is the error:
Failed to write HTTP message: org.springframework.http.converter.HttpMessageNotWritableException:
Could not write content: (was java.lang.NullPointerException) (through
reference chain:
org.springframework.data.rest.webmvc.json.["content"]); nested
exception is com.fasterxml.jackson.databind.JsonMappingException: (was
java.lang.NullPointerException) (through reference chain:
org.springframework.data.rest.webmvc.json.["content"])
I suspect the source of the error lies in the JSON, since the OneToMany Relation works perfectly when I insert the data manually.
The relevant part of the JSON looks like this:
job_language_proficiency: Array[1]
0: Object
languages: "http://localhost:9000/api/languages/de"
proficiency_code: "http://localhost:9000/api/langproficiency/C1"
Any ideas why this doesn't work?
EDIT: Updated the JSON so it contains objects instead of links.
LangProficiency entity:
package ch.alv.jobmatch.entity.aux;
import javax.persistence.*;
#Entity
#Table(name = "LangProficiency")
public class LangProficiency {
#Id
#Column(name = "proficiency_code")
private String proficiency_code;
private String description_de;
private String description_fr;
private String description_it;
private String description_en;
public String getProficiency_code() {
return proficiency_code;
}
public void setProficiency_code(String proficiency_code) {
this.proficiency_code = proficiency_code;
}
public String getDescription_de() {
return description_de;
}
public void setDescription_de(String description_de) {
this.description_de = description_de;
}
public String getDescription_fr() {
return description_fr;
}
public void setDescription_fr(String description_fr) {
this.description_fr = description_fr;
}
public String getDescription_it() {
return description_it;
}
public void setDescription_it(String description_it) {
this.description_it = description_it;
}
public String getDescription_en() { return description_en; }
public void setDescription_en(String description_en) { this.description_en = description_en; }
}
Languages entity:
package ch.alv.jobmatch.entity.aux;
import javax.persistence.*;
import java.io.Serializable;
#Entity
#Table(name = "Languages")
public class Languages implements Serializable {
#Id
#Column(name = "languages")
private String languages;
private String description_de;
private String description_fr;
private String description_it;
private String description_en;
public String getLanguages() {
return languages;
}
public void setLanguages(String languages) {
this.languages = languages;
}
public String getDescription_de() {
return description_de;
}
public void setDescription_de(String description_de) {
this.description_de = description_de;
}
public String getDescription_fr() {
return description_fr;
}
public void setDescription_fr(String description_fr) {
this.description_fr = description_fr;
}
public String getDescription_it() {
return description_it;
}
public void setDescription_it(String description_it) {
this.description_it = description_it;
}
public String getDescription_en() { return description_en; }
public void setDescription_en(String description_en) { this.description_en = description_en; }
}
Your JSON structure should match your Java Mapping, otherwise your object won't be persisted by your ORM, that's why you are getting such Mapping error.
In your case in your Entity you have a relationship with two entities that should be objects in your JSON:
#OneToOne
private Languages languages;
#OneToOne
private LangProficiency langProficiency;
But in your JSON, you have set those two objects as simple strings:
languages: "http://localhost:9000/api/languages/de"
proficiency_code: "http://localhost:9000/api/langproficiency/C1"
They should be matching Languages and langProficiency objects, and proficiency_code should be named langProficiency respectively like your Java attribute.
Entity-relationship diagram:
I want to receive a translation, but the element will link back to translation.
So it will crash because it keeps looping..
Translation entity:
package com.exstodigital.photofactory.model;
import javax.persistence.*;
import java.io.Serializable;
/**
* Created by youri on 21-09-16.
*/
#Table(name = "translation")
#Entity
public class Translation implements Serializable {
#Id
#GeneratedValue
private int id;
public int getId() {
return id;
}
private String text;
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
#OneToOne
#JoinColumn(name = "language_id")
private Language language;
public Language getLanguage() {
return language;
}
#OneToOne
#JoinColumn(name = "element_id")
private Element element;
public Element getElement() {
return element;
}
public Translation(int id, String text) {
this.id = id;
this.text = text;
}
public Translation() {
// Empty constructor
}
#Override
public boolean equals(Object obj) {
return obj instanceof Translation && (!this.text.equals(((Translation) obj).text));
}
}
Element entity:
package com.exstodigital.photofactory.model;
import javax.persistence.*;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* Created by youri on 21-09-16.
*/
#Entity
#Table(name = "element")
public class Element implements Serializable {
#Id
#GeneratedValue
private int id;
public int getId() {
return id;
}
private String label;
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
#OneToMany
#JoinColumn(name = "element_id")
private List<Translation> translations = new ArrayList<>();
public List<Translation> getTranslations() {
return Collections.unmodifiableList(translations);
}
public Element(int id, String label) {
this.id = id;
this.label = label;
}
public Element() {
// Empty constructor
}
#Override
public boolean equals(Object obj) {
return obj instanceof Element && (this.id != ((Element) obj).id || !this.label.equals(((Element) obj).label));
}
}
TranslationDaoImpl:
#Override
public Translation get(int id) {
return sessionFactory.openSession().get(Translation.class, id);
}
You have established wrong relationship, from one side you are giving OneToOne and with same but from second entity you are giving OneToMany
Your code:
#Table(name = "translation")
#Entity
public class Translation implements Serializable {
#OneToOne
#JoinColumn(name = "element_id")
private Element element;
}
#Entity
#Table(name = "element")
public class Element implements Serializable {
#OneToMany
#JoinColumn(name = "element_id")
private List<Translation> translations = new ArrayList<>();
}
Right code for OneToOne :
#Table(name = "translation")
#Entity
public class Translation implements Serializable {
#JsonIgnore
#OneToOne
#JoinColumn(name = "element_id")
private Element element;
}
#Entity
#Table(name = "element")
public class Element implements Serializable {
#OneToOne
(mappedBy="element")
private Translation translation;
}
Right code for OneToMany :
#Table(name = "translation")
#Entity
public class Translation implements Serializable {
#JsonIgnore
#ManyToOne
#JoinColumn(name = "element_id")
private Element element;
}
#Entity
#Table(name = "element")
public class Element implements Serializable {
#OneToMany
(mappedBy="element")
private List<Translation> translations;
}
Use "#JsonIgnore" to avoid Infinite recursion that is coming into your
code
I have two DTO objects say A and B which are having getters and setters and are used to take data from the database. The problem is when I am calling A, B gets called and B again points itself to A and a cycle is created.
I cannot ignore/hide the method which is creating the cycle. I need to take the whole data of A and B.
Is there any way to achieve it ?
Please help
This is my code which is causing the problem. This is application DTO which is calling environment DTO
#OneToMany(mappedBy="application", fetch=FetchType.LAZY
,cascade=CascadeType.ALL
)
public Set<EnvironmentDTO> getEnvironment() {
return environment;
}
public void setEnvironment(Set<EnvironmentDTO> environment) {
this.environment = environment;
}
And this is environment DTO which is calling the application DTO
#ManyToOne(targetEntity=ApplicationDTO.class )
#JoinColumn(name="fk_application_Id")
public ApplicationDTO getApplication() {
return application;
}
public void setApplication(ApplicationDTO application) {
this.application = application;
}
Here cycle is getting created
This is my rest call which will give result in XML format and I think while creating XML cycle is getting created
#GET
#Path("/get")
#Produces({MediaType.APPLICATION_XML})
public List<ApplicationDTO> getAllApplications(){
List<ApplicationDTO> allApplication = applicationService.getAllApplication();
return allApplication;
}
This is the Application DTO class
#Entity
#Table(name="application")
#org.hibernate.annotations.GenericGenerator(
name ="test-increment-strategy",strategy = "increment")
#XmlRootElement
public class ApplicationDTO implements Serializable {
#XmlAttribute
public Long appTypeId;
private static final long serialVersionUID = -8027722210927935073L;
private Long applicationId;
private String applicationName;
private ApplicationTypeDTO applicationType;
private String applicationDescription;
private Integer owner;
private Integer createdBy;
private Integer assignedTo;
private Date createTime;
private Date modifiedTime;
private Set<EnvironmentDTO> environment;
#Id
#GeneratedValue(generator = "test-increment-strategy")
#Column(name = "applicationId")
public Long getApplicationId() {
return applicationId;
}
private void setApplicationId(Long applicationId) {
this.applicationId = applicationId;
}
#Column(name = "applicationName")
public String getApplicationName() {
return applicationName;
}
public void setApplicationName(String applicationName) {
this.applicationName = applicationName;
}
#ManyToOne(targetEntity=ApplicationTypeDTO.class
,fetch = FetchType.LAZY
)
#JoinColumn(name="applicationType")
public ApplicationTypeDTO getApplicationType() {
return applicationType;
}
public void setApplicationType(ApplicationTypeDTO applicationType) {
this.applicationType = applicationType;
}
#Column(name = "description")
public String getApplicationDescription() {
return applicationDescription;
}
public void setApplicationDescription(String applicationDescription) {
this.applicationDescription = applicationDescription;
}
#Column(name = "owner")
public Integer getOwner() {
return owner;
}
public void setOwner(Integer owner) {
this.owner = owner;
}
#Column(name = "createdBy")
public Integer getCreatedBy() {
return createdBy;
}
public void setCreatedBy(Integer createdBy) {
this.createdBy = createdBy;
}
#Column(name = "assignedTo")
public Integer getAssignedTo() {
return assignedTo;
}
public void setAssignedTo(Integer assignedTo) {
this.assignedTo = assignedTo;
}
#Column(name = "createTime")
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
#Column(name = "modifiedTime")
public Date getModifiedTime() {
return modifiedTime;
}
public void setModifiedTime(Date modifiedTime) {
this.modifiedTime = modifiedTime;
}
#OneToMany(mappedBy="application", fetch=FetchType.LAZY
,cascade=CascadeType.ALL
)
public Set<EnvironmentDTO> getEnvironment() {
return environment;
}
public void setEnvironment(Set<EnvironmentDTO> environment) {
this.environment = environment;
}
This is the Environment DTO class
#Entity
#Table(name="environment")
#org.hibernate.annotations.GenericGenerator(
name = "test-increment-strategy",
strategy = "increment")
#XmlRootElement
public class EnvironmentDTO implements Serializable {
#XmlAttribute
public Long envTypeId;
#XmlAttribute
public Long appId;
private static final long serialVersionUID = -2756426996796369998L;
private Long environmentId;
private String environmentName;
private EnvironmentTypeDTO environmentType;
private Integer owner;
private Date createTime;
private Set<InstanceDTO> instances;
private ApplicationDTO application;
#Id
#GeneratedValue(generator = "test-increment-strategy")
#Column(name = "envId")
public Long getEnvironmentId() {
return environmentId;
}
private void setEnvironmentId(Long environmentId) {
this.environmentId = environmentId;
}
#Column(name = "envName")
public String getEnvironmentName() {
return environmentName;
}
public void setEnvironmentName(String environmentName) {
this.environmentName = environmentName;
}
#ManyToOne(targetEntity=EnvironmentTypeDTO.class)
#JoinColumn(name = "envType")
public EnvironmentTypeDTO getEnvironmentType() {
return environmentType;
}
public void setEnvironmentType(EnvironmentTypeDTO environmentType) {
this.environmentType = environmentType;
}
#Column(name = "owner")
public Integer getOwner() {
return owner;
}
public void setOwner(Integer owner) {
this.owner = owner;
}
#Temporal(TemporalType.DATE)
#Column(name = "createTime")
public Date getCreateTime()
{
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
#OneToMany(mappedBy="environment", cascade=CascadeType.ALL, fetch = FetchType.EAGER)
public Set<InstanceDTO> getInstances() {
return instances;
}
public void setInstances(Set<InstanceDTO> instances) {
this.instances = instances;
}
#ManyToOne(targetEntity=ApplicationDTO.class )
#JoinColumn(name="fk_application_Id")
//#XmlTransient
public ApplicationDTO getApplication() {
return application;
}
public void setApplication(ApplicationDTO application) {
this.application = application;
}
Your object graph is cyclic. There is nothing intrinsically wrong with that, and it is a natural consequence of using JPA.
Your problem is not that your object graph is cyclic, but that you are encoding it in a format which cannot handle cycles. This isn't a Hibernate question, it's a JAXB question.
My suggestion would be to stop JAXB from attempting to marshal the application property of the EnvironmentDTO class. Without that property the cyclic graph becomes a tree. You can do this by annotating that property with #XmlTransient.
(confession: i learned about this annotation by reading a blog post by Mr Doughan, which i came across after reading his answer to this question!)
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.
MOXy offers the #XmlInverseReference extension to handle this use case. Below is an example of how to apply this mapping on two entities with a bidirectional relationship.
Customer
import javax.persistence.*;
#Entity
public class Customer {
#Id
private long id;
#OneToOne(mappedBy="customer", cascade={CascadeType.ALL})
private Address address;
}
Address
import javax.persistence.*;
import org.eclipse.persistence.oxm.annotations.*;
#Entity
public class Address implements Serializable {
#Id
private long id;
#OneToOne
#JoinColumn(name="ID")
#MapsId
#XmlInverseReference(mappedBy="address")
private Customer customer;
}
For More Information
http://blog.bdoughan.com/2010/07/jpa-entities-to-xml-bidirectional.html
http://blog.bdoughan.com/2013/03/moxys-xmlinversereference-is-now-truly.html
My advice is not exposing your JPA entity class to your webservices. You can create different POJO class and convert your JPA entity to the POJO. For example:
this is your JPA entity
import javax.persistence.*;
#Entity
public class Customer {
#Id
private long id;
#OneToOne(mappedBy="customer", cascade={CascadeType.ALL})
private Address address;
}
you should use this class for your webservices:
public class CustomerModel{
private long id;
//you can call different WS to get the Address class, or combine to this model
public void setFromJpa(Customer customer){
this.id = customer.id;
}
}
i need some help for my class...
package com.it.ese.orbit.entity;
import javax.persistence.*;
import java.util.List;
/**
* Created by IntelliJ IDEA.
* User: Shahriar Newaz
* Date: 07/03/11
* Time: 10.07
*/
#Entity
#Inheritance(strategy =InheritanceType.JOINED)
public class OrbitObject {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue
#Column(name="id",nullable = false)
private Long id;
#Column(name="Scenario",nullable = false)
private String scenario; // not sure about how to map scenario
#Column(name="code",nullable = true)
private String code;
#Column(name="name",nullable = true)
private String name;
#OneToOne(cascade=CascadeType.ALL)
private Bia bia;
#OneToOne(cascade=CascadeType.ALL)
public Impatti impatti;
#Column(name="parent",nullable = true)
#OneToMany(cascade=CascadeType.ALL)
private OrbitObject OrbitObject;
public Long getId() {
return id;
}
protected void setId(Long id) {
this.id = id;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getScenario() {
return scenario;
}
public void setScenario(String scenario) {
this.scenario = scenario;
}
public String getName() {
return name;
}
public void setName(String name) {
name = name;
}
// LOG
#Override
public String toString(){
return "com.it.ese.orbit.models.OrbitObject["
+ " - name="+name + " - scenario="+scenario +" - id= "+id+"]";
}
}
But i get thi error...
Caused by: org.hibernate.AnnotationException: Illegal attempt to map a non collection as a #OneToMany, #ManyToMany or #CollectionOfElements: com.it.ese.orbit.entity.OrbitObject.OrbitObject
I wish i create an OrbitObject field as like an object of the same class...
Help please!
You either do
#Column(name="parent",nullable = true)
#ManyToOne(cascade=CascadeType.ALL)
private OrbitObject OrbitObject;
Or
#Column(name="parent",nullable = true)
#OneToMany(cascade=CascadeType.ALL)
private Set<OrbitObject> OrbitObject;
The first case implies this entity will be the owning side, namely, it will have the foreign key.
OneToMany means that OrbitObject has many OrbitObject children, which is not true because the OrbitObject property is not a collection.
You must convert it to a ManyToOne
you can use #OneToMany referring to a collection of elements, for example
#OneToMany
List<OrbitObject> orbitList;