Gson StackOverflow on JSONWriter - json

I created a system and it libero access via Webservice Restful, with him I release a maintenance list, this list is formed by objects: Cliente, Endereco, Manutencao, StatusManutencao.
I have a class that seeks the bench all maintenance that is Class: PesquisaManutencoesWebService, and the class that receives the call webservice calls SimpleRestService.
When I turn my maintenance list in JSON (return gson.toJson (ws.getJson ());), is generated the following error:
java.lang.StackOverflowError
java.io.StringWriter.write (StringWriter.java:112)
com.google.gson.stream.JsonWriter.string (JsonWriter.java:559)
com.google.gson.stream.JsonWriter.writeDeferredName (JsonWriter.java:402)
com.google.gson.stream.JsonWriter.value (JsonWriter.java:495)
com.google.gson.internal.bind.TypeAdapters $ 8.write (TypeAdapters.java:268)
Already tested if the list is working, and really is, I can get all the data I want, but I just can not turn into JSON.
Can anyone help me? Thanks.
Class Cliente
#Entity
#Table(name = "cliente")
public class Cliente implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue
private Long id;
#NotBlank #Size(max = 6)
#Column(nullable = false, length = 6)
private String codigoAcesso;
#NotBlank #Size(max = 100)
#Column(nullable = false, length = 100)
private String nome;
#Size(max = 150)
#Column(nullable = true, length = 150)
private String email;
#NotBlank #Size(max = 14)
#Column(name = "doc_receita_federal", nullable = false, length = 14)
private String documentoReceitaFederal;
#Enumerated(EnumType.STRING)
#Column(nullable = false, length = 15)
private TipoPessoa tipo;
#OneToMany(mappedBy = "cliente", cascade = CascadeType.ALL)
private List<Endereco> enderecos = new ArrayList<>();
Class Endereco
#Entity
#Table(name = "endereco")
public class Endereco implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue
private Long id;
#NotBlank #Size(max = 150)
#Column(nullable = false, length = 150)
private String logradouro;
#NotBlank #Size(max = 20)
#Column(nullable = false, length = 20)
private String numero;
#Size(max = 100)
#Column(length = 100)
private String complemento;
#NotBlank #Size(max = 100)
#Column(nullable = false, length = 100)
private String cidade;
#NotBlank #Size(max = 100)
#Column(nullable = false, length = 100)
private String uf;
#NotBlank #Size(max = 8)
#Column(nullable = false, length = 8)
private String cep;
//#NotBlank
#ManyToOne
#JoinColumn(name = "cliente_id", nullable = false)
private Cliente cliente;
getters and setters ...
Class Manutencao
#Entity
#Table(name = "manutencao")
public class Manutencao implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue
private Long id;
#ManyToOne
#JoinColumn(name = "cliente_id")
private Cliente cliente;
#Embedded
private StatusManutencao status;
#NotBlank
#Column(nullable = false, length = 255, name="descricao_manutencao")
private String descricaoManutencao;
#Column(name = "valor", precision = 10, scale = 2)
private BigDecimal valor;
getters and setters ...
Class StatusManutencao
#Embeddable
public class StatusManutencao implements Serializable {
private static final long serialVersionUID = 1L;
#Column(name="recebido")
#Type(type="true_false")
private boolean recebido;
#Temporal(TemporalType.DATE)
#Column(name="data_recebimento")
private Date dataRecebimento;
#Column(name="em_manutencao")
#Type(type="true_false")
private boolean emManutencao;
#Temporal(TemporalType.DATE)
#Column(name="data_manutencao")
private Date dataManutencao;
#Column(name="manutencao_finalizada")
#Type(type="true_false")
private boolean manutencaoFinalizada;
#Temporal(TemporalType.DATE)
#Column(name="data_finalizacao")
private Date dataFinalizacao;
#Column(name="entregue")
#Type(type="true_false")
private boolean entregue;
#Temporal(TemporalType.DATE)
#Column(name="data_entrega")
private Date dataEntrega;
#Column(name="pago")
#Type(type="true_false")
private boolean pago;
#Temporal(TemporalType.DATE)
#Column(name="data_pagamento")
private Date dataPagamento;
getters and setters ...
Class PesquisaManutencaoWebService
public class PesquisaManutencoesWebService implements Serializable {
private static final long serialVersionUID = 1L;
private EntityManager manager;
private EntityManagerFactory factory;
private EntityTransaction trx;
public PesquisaManutencoesWebService(){
this.factory = Persistence.createEntityManagerFactory("ManutencaoPU");
this.manager = factory.createEntityManager();
this.trx = manager.getTransaction();
this.trx.begin();
}
#SuppressWarnings("unchecked")
public JsonModel getJson(){
List<Manutencao> manutencoes = manager.createQuery("SELECT m FROM Manutencao m").getResultList();
return new JsonModel(manutencoes);
}
}
Class SimpleRestService
#Path("service")
public class SimpleRestService {
private PesquisaManutencoesWebService ws;
#GET
#Produces("application/json")
#Path("/{codigoAcesso}/")
public String getManutencoes(#PathParam("codigoAcesso") String codigoAcesso) throws IOException, SQLException, ClassNotFoundException{
ws = new PesquisaManutencoesWebService();
Gson gson = new GsonBuilder().serializeSpecialFloatingPointValues().setPrettyPrinting().create();
return gson.toJson(ws.getJson());
}
}

In most of the cases StackOverError is thrown when call stack exceeds because of excessive deep or infinite recursion. It is also thrown when the need to store the local variable in the method exceeds the allocated stack size.
In your Endereco Class, add Fetch Type to #ManyToOne anotattion in the Cliente attribute, then your code should look like this:
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "cliente_id")
private Cliente cliente;
When you set FetchType to Lazy, you are basically saying that Entity should not be nested to the parent Entity.
Then try to get the Clientes List Manually...

Related

How can i mapping entities in spring boot jpa?

I'm new in Spring Boot JPA
I have questions in JPA Entity mappings.
there is 4 tables in my MySql DB
SPACE, PROJECT, ISSUE, MEMBER
SPACE is Big Project which contains multiple PROJECT.
PROJECT contains multiple ISSUE.
and MEMBER can join only 1 SPACE and multiple PROJECT which MEMBER belongs to SPACE.
MEMBER can write multiple ISSUE
in this situation, my ERD model is correct?
my ERD
and please check my jpa mappings.
If there's anything wrong, please point it out.
SPACE
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "space_no")
private Long spaceNo;
#NotEmpty
#Column(name = "space_name", unique=true, length = 100)
private String spaceName;
/** 1:N relation */
#OneToMany(mappedBy = "smsSpace")
private List<PmsProject> pmsProjects = new ArrayList<>();
PROJECT
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "project_no")
private Long projectNo;
#Column(name ="space_no")
private Long spaceNo;
#Column(name = "project_name", length = 100)
private String projectName;
/** 1:N relation */
#OneToMany(mappedBy = "pmsProject")
private List<ImsIssue> imsIssues = new ArrayList<>();
#OneToMany(mappedBy = "pmsProject")
private List<PmsProjectMember> projectMembers = new ArrayList<>();
/** N:1 relation */
#ManyToOne
#JoinColumn(name = "space_no", referencedColumnName = "space_no", insertable = false, updatable = false)
private SmsSpace smsSpace;
MEMBER
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "member_no")
private Long memberNo;
#Column(name = "mail_address", unique=true, length = 100)
private String mailAddress;
#Column(name = "name", length = 100)
private String name;
#Column(name = "keyword", length = 1000)
private String keyword;
#Column(name = "image", length = 1000)
private String image;
#Column(name = "password", length = 1000)
private String password;
#Column(name = "user_id", length = 50)
private String userId;
#Enumerated(EnumType.STRING)
private MemberRole role;
public void encodingPassword(String password) {
this.password = password;
}
/** 1:N realtion */
#OneToMany(mappedBy = "mmsMember")
private List<PmsProjectMember> projectMembers = new ArrayList<>();
ISSUE
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "issue_no")
private Long issueNo;
#Column(name ="project_no")
private Long projectNo;
#Column(name = "issue_name", length = 1000)
private String issueName;
#Column(name = "priority")
private Long priority;
#Column(name = "status", length = 20)
private String status;
#Column(name = "summary", length = 100)
private String summary;
#Column(name = "is_overdue")
private Long isOverdue;
#Column(name = "issue_type_cd")
private String issueTypeCd;
/** N:1 relation */
#ManyToOne
#JoinColumn(name = "project_no", referencedColumnName = "project_no", insertable = false, updatable = false)
private PmsProject pmsProject;
PROJECTMEMBER
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "group_no")
private Long groupNo;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "member_no")
private MmsMember mmsMember;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "project_no")
private PmsProject pmsProject;
I've been thinking about it for days, but I can't solve it because I lack knowledge. Please help me.
Assuming I got your situation right, you have A member that can have one Space and multiple project, space has multiple projects, every project can have more than one issue, every member can write more then one issue for each project.
Due to the suggestion the ERD you posted it's not corrected.
Here is the correct ERD
(I just wrote the Foreign Keys and Primary Keys, the rest its up to you)
And here you have all the entites:
Member
#Entity
#Table(name = "MEMBERS")
public class Member {
//members is the property name in Project entity.
#ManyToMany(mappedBy = "members")
Set<Project> projects;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY, generator = "native")
#Column(name = "MEMBER_ID")
private Long id;
#ManyToOne
#JoinColumn(name = "SPACE_ID")
private Space space;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Space getSpace() {
return space;
}
public void setSpace(Space space) {
this.space = space;
}
public Set<Project> getProjects() {
return projects;
}
public void setProjects(Set<Project> projects) {
this.projects = projects;
}
}
Space
#Entity
#Table(name = "SPACES")
public class Space {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY, generator = "native")
#Column(name = "SPACE_ID")
private Long id;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
}
Issue
#Entity
#Table(name = "ISSUES")
public class Issue {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY, generator = "native")
#Column(name = "ISSUE_ID")
private Long id;
#ManyToOne
#JoinColumn(name = "MEMBER_ID")
private Member member;
#ManyToOne
#JoinColumn(name = "PROJECt_ID")
private Project project;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Member getMember() {
return member;
}
public void setMember(Member member) {
this.member = member;
}
public Project getProject() {
return project;
}
public void setProject(Project project) {
this.project = project;
}
}
Project
#Entity
#Table(name = "PROJECTS")
public class Project {
#ManyToMany
#JoinTable(
name = "PROJECTS_MEMBERS",
joinColumns = #JoinColumn(name = "PROJECT_ID"),
inverseJoinColumns = #JoinColumn(name = "MEMBER_ID"))//Is referring to the id of the other Entity, in this case, members
Set<Member> members;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY, generator = "native")
#Column(name = "PROJECT_ID")
private Long id;
#ManyToOne
#JoinColumn(name = "SPACE_ID")
private Space space;
public Set<Member> getMembers() {
return members;
}
public void setMembers(Set<Member> members) {
this.members = members;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Space getSpace() {
return space;
}
public void setSpace(Space space) {
this.space = space;
}
}
You don't have to put necessarily both #ManyToOne and #OneToMany annotation, the back-reference could be useful in some use case, you have to see if you need it or not. Remember the back reference could cause problems with deserialization, creating a stack overflow by circular reference. You can avoid this, using transient keyword or various annotation (depending on the library you are using, Jackson, Gson, ecc..).
Be careful to don't use FetchType.EAGER randomly here's the why => Difference between FetchType LAZY and EAGER in Java Persistence API?

Many to many relation ship gives null

using spring data and mysql as persistence layer getting some issues in Many to many mappings
#Getter
#Setter
public class BusinessUnitEntitiy extends AbstractTenantEntity implements Auditable{
private static final long serialVersionUID = -1123383144979037984L;
#Column(name = "NAME")
String name;
#Column(name = "DESCRIPTION")
String description;
#ManyToMany(fetch = FetchType.LAZY,mappedBy = "businessUnits" )
private Set<User> businessUsers;
public Set<User> fetchBusinessUsers() {
return businessUsers;
}
#Column(name = "DISPLAY_SEQUENCE_NUM")
protected Long displaySequenceNum;
#Column(name = "UNIQUE_SEQUENCE_ID",unique = true)
protected String uniqueSequenceId;
}
#Getter
#Setter
public class User extends AbstractTenantEntity {
private static final long serialVersionUID = 65981149772133526L;
#Column(name = "PROVIDER_USER_ID")
private String providerUserId;
private String email;
#Column(name = "enabled", columnDefinition = "BIT", length = 1)
private boolean enabled;
#Column(name = "DISPLAY_NAME")
private String displayName;
private String password;
private String provider;
#Column(name = "DISPLAY_SEQUENCE_NUM")
protected Long displaySequenceNum;
#Column(name = "UNIQUE_SEQUENCE_ID",unique = true)
protected String uniqueSequenceId;
#ManyToMany(fetch = FetchType.EAGER)
#JoinTable(
name = "business_unit_user",
joinColumns={#JoinColumn(name ="user_id")},
inverseJoinColumns = { #JoinColumn(name="business_unit_id") }
)
Set<BusinessUnitJpaEntitiy> businessUnits;
}
fetching the user from businessunit works perfectly
but fetching businessunits from users gives null set even updating the same user is persisiting only the newly linked businessunit older values vanishes
If you persisted the user within the transaction without initializing the businessUnits fields, that's what you get. Either you also initialize the set correctly before persisting, or you detach the user after persisting, so that the user is reloaded from the database and the set is properly initialized.
you can try this
#ManyToMany
#JoinTable(
name = "business_unit_user",
joinColumns={#JoinColumn(name ="user_id",referencedColumnName = "id")},
inverseJoinColumns = { #JoinColumn(name="business_unit_id",referencedColumnName = "id") }
)
Set<BusinessUnitJpaEntitiy> businessUnits;
and you must have setter and getter for each property

Nested one to many relationship jpa spring boot

I have three classes - Document, Page, Sentence. A Document will have multiple Pages & each Page will have multiple Sentences. I'm trying to map One to Many relationship using Spring Data JPA annotation. But it only works when there are only one layer like - Document>Page. Doesn't work while it's Document>Page>Sentence.
Can anyone please give me a solution for how to do it for nested one to many relationship ?
My classes are given below.
#Entity
#Table(name = "DOCUMENT")
public class Document implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name = "FILEID")
#GeneratedValue(strategy = GenerationType.AUTO)
private long idFile;
#Lob
#Column(name = "CONTENT")
private byte[] content;
#Column(name = "NAME")
private String name;
#Column(name = "ID_MAIL_USER")
private String idMailUser;
#Column(name = "NUM_PAGES")
private int numPages;
#Column(name = "TO_ANALIZE")
private boolean toAnalize;
#Column(name = "HASH")
private String hash;
#Column(name = "EXTENSION")
private String extension;
#Column(name = "SIZE")
private double size;
#Column(name = "LINK_TO_DRIVE_FILE")
private String linkToDriveFile;
#Column(name="PATH")
private String path;
#OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
#Column(name = "PAGES")
private List<Page> pages = new ArrayList<>();
// Setter Getters
}
.
#Entity
#Table(name = "PAGE")
public class Page implements Serializable {
#Id
#Column(name = "PAGE_ID")
#GeneratedValue(strategy = GenerationType.AUTO)
private long idPage;
#Column(name = "PAGE_NUMBER")
private int pageNum;
#Lob
#Column(name = "CONTENT")
private String content;
#ManyToMany(cascade = CascadeType.ALL)
#Column(name = "SENTENCES")
private List<Sentence> sentences = new ArrayList<>();
// Setter Getters
}
.
#Entity
#Table(name = "SENTENCE")
public class Sentence implements Serializable {
//private long idFile;
//private long idPage;
#Id
#Column(name = "SENTENCE_ID")
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#Column(name = "PAGE_NUMBER")
private int pageNumber;
#Column(name = "ORDER")
private int ord;
#Column(name = "CONTENT")
private String content;
#Column(name = "HASH")
private String hash;
// Setter Getters
}
Your OneToMany mappings are incorrect. Correct it as follows
#Entity
#Table(name = "DOCUMENT")
public class Document implements Serializable {
......
#OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
#JoinColumn(name = "DOCUMENT_ID") //Name the foreign key column in PAGE table to DOCUMENT_ID
private List<Page> pages = new ArrayList<>();
}
#Entity
#Table(name = "PAGE")
public class Page implements Serializable {
....
#OneToMany(cascade = CascadeType.ALL)
#JoinColumn(name = "PAGE_ID") //Name the forein key column in PAGE table to PAGE_ID
private List<Sentence> sentences = new ArrayList<>();
}
Use #JoinColumn annotation instead of #Column to give the name of the foreign key that do the physical mapping between tables in your database.
#Entity
#Table(name = "DOCUMENT")
public class Document implements Serializable {
private static final long serialVersionUID = 1L;
#OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy="document")
#Column(name = "PAGES")
private List<Page> pages = new ArrayList<>();
}
#Entity
#Table(name = "PAGE")
public class Page implements Serializable {
#ManyToOne
#JoinColumn(name="DOCUMENT_ID")
private Document document;
#ManyToMany(cascade = CascadeType.ALL, mappedBy="pages")
#Column(name = "SENTENCES")
private List<Sentence> sentences = new ArrayList<>();
}
#Entity
#Table(name = "SENTENCE")
public class Sentence implements Serializable {
#ManyToMany(mappedBy="sentences")
private List<Page> pages;
}
Here a Document One to Many relationship with Pages.
So.. we need define mappedBy in the entity we want to map another entity.. so in this case
#OneToMany(mappedBy="document",cascade = CascadeType.ALL, orphanRemoval = true)
and in referenced entity i.e. Pages we want foreign key DOCUMENT_ID, so we have to define it using
#ManyToOne
#JoinColumn(name="DOCUMENT_ID")

JPA EclipseLink oneToMany Derived Ids Fail

Hello I'm trying to make an example of persistence of a OneToMany relationship in which I get the following error:
Exception Description: Invalid composite primary key specification. The names of the primary key fields or properties in the primary key class [entitys.OrderItemPK] and those of the entity bean class [class entitys.OrderItem] must correspond and their types must be the same. Also, ensure that you have specified ID elements for the corresponding attributes in XML and/or an #Id on the corresponding fields or properties of the entity class.
Note: I'm using EclipseLink and MySQL DB
The entities:
#Entity
public class CustomerOrder implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "idOrder")
private Integer idOrder;
#Basic(optional = false)
#Column(name = "orderText")
private String orderText;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "customerOrder")
private Collection<OrderItem> orderItemCollection;
public CustomerOrder() {
}
}
#Entity
#IdClass(OrderItemPK.class)
public class OrderItem implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
protected OrderItemPK orderItemPK;
#Basic(optional = false)
#Column(name = "itemDesc")
private String itemDesc;
#Id
#ManyToOne(optional = false)
#JoinColumns({
#JoinColumn(name="idOrder", referencedColumnName="idOrder"),
#JoinColumn(name="ItemNumber", referencedColumnName="ItemNumber")
})
//#JoinColumn(name = "idOrder", referencedColumnName = "idOrder", insertable = false, updatable = false)
private CustomerOrder customerOrder;
private CustomerOrder customerOrder;
public OrderItem() {
this.orderItemPK = new OrderItemPK();
}
}
#Embeddable
public class OrderItemPK implements Serializable {
#Basic(optional = false)
#Column(name = "idOrder")
private int idOrder;
#Basic(optional = false)
#Column(name = "itemNumber")
private int itemNumber;
public OrderItemPK() {
}
}
The test Source:
public static void main(String[] args) {
factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
EntityManager em = factory.createEntityManager();
em.getTransaction().begin();
// Fill the items fileds
OrderItem item = new OrderItem();
item.setItemDesc("Item Text");
// Fill the orders fields
CustomerOrder order = new CustomerOrder();
order.setOrderText("Order text");
// Fill the relationship fields
order.getOrderItemCollection().add(item);
item.setCustomerOrder(order);
em.persist(order);
em.getTransaction().commit();
}
I have no idea what I'm doing wrong, any suggestions are welcome.
Well i managed to solve the problem by removing idClass annotation and adding the #MapId
heres the final code:
#Entity
#Table(name = "Orders")
public class CustomerOrder implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "idOrder")
private Integer idOrder;
#Basic(optional = false)
#Column(name = "orderText")
private String orderText;
#OneToMany(mappedBy = "customerOrder", cascade = CascadeType.ALL)
private Collection<OrderItem> orderItemCollection;
public CustomerOrder() {
}
#Entity
#Table(name = "OrdersItems")
public class OrderItem implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
protected OrderItemPK orderItemPK;
#Basic(optional = false)
#Column(name = "itemDesc")
private String itemDesc;
#MapsId("idOrder")
#ManyToOne(optional = false)
#JoinColumn(name = "idOrder", referencedColumnName = "idOrder", nullable = false)
private CustomerOrder customerOrder;
public OrderItem() {
this.orderItemPK = new OrderItemPK();
}
#Embeddable
public class OrderItemPK implements Serializable {
#Basic(optional = false)
#Column(name = "idOrder")
private int idOrder;
#Basic(optional = false)
#Column(name = "itemNumber")
private int itemNumber;
public OrderItemPK() {
}
public static void main(String[] args) {
factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
EntityManager em = factory.createEntityManager();
em.getTransaction().begin();
// Fill the order item
OrderItem item = new OrderItem();
item.getOrderItemPK().setItemNumber(1);
item.setItemDesc("Product Name");
// Fill the order
CustomerOrder order = new CustomerOrder();
order.setOrderText("Testing");
// Create relationship
order.getOrderItemCollection().add(item);
item.setCustomerOrder(order);
// Persist
em.persist(order);
em.getTransaction().commit();
}
But i can't get it work with IdClass, here's the source
#Embeddable
public class OrderItemPK implements Serializable {
#Basic(optional = false)
#Column(name = "idOrder")
private Integer idOrder;
#Basic(optional = false)
#Column(name = "ItemNumber")
private Integer itemNumber;
public OrderItemPK() {
}
#Entity
#IdClass(OrderItemPK.class)
public class OrderItem implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name = "itemNumber")
private Integer itemNumber;
#Basic(optional = false)
#Column(name = "itemDesc")
private String itemDesc;
#MapsId("idOrder")
#ManyToOne(optional = false)
#JoinColumn(name = "idOrder", referencedColumnName = "idOrder", nullable = false)
private CustomerOrder customerOrder;
public OrderItem() {
}
#Entity
public class CustomerOrder implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "idOrder")
private Integer idOrder;
#Basic(optional = false)
#Column(name = "OrderText")
private String orderText;
#OneToMany(mappedBy = "customerOrder", cascade = CascadeType.ALL)
private Collection<OrderItem> orderItemCollection;
public CustomerOrder() {
this.orderItemCollection = new ArrayList();
}
Use MapsId in OrderItem:
#Entity
public class OrderItem implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
protected OrderItemPK orderItemPK;
#Basic(optional = false)
#Column(name = "itemDesc")
private String itemDesc;
#MapsId("idOrder")
#ManyToOne(optional = false)
#JoinColumn(name = "idOrder", referencedColumnName = "idOrder")
private CustomerOrder customerOrder;
}
An alternative is to remove the embedded id and use an ID class:
#Entity
#IdClass(OrderItemPK.class)
public class OrderItem implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name = "itemNumber")
private int itemNumber;
#Basic(optional = false)
#Column(name = "itemDesc")
private String itemDesc;
#Id
#ManyToOne(optional = false)
#JoinColumn(name = "idOrder", referencedColumnName = "idOrder")
private CustomerOrder customerOrder;
}
public class OrderItemPK implements Serializable {
//name of the relation in the entity, but same type as the CustomerOrder PK.
int customerOrder;
int itemNumber;
public OrderItemPK() {
}
}

