API REST java persistence onetomany

0

Hello friends, I'm going back to consult you again, and from now on I thank those who will take the time to respond and help me. Well I'm new in all this java, I tell you that I'm trying to generate a api rest with two related tables, I'm occupying netbeans with maven and deployando in payara with a postgress database hosted in heroku.

My problem is that I'm getting a java.lang.StackOverflowError I'm just trying the general GET method, that is, I want to drag all the branches and employees in a json here, I leave my configuration.

first the persistence employee

package root.persistence.entities;

import java.io.Serializable;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import javax.xml.bind.annotation.XmlRootElement;

/**
*
* @author rodrigo
*/
@Entity
@Table(name = "empleados")
@XmlRootElement
@NamedQueries({
@NamedQuery(name = "Empleado.findAll", query = "SELECT e FROM Empleado e")
, @NamedQuery(name = "Empleado.findById", query = "SELECT e FROM Empleado e WHERE e.id = :id")
, @NamedQuery(name = "Empleado.findByNombre", query = "SELECT e FROM Empleado e WHERE e.nombre = :nombre")
, @NamedQuery(name = "Empleado.findByApellido", query = "SELECT e FROM Empleado e WHERE e.apellido = :apellido")
, @NamedQuery(name = "Empleado.findByRut", query = "SELECT e FROM Empleado e WHERE e.rut = :rut")
, @NamedQuery(name = "Empleado.findByPuesto", query = "SELECT e FROM Empleado e WHERE e.puesto = :puesto")})
public class Empleado implements Serializable {

private static final long serialVersionUID = 1L;
@Id
@Basic(optional = false)
@NotNull
@Column(name = "id")
private Integer id;
@Size(max = 2147483647)
@Column(name = "nombre")
private String nombre;
@Size(max = 2147483647)
@Column(name = "apellido")
private String apellido;
@Size(max = 2147483647)
@Column(name = "rut")
private String rut;
@Size(max = 2147483647)
@Column(name = "puesto")
private String puesto;
@JoinColumn(name = "idsucursal", referencedColumnName = "id")
@ManyToOne(fetch = FetchType.EAGER)
private Sucursal idsucursal;

public Empleado() {
}

public Empleado(Integer id) {
    this.id = id;
}

public Integer getId() {
    return id;
}

public void setId(Integer id) {
    this.id = id;
}

public String getNombre() {
    return nombre;
}

public void setNombre(String nombre) {
    this.nombre = nombre;
}

public String getApellido() {
    return apellido;
}

public void setApellido(String apellido) {
    this.apellido = apellido;
}

public String getRut() {
    return rut;
}

public void setRut(String rut) {
    this.rut = rut;
}

public String getPuesto() {
    return puesto;
}

public void setPuesto(String puesto) {
    this.puesto = puesto;
}

public Sucursal getIdsucursal() {
    return idsucursal;
}

public void setIdsucursal(Sucursal idsucursal) {
    this.idsucursal = idsucursal;
}

@Override
public int hashCode() {
    int hash = 0;
    hash += (id != null ? id.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 Empleado)) {
        return false;
    }
    Empleado other = (Empleado) object;
    if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
        return false;
    }
    return true;
}

@Override
public String toString() {
    return "root.persistence.entities.Empleado[ id=" + id + " ]";
}

}

and now my persistence class Branch     / *     * To change this license header, choose License Headers in Project    Properties.     * To change this template file, choose Tools | Templates     * and open the template in the editor.     * /    package root.persistence.entities;

import java.io.Serializable;
import java.util.List;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;

/**
*
* @author rodrigo
*/
@Entity
@Table(name = "sucursales")
@XmlRootElement
@NamedQueries({
@NamedQuery(name = "Sucursal.findAll", query = "SELECT s FROM Sucursal s")
, @NamedQuery(name = "Sucursal.findById", query = "SELECT s FROM Sucursal s WHERE s.id = :id")
, @NamedQuery(name = "Sucursal.findByComuna", query = "SELECT s FROM Sucursal s WHERE s.comuna = :comuna")
, @NamedQuery(name = "Sucursal.findByDireccion", query = "SELECT s FROM Sucursal s WHERE s.direccion = :direccion")})
public class Sucursal implements Serializable {

private static final long serialVersionUID = 1L;
@Id
@Basic(optional = false)
@NotNull
@Column(name = "id")
private Integer id;
@Size(max = 2147483647)
@Column(name = "comuna")
private String comuna;
@Size(max = 2147483647)
@Column(name = "direccion")
private String direccion;
@OneToMany(mappedBy = "idsucursal", fetch = FetchType.EAGER)
private List<Empleado> empleadoList;

public Sucursal() {
}

public Sucursal(Integer id) {
    this.id = id;
}

public Integer getId() {
    return id;
}

public void setId(Integer id) {
    this.id = id;
}

public String getComuna() {
    return comuna;
}

public void setComuna(String comuna) {
    this.comuna = comuna;
}

public String getDireccion() {
    return direccion;
}

public void setDireccion(String direccion) {
    this.direccion = direccion;
}

@XmlTransient
public List<Empleado> getEmpleadoList() {
    return empleadoList;
}

public void setEmpleadoList(List<Empleado> empleadoList) {
    this.empleadoList = empleadoList;
}

@Override
public int hashCode() {
    int hash = 0;
    hash += (id != null ? id.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 Sucursal)) {
        return false;
    }
    Sucursal other = (Sucursal) object;
    if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
        return false;
    }
    return true;
}

@Override
public String toString() {
    return "root.persistence.entities.Sucursal[ id=" + id + " ]";
}

}  my POM.xml file

<?xml version="1.0" encoding="UTF-8"?>

link

<groupId>com.mycompany</groupId>
<artifactId>asucursalesrest</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>

<name>asucursalesrest</name>

<properties>
    <endorsed.dir>${project.build.directory}/endorsed</endorsed.dir>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<dependencies>
    <dependency>
        <groupId>org.eclipse.persistence</groupId>
        <artifactId>eclipselink</artifactId>
        <version>2.5.2</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>postgresql</groupId>
         <artifactId>postgresql</artifactId>
     <version>9.1-901-1.jdbc4</version>
    </dependency>
    <dependency>
        <groupId>org.eclipse.persistence</groupId>
        <artifactId>org.eclipse.persistence.jpa.modelgen.processor</artifactId>
        <version>2.5.2</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>javax</groupId>
        <artifactId>javaee-web-api</artifactId>
        <version>7.0</version>
        <scope>provided</scope>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.1</version>
            <configuration>
                <source>1.7</source>
                <target>1.7</target>
                <compilerArguments>
                    <endorseddirs>${endorsed.dir}</endorseddirs>
                </compilerArguments>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-war-plugin</artifactId>
            <version>2.3</version>
            <configuration>
                <failOnMissingWebXml>false</failOnMissingWebXml>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-dependency-plugin</artifactId>
            <version>2.6</version>
            <executions>
                <execution>
                    <phase>validate</phase>
                    <goals>
                        <goal>copy</goal>
                    </goals>
                    <configuration>
                        <outputDirectory>${endorsed.dir}</outputDirectory>
                        <silent>true</silent>
                        <artifactItems>
                            <artifactItem>
                                <groupId>javax</groupId>
                                <artifactId>javaee-endorsed-api</artifactId>
                                <version>7.0</version>
                                <type>jar</type>
                            </artifactItem>
                        </artifactItems>
                    </configuration>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>fish.payara.maven.plugins</groupId>
            <artifactId>payara-micro-maven-plugin</artifactId>
            <version>1.0.1</version>
        </plugin>
    </plugins>
</build>

I have an entry point to my api APPconfig

package root.services;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;




@ApplicationPath("/api")
public class AppConfig extends Application{

}

and a class from which I generate the methods, so far I only did the get method, since I wanted to try but it has not worked. configure eager, because in theory I should call all the children (employees) of a branch .

package root.services;

import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import root.persistence.entities.Empleado;
import root.persistence.entities.Sucursal;

@Path("/sucursales")
public class SucursalesREST {

EntityManagerFactory emf = Persistence.createEntityManagerFactory("UP_Sucursales");
EntityManager em;

@GET
@Produces(MediaType.APPLICATION_JSON)
public Response listarTodo() {

    em = emf.createEntityManager();


List<Sucursal> lista = em.createNamedQuery("Sucursal.findAll").getResultList();

return Response.ok().entity(lista).build();

} }  but when doing the tests I get the following error

I know it might be a mistake for beginners, because as I told you, I'm new to java, and the APIs and the use of persistence, I hope someone can help me since I've been with the same error for days, greetings

    
asked by Rodrigo 09.12.2018 в 20:31
source

1 answer

0

Rodrigo, I think your problem has to do with what you're writing about the relationship between employees and branches like EAGER on both sides of the relationship. When looking for branches, they bring their employees and they bring them back to the branches, the cycle continues indefinitely until you run out of memory.

I would recommend using EAGER on only one side of the relationship. Keep in mind that the ratio @ManyToOne is EAGER by default so, if you want the list of employees to maintain this property, you will have to explicitly define the branch as LAZY.

I hope this helps you:)

    
answered by 10.12.2018 в 00:12