简体   繁体   English

使用 Spring + Thymeleaf 时出现 java.lang.StackOverflowError

[英]Getting java.lang.StackOverflowError while using Spring + Thymeleaf

I'm developing a facturation system using Java Spring Boot + Thymeleaf.我正在使用 Java Spring Boot + Thymeleaf 开发一个制造系统。 I'm getting this error:我收到此错误:

>Whitelabel Error Page
>This application has no explicit mapping for /error, so you are seeing this as a fallback.

>Wed Mar 04 10:58:26 ART 2020
>There was an unexpected error (type=Internal Server Error, status=500).
>No message available
>java.lang.StackOverflowError

I use two Controllers to handle the filling of the bill that is divided in 3 tables: Encabezado(header)Items and Pie (foot) Class Encabezado:我使用两个控制器来处理分为 3 个表的账单的填写:Encabezado(header)Items 和 Pie (foot) 类 Encabezado:

@EqualsAndHashCode
@Entity
@Table(name="facturas_encabezado")
public class Encabezado implements Serializable {

    private static final long serialVersionUID = -3479505724865821556L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)

    private Long id;
    @NotNull
    private Timestamp fecha;
    @NotNull
    @Size(min = 1,max = 11)
    private String numero;
    @Nullable
    private String letra;
    @NotNull
    @OneToOne
    private Cliente cliente;
    @OneToMany(mappedBy = "encabezado")
    private List<Item> items;
    @NotNull
    private Boolean anulado=false;

Class Item类项目

@Entity
@Table(name="facturas_items")
public class Item implements Serializable {

    private static final long serialVersionUID = -3560761383569266746L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)

    private Long id;
    @OneToOne
    @JoinColumn(name = "productos_id")
    private Producto producto;
    @ManyToOne
    @JoinColumn(name = "facturas_encabezado_id")
    private Encabezado encabezado;
    private BigDecimal cantidad;
    private BigDecimal precioUnitario;  
    private BigDecimal subTotal;

HeaderController头控制器

 @Controller
@RequestMapping("/factura")
public class EncabezadoControl {
    @Autowired
    private ClienteRepositorio clienterepository;
    @Autowired
    private ProductoRepositorio productorepository;
    @Autowired
    private EncabezadoRepositorio encabezadorepository;

    @GetMapping("/creacion_factura")
    public String creacionFactura(Encabezado encabezado,Errors errors,Model model ) {
        List<Cliente> clientes;
        clientes=clienterepository.findByVisibilidad();
        model.addAttribute("titulo", "Listado de Clientes");
        model.addAttribute("data", clientes);
        model.addAttribute("encabezado",new Encabezado());

        return "facturas/creacion_factura";
    }

    @PostMapping(value = "/creacion_factura")
    public String guardarFactura(Encabezado encabezado,Errors errors,Model model) {
        Timestamp timestamp = new Timestamp(System.currentTimeMillis()); //Instanciamos fecha actual para el encabezado de factura.
        encabezado.setFecha(timestamp);
        model.addAttribute("facturaInfo",encabezado);
        System.out.println(encabezado);

        if(encabezado.getId()==null){
            encabezadorepository.save(encabezado);
        }
        Long id=encabezado.getId();
        return "redirect:/factura/establecer_productos/"+id;
    }

}

ItemController项目控制器

  @Controller
@RequestMapping("/factura")
public class ItemControl {
    @Autowired
    private ItemRepositorio itemrepository;
    @Autowired
    private ProductoRepositorio productorepository;
    @Autowired
    private EncabezadoRepositorio encabezadorepository;

    @GetMapping(value = "/establecer_productos/{id}")
    public String indicarProductos(Model model, @PathVariable Long id){

        List<Producto> listaproductos=null;
        listaproductos=productorepository.findByEstado();

        model.addAttribute("titulo", "Selección de Productos");
        model.addAttribute("productos",listaproductos);

        model.addAttribute("item", new Item());


        return "facturas/seleccion_productos";
    }


    @PostMapping(value = "/establecer_productos/{ided}")
    public String procesarProductos(@PathVariable Long ided, Item item,Model model){

        if(item.getId()==null) {
            BigDecimal cantidad = item.getCantidad();
            BigDecimal precio = item.getPrecioUnitario();
            item.setSubTotal(cantidad.multiply(precio));
            item.setEncabezado(encabezadorepository.getOne(ided));
            itemrepository.save(item);
        }
        System.out.println("ITEM\n\n\n"+item+"\n\n\n");
        return "redirect:/factura/establecer_productos/"+ided;
    }

}

First step view: Header creation第一步视图:标题创建