Mapping this relationship with 2 entities using the same entity

I´m making the model classes using Hibernate, but I don´t know what to do with this kind of relationship.
I have three tables.
Adrress, employee and person.
One emplooye can have one adrress and one person can have one addrress.
I don´t know how map.
Because I thought to use embedded annotattion but doesn´t work.
First is to map my class, I need to put this two entities in address class?
What kind of annotattion i need to use?
I use a superclass with id property and every class extends.
I´m using mysql
my person class
#Entity
#Table(name = "destinatario")
public class Destinatario extends Persistent {
private static final long serialVersionUID = -7091318100871934315L;
#ManyToOne(cascade = CascadeType.PERSIST)
#JoinColumn(name = "endereco_id", referencedColumnName = "id")
private Endereco endereco;
#NotNull
#Size(max = 60)
#Column(name = "razao_social")
private String razaoSocial;
#NotNull
#Size(max = 14)
#Column(name = "inscricao_estadual")
private String inscricaoEstadual;
#Size(max = 9)
#Column(name = "inscricao_suframa")
private String inscricaoSuframa;
#Size(max = 60)
#Column(name = "email")
private String email;
#Size(max = 14)
#Column(name = "cnpj")
private String cnpj;
#Size(max = 11)
#Column(name = "cpf")
private String cpf;
#OneToMany
#JoinColumn(name = "destinatario_id")
private List<NotaFiscal> notaFiscais;
}
my address class
#Entity
#Table(name = "endereco")
public class Endereco extends Persistent {
private static final long serialVersionUID = -3308931308130690090L;
public enum UF {
AC("AC", "Acre"),
AL("AL", "Alagoas"),
AP("AP", "Amapá"),
AM("AM", "Amazonas"),
BA("BA", "Bahia"),
CE("CE", "Ceara"),
DF("DF", "Distrito Federal"),
ES("ES", "Espirito Santo"),
GO("GO", "Goiás"),
MA("MA", "Maranhão"),
MT("MT", "Mato Grosso"),
MS("MS", "Mato Grosso do Sul"),
MG("MG", "Minas Gerais"),
PA("PA", "Pará"),
PB("PB", "Paraíba"),
PR("PR", "Paraná"),
PE("PE", "Pernambuco"),
PI("PI", "Piauí"),
RJ("RJ", "Rio de Janeiro"),
RN("RN", "Rio Grande do Norte"),
RS("RS", "Rio Grande do Sul"),
RO("RO", "Rondônia"),
RR("RR", "Roraima"),
SC("SC", "Santa Catarina"),
SP("SP", "São Paulo"),
SE("SE", "Sergipe"),
TO("TO", "Tocantins");
private final String index;
private String descricao;
private UF(String index, String descricao) {
this.index = index;
this.descricao = descricao;
}
public String getNomeEstado() {
return descricao;
}
public String getIndex() {
return index;
}
}
#NotNull
#Size(max = 60)
#Column(name = "logradouro", unique = true)
private String logradouro;
#NotNull
#Size(max = 60)
#Column(name = "numero", unique = true)
private String numero;
#Size(max = 60)
#Column(name = "complemento")
private String complemento;
#NotNull
#Size(max = 60)
#Column(name = "bairro", unique = true)
private String bairro;
#NotNull
#Size(max = 60)
#Column(name = "municipio", unique = true)
private String municipio;
#Enumerated(EnumType.STRING)
#NotNull
//#Type(type = UFType.TYPE)
#Column(name = "uf", columnDefinition = "varchar", length = 2)
private UF uf;
#NotNull
#Size(max = 8)
#Column(name = "cep", unique = true)
private String cep;
#Size(max = 14)
#Column(name = "telefone")
private String telefone;
}
my methods to run and create a person by xml source
public static void main(String[] args) {
new Processadora().extrairDadosXml("diego");
ArquivoNotaFiscal arquivoNotaFiscal = null;
Destinatario destinatario = null;
NotaFiscal notaFiscal = null;
destinatario = createDestinatario();
arquivoNotaFiscal = createArquivoNotaFiscal();
notaFiscal = createNotaFiscal(arquivoNotaFiscal, emitente, destinatario);
destinatario.setNotaFiscais(Arrays.asList(notaFiscal));
DestinatarioDAO<Destinatario> destinatarioDAO = new DestinatarioDAOImpl<>();
Session session = HibernateSessionFactory.getSession();
Transaction transaction = session.getTransaction();
transaction.begin();
destinatarioDAO.save(destinatario);
transaction.commit();
}
private static Destinatario createDestinatario() {
Destinatario destinatario = new Destinatario();
Endereco endereco = new Endereco();
endereco.setLogradouro(nFeProc.getNfe().getInfNFe().getDestinatario().getEndereco().getLogradouro());
endereco.setNumero(nFeProc.getNfe().getInfNFe().getDestinatario().getEndereco().getNumero());
endereco.setBairro(nFeProc.getNfe().getInfNFe().getDestinatario().getEndereco().getBairro());
endereco.setComplemento(nFeProc.getNfe().getInfNFe().getDestinatario().getEndereco().getComplemento());
endereco.setCep(nFeProc.getNfe().getInfNFe().getDestinatario().getEndereco().getCep());
endereco.setMunicipio(nFeProc.getNfe().getInfNFe().getDestinatario().getEndereco().getMunicipio());
endereco.setUf(UF.valueOf(nFeProc.getNfe().getInfNFe().getDestinatario().getEndereco().getUF()));
endereco.setTelefone(nFeProc.getNfe().getInfNFe().getDestinatario().getEndereco().getTelefone());
destinatario.setEndereco(endereco);
destinatario.setRazaoSocial(nFeProc.getNfe().getInfNFe().getDestinatario().getRazaoSocial());
destinatario.setInscricaoEstadual(nFeProc.getNfe().getInfNFe().getDestinatario().getInscricaoEstadual());
destinatario.setInscricaoSuframa(nFeProc.getNfe().getInfNFe().getDestinatario().getInscricaoSuframa());
destinatario.setEmail(nFeProc.getNfe().getInfNFe().getDestinatario().getEmail());
destinatario.setCnpj(nFeProc.getNfe().getInfNFe().getDestinatario().getCnpj());
destinatario.setCpf(nFeProc.getNfe().getInfNFe().getDestinatario().getCpf());
return destinatario;
}
my database have foreign key constraint, I´m using mysql
I found my problem, I was saving only one object, because I thought if I use the save for the object who contains other it will save, but I need before save the address and later the person.
So this way everthing worked.