<div class="container">

        <form method="post" th:action="@{/factura/creacion_factura}" th:object="${encabezado}">
            <br/>
            <h2>Introduzca los datos de la Factura</h2>
            <hr/>
            <div class="row">
                <div class="col-md-3">
                    <h3>Cliente</h3>
                </div>
                <div class="col-md-6">
                    <select name="cliente" class="form-control form-control-lg" th:field="*{cliente}">
                        <option th:each="cliente : ${data}" th:value="${cliente.id}" th:text="${cliente.nombre}"></option>

                    </select>
                </div>
                <div class="col-md-3"></div>
            </div>

            <div class="row" th:class="${#fields.hasErrors('numero')} ? 'form-group row has-danger' : (*{numero == null} ? 'form-group row' : 'form-group row has-success')">
                <div class="col-md-3">
                    <h3>Numero Factura</h3>
                </div>
                <div class="col-md-6">
                    <div class="input-group">
                        <input th:field="*{numero}" type="text" th:class="${#fields.hasErrors('numero')} ? 'form-control form-control-danger' : (*{numero == null} ? 'form-control' : 'form-control form-control-success')" placeholder="Ingrese el numero de factura" required="required"/>
                    </div>
                    <div th:if="${#fields.hasErrors('numero')}" class="form-control-feedback">El número debe tener entre 1 y 11 caracteres</div>
                </div>
                <div class="col-md-3"></div>
            </div>

            <div class="row" th:class="${#fields.hasErrors('letra')} ? 'form-group row has-danger' : (*{letra == null} ? 'form-group row' : 'form-group row has-success')">
                <div class="col-md-3">
                    <h3>Categoria Factura</h3>
                </div>
                <div class="col-md-6">
                    <select class="form-control form-control-lg" th:field="*{letra}" >
                        <option th:value="'A'"th:text="A"></option>
                        <option th:value="'B'"th:text="B"></option>
                        <option th:value="'C'"th:text="C"></option>
                    </select>
                </div>
                <div class="col-md-3"></div>
            </div>


            <div class="form-group row">
                <div class="col-sm-2"></div>
                <div class="col-sm-6">
                    <button type="submit" class="btn btn-primary btn-md btn-block">Siguiente Paso</button>
                </div>
            </div>

        </form>
    </div>

Second step: Add Items view第二步:添加项目视图

<div class="container">

    <form method="post" th:action="@{/factura/establecer_productos/{id}(id=${id})}" th:object="${item}">
        <br/>
        <h2>Seleccione los Productos de la Factura</h2>
        <hr/>

        <div class="row">
            <div class="col-md-3">
                <h3>Productos</h3>
            </div>
            <div class="col-md-6">
                <select class="form-control form-control-lg" name="producto" th:field="*{producto}">
                    <option th:each="producto : ${productos}"  th:value="${producto.id}" th:text="${producto.nombre}"></option>
                z</select>
            </div>
            <div class="col-md-3"></div>
        </div>

        <div class="row">
                <div class="col-md-3">
                    <h4>Cantidad</h4>
                </div>
                <div class="col-md-6">
                    <div class="input-group">
                        <input class="form-control text-center" th:field="*{cantidad}" type="text" th:class="${#fields.hasErrors('cantidad')} ? 'form-control form-control-danger' : (*{cantidad == null} ? 'form-control' : 'form-control form-control-success')" placeholder="introduzca cantidad a comprar" required="required"/>
                    </div>
                    <div th:if="${#fields.hasErrors('cantidad')}" class="form-control-feedback">La cantidad es obligatoria</div>
                </div>
                <div class="col-md-3"></div>
        </div>

        <div class="row">

            <div class="col-md-3">
                <h4>Precio Unitario</h4>
            </div>
            <div class="col-md-6">
                <div class="input-group">
                    <input class="form-control text-center" th:field="*{precioUnitario}" type="text" th:class="${#fields.hasErrors('precioUnitario')} ? 'form-control form-control-danger' : (*{precioUnitario == null} ? 'form-control' : 'form-control form-control-success')" placeholder="introduzca precio unitario" required="required"/>
                </div>
                <div th:if="${#fields.hasErrors('precioUnitario')}" class="form-control-feedback">El precio es obligatoria</div>
            </div>
            <div class="col-md-3"></div>

        </div>

        <div class="form-group row">
            <div class="col-sm-2"></div>
            <div class="col-sm-6">
                <button type="submit" class="btn btn-primary btn-md btn block">Siguiente</button>
            </div>
        </div>

    </form>
</div>

Compiling the execution goes well.编译执行很顺利。 The bill header is correctly saved on the db but the problem appears when we reach the second step: The item is saved crashing the entire execution.帐单标题正确保存在数据库中,但当我们到达第二步时出现问题:保存项目导致整个执行崩溃。 Any solutions?任何解决方案?

Don't use @Data, @ToString, @EqualsAndHashCode with JPA they can lead to StackOverflowErrors and other problem.不要将@Data, @ToString, @EqualsAndHashCode与 JPA 一起使用@Data, @ToString, @EqualsAndHashCode它们会导致 StackOverflowErrors 和其他问题。

Please read: https://mdeinum.github.io/2019-02-13-Lombok-Data-Ojects-Arent-Entities/请阅读: https : //mdeinum.github.io/2019-02-13-Lombok-Data-Ojects-Arent-Entities/

And here how these methods should be implemented: https://vladmihalcea.com/the-best-way-to-implement-equals-hashcode-and-tostring-with-jpa-and-hibernate/这里应该如何实施这些方法: https : //vladmihalcea.com/the-best-way-to-implement-equals-hashcode-and-tostring-with-jpa-and-hibernate/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM