Java / Spring - объект ссылается на несохраненный временный экземпляр - PullRequest
0 голосов
/ 26 марта 2019

Ну, моя проблема связана с тем, когда я пытаюсь сохранить сущность (Parade), у которой есть коллекция другой сущности (AcmeFloat), используя соответствующий метод CRUD по умолчанию в удобном хранилище (код прилагается ниже). Когда он достигает метода save (), он генерирует исключение.

Я пытался сохранить соответствующие объекты класса AcmeFloat, которые необходимо обновить вручную, но, что бы я ни делал (сохранить ли сначала обновленный парад, а затем обновить и сохранить каждый AcmeFloat или вывернуть наизнанку), возникает исключение.

Итак, я вошел в Переполнение стека, и решение, которое я нашел, это поместить cascade = CascadeType.ALL внутри аннотации @ManyToMany, но безуспешно. Я также пытался сделать обе вещи, что тоже не получается.

Вот код:

Парад (Класс домена):

package domain;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;

import javax.persistence.Access;
import javax.persistence.AccessType;
import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.validation.Valid;
import javax.validation.constraints.Pattern;

import org.hibernate.validator.constraints.NotBlank;
import org.springframework.format.annotation.DateTimeFormat;

@Entity
@Access(AccessType.PROPERTY)
public class Parade extends DomainEntity {

    // Fields -----------------------------------------------------------------

    private String                  title;
    private String                  description;
    private Date                    moment;
    private String                  ticker;
    private boolean                 isDraft;

    // Relationships ----------------------------------------------------------

    private Brotherhood             brotherhood;
    private Collection<AcmeFloat>   acmeFloats;


    // Field access methods ---------------------------------------------------

    @NotBlank
    public String getTitle() {
        return this.title;
    }

    public void setTitle(final String title) {
        this.title = title;
    }

    @NotBlank
    public String getDescription() {
        return this.description;
    }

    public void setDescription(final String description) {
        this.description = description;
    }

    @Temporal(TemporalType.TIMESTAMP)
    @DateTimeFormat(pattern = "dd/MM/yyyy HH:mm")
    public Date getMoment() {
        return this.moment;
    }

    public void setMoment(final Date moment) {
        this.moment = moment;
    }

    @NotBlank
    @Pattern(regexp = "^([\\d]){6}-([A-Z]){5}$")
    @Column(unique = true)
    public String getTicker() {
        return this.ticker;
    }

    public void setTicker(final String ticker) {
        this.ticker = ticker;
    }

    @Basic
    public boolean getIsDraft() {
        return this.isDraft;
    }

    public void setIsDraft(final boolean isDraft) {
        this.isDraft = isDraft;
    }

    // Relationship access methods --------------------------------------------

    @Valid
    @ManyToOne(optional = true)
    public Brotherhood getBrotherhood() {
        return this.brotherhood;
    }

    public void setBrotherhood(final Brotherhood brotherhood) {
        this.brotherhood = brotherhood;
    }

    @Valid
    @ManyToMany(mappedBy = "parades", cascade = CascadeType.ALL)
    public Collection<AcmeFloat> getAcmeFloats() {
        return new ArrayList<AcmeFloat>(this.acmeFloats);
    }

    public void setAcmeFloats(final Collection<AcmeFloat> acmeFloats) {
        this.acmeFloats = acmeFloats;
    }

}

AcmeFloat (класс домена):

package domain;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import javax.persistence.Access;
import javax.persistence.AccessType;
import javax.persistence.CascadeType;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;

import org.hibernate.validator.constraints.NotBlank;

@Entity
@Access(AccessType.PROPERTY)
public class AcmeFloat extends DomainEntity {

    // Fields -----------------------------------------------------------------

    private String              title;
    private String              description;
    private List<String>        pictures;

    // Relationships ----------------------------------------------------------

    private Collection<Parade>  parades;
    private Brotherhood         brotherhood;


    // Field access methods ---------------------------------------------------

    @NotNull
    @NotBlank
    public String getTitle() {
        return this.title;
    }

    public void setTitle(final String title) {
        this.title = title;
    }

    @NotNull
    @NotBlank
    public String getDescription() {
        return this.description;
    }

    public void setDescription(final String description) {
        this.description = description;
    }

    //Optional
    //@URL
    @NotNull
    @ElementCollection
    public List<String> getPictures() {
        return this.pictures;
    }

    public void setPictures(final List<String> pictures) {
        this.pictures = pictures;
    }

    // Relationship access methods --------------------------------------------

    @ManyToMany(cascade = CascadeType.ALL)
    @Valid
    public Collection<Parade> getParades() {
        return this.parades;
    }

    public void setParades(final Collection<Parade> parades) {
        this.parades = new ArrayList<Parade>(parades);
    }
    @ManyToOne
    @Valid
    public Brotherhood getBrotherhood() {
        return this.brotherhood;
    }

    public void setBrotherhood(final Brotherhood brotherhood) {
        this.brotherhood = brotherhood;
    }

}

ParadeForm (Объект формы):

package forms;

import java.util.Collection;
import java.util.Date;

import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.validation.constraints.NotNull;

import org.hibernate.validator.constraints.NotBlank;
import org.hibernate.validator.constraints.Range;
import org.springframework.format.annotation.DateTimeFormat;

import domain.AcmeFloat;

public class ParadeForm {

    // Fields -----------------------------------------------------------------

    private int                     id;

    private String                  title;
    private String                  description;
    private Date                    moment;

    // Relationships ----------------------------------------------------------

    private Collection<AcmeFloat>   acmeFloats;


    // Field access methods ---------------------------------------------------

    @Range(min = 0)
    public int getId() {
        return this.id;
    }

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

    @NotBlank
    public String getTitle() {
        return this.title;
    }

    public void setTitle(final String title) {
        this.title = title;
    }

    @NotBlank
    public String getDescription() {
        return this.description;
    }

    public void setDescription(final String description) {
        this.description = description;
    }

    @Temporal(TemporalType.TIMESTAMP)
    @DateTimeFormat(pattern = "dd/MM/yyyy HH:mm")
    public Date getMoment() {
        return this.moment;
    }

    public void setMoment(final Date moment) {
        this.moment = moment;
    }

    // Relationship access methods --------------------------------------------

    @NotNull
    public Collection<AcmeFloat> getAcmeFloats() {
        return this.acmeFloats;
    }

    public void setAcmeFloats(final Collection<AcmeFloat> acmeFloats) {
        this.acmeFloats = acmeFloats;
    }

}

ParadeRepository:

package repositories;

import java.util.Date;
import java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;

import domain.Parade;

@Repository
public interface ParadeRepository extends JpaRepository<Parade, Integer> {

    @Query("select p from Parade p where p.ticker like ?1")
    List<Parade> findByTicker(String ticker);

    @Query("select p from Parade p where p.moment < ?1 and p.isDraft = false")
    List<Parade> findBeforeDate(Date date);

    @Query("select p from Parade p where p.isDraft = false")
    List<Parade> findAllFinal();

    @Query("select p from Parade p where p.isDraft = false and brotherhood.userAccount.id = ?1")
    List<Parade> findAllFinalByBrotherhoodAccountId(int id);

    @Query("select p from Parade p where brotherhood.userAccount.id = ?1")
    List<Parade> findAllByBrotherhoodAccountId(int id);

    @Query("select p from Parade p join p.brotherhood.enrolments e where e.member.id= ?1")
    List<Parade> findPossibleMemberParades(int id);

}

AcmeFloatRepository:

package repositories;

import java.util.Collection;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;

import domain.AcmeFloat;

@Repository
public interface AcmeFloatRepository extends JpaRepository<AcmeFloat, Integer> {

    @Query("select f from AcmeFloat f where f.brotherhood.userAccount.id = ?1")
    Collection<AcmeFloat> findAcmeFloats(int principalId);

}

ParadeService:

package services;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Random;

import javax.validation.ValidationException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.validation.BindingResult;
import org.springframework.validation.Validator;

import repositories.ParadeRepository;
import security.LoginService;
import domain.AcmeFloat;
import domain.Parade;
import forms.ParadeForm;

@Service
@Transactional
public class ParadeService {

    ////////////////////////////////////////////////////////////////////////////////
    // Managed repository

    @Autowired
    private ParadeRepository    paradeRepository;

    ////////////////////////////////////////////////////////////////////////////////
    // Supporting services

    @Autowired
    private BrotherhoodService      brotherhoodService;

    ////////////////////////////////////////////////////////////////////////////////
    // Supporting services

    @Autowired
    private Validator               validator;

    ////////////////////////////////////////////////////////////////////////////////
    // Ticker generation fields

    private static final String     TICKER_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    private static final int        TICKER_LENGTH   = 5;
    private final Random            random          = new Random();


    ////////////////////////////////////////////////////////////////////////////////
    // Constructors

    public ParadeService() {
        super();
    }

    ////////////////////////////////////////////////////////////////////////////////
    // CRUD methods

    public Parade create() {
        final Parade parade = new Parade();
        parade.setBrotherhood(this.brotherhoodService.findByUserAccountId(LoginService.getPrincipal().getId()));
        parade.setAcmeFloats(new ArrayList<AcmeFloat>());
        parade.setIsDraft(true);
        parade.setDescription("");
        parade.setTitle("");
        if (parade.getTicker() == null || parade.getTicker().isEmpty()) {
            final Calendar calendar = new GregorianCalendar();
            String dateString = "";
            dateString += String.format("%02d", calendar.get(Calendar.YEAR) % 100);
            dateString += String.format("%02d", calendar.get(Calendar.MONTH) + 1);
            dateString += String.format("%02d", calendar.get(Calendar.DAY_OF_MONTH));
            dateString += "-";
            String ticker;
            do {
                ticker = dateString;
                for (int i = 0; i < ParadeService.TICKER_LENGTH; ++i)
                    ticker += ParadeService.TICKER_ALPHABET.charAt(this.random.nextInt(ParadeService.TICKER_ALPHABET.length()));
            } while (this.paradeRepository.findByTicker(ticker).size() > 0);
            parade.setTicker(ticker);
        }

        return parade;
    }

    public Parade save(final Parade parade) {
        Assert.notNull(parade);
        //final Parade originalParade = this.paradeRepository.findOne(parade.getId());
        //if (originalParade != null)
        Assert.isTrue(parade.getIsDraft());
        Assert.isTrue(parade.getMoment().after(new Date()));

        //TODO: if ticker existe en BBDD, generar nuevo, else, se guarda
        return this.paradeRepository.save(parade);
    }
    public void delete(final Parade parade) {
        Assert.notNull(parade);
        Assert.isTrue(parade.getIsDraft());

        this.paradeRepository.delete(parade);
    }
    public Parade findOne(final int id) {
        return this.paradeRepository.findOne(id);
    }

    public List<Parade> findAll() {
        return this.paradeRepository.findAll();
    }

    ////////////////////////////////////////////////////////////////////////////////
    // Ancillary methods

    public List<Parade> findWithin30Days() {
        final Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.add(Calendar.DATE, 30);
        final Date plus30Days = calendar.getTime();
        return this.paradeRepository.findBeforeDate(plus30Days);
    }

    public List<Parade> findAllByBrotherhoodAccountId(final int id) {
        return this.paradeRepository.findAllByBrotherhoodAccountId(id);
    }

    public List<Parade> findAllFinalByBrotherhoodAccountId(final int id) {
        return this.paradeRepository.findAllFinalByBrotherhoodAccountId(id);
    }

    public List<Parade> findAllFinal() {
        return this.paradeRepository.findAllFinal();
    }

    public List<Parade> findPossibleMemberParades(final int memberId) {
        return this.paradeRepository.findPossibleMemberParades(memberId);
    }

    public Parade reconstruct(final ParadeForm paradeForm, final BindingResult binding) {
        Parade result;

        if (paradeForm.getId() == 0)
            result = this.create();
        else
            result = this.paradeRepository.findOne(paradeForm.getId());

        result.setTitle(paradeForm.getTitle());
        result.setDescription(paradeForm.getDescription());
        result.setMoment(paradeForm.getMoment());
        result.setAcmeFloats(paradeForm.getAcmeFloats());

        this.validator.validate(result, binding);
        this.paradeRepository.flush();
        if (binding.hasErrors())
            throw new ValidationException();

        return result;
    }

}

AcmeFloatService:

package services;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import repositories.AcmeFloatRepository;
import domain.AcmeFloat;
import domain.Parade;

@Service
@Transactional
public class AcmeFloatService {

    ////////////////////////////////////////////////////////////////////////////////
    // Managed repository

    @Autowired
    private AcmeFloatRepository acmeFloatRepository;


    ////////////////////////////////////////////////////////////////////////////////
    // Supporting services

    ////////////////////////////////////////////////////////////////////////////////
    // Constructors

    public AcmeFloatService() {
        super();
    }

    ////////////////////////////////////////////////////////////////////////////////
    // CRUD methods

    public AcmeFloat create() {
        final AcmeFloat result = new AcmeFloat();

        // set fields
        result.setTitle("");
        result.setDescription("");
        result.setPictures(new ArrayList<String>());
        // set relationships
        result.setParades(new ArrayList<Parade>());
        result.setBrotherhood(null);

        return result;
    }

    public AcmeFloat save(final AcmeFloat acmeFloat) {
        Assert.isTrue(acmeFloat != null);
        return this.acmeFloatRepository.save(acmeFloat);
    }

    public Iterable<AcmeFloat> save(final Iterable<AcmeFloat> acmeFloats) {
        Assert.isTrue(acmeFloats != null);
        return this.acmeFloatRepository.save(acmeFloats);
    }

    public void delete(final AcmeFloat acmeFloat) {
        Assert.isTrue(acmeFloat != null);
        this.acmeFloatRepository.delete(acmeFloat);
    }

    public void delete(final Iterable<AcmeFloat> acmeFloats) {
        Assert.isTrue(acmeFloats != null);
        this.acmeFloatRepository.delete(acmeFloats);
    }

    public AcmeFloat findOne(final int id) {
        return this.acmeFloatRepository.findOne(id);
    }

    public List<AcmeFloat> findAll() {
        return this.acmeFloatRepository.findAll();
    }

    ////////////////////////////////////////////////////////////////////////////////
    // Ancillary methods

    public Collection<AcmeFloat> findAcmeFloats(final int id) {
        return this.acmeFloatRepository.findAcmeFloats(id);
    }

}

ParadeController:

package controllers;

import java.util.Collection;
import javax.validation.Valid;
import javax.validation.ValidationException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.Assert;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import security.LoginService;
import security.UserAccount;
import services.AcmeFloatService;
import services.BrotherhoodService;
import services.ParadeService;
import domain.AcmeFloat;
import domain.Brotherhood;
import domain.Parade;
import forms.ParadeForm;

@Controller
@RequestMapping("/parade")
public class ParadeController extends AbstractController {

    // Services ---------------------------------------------------------------

    @Autowired
    private ParadeService       paradeService;

    @Autowired
    private BrotherhoodService  brotherhoodService;

    @Autowired
    private AcmeFloatService    acmeFloatService;


    // Constructors -----------------------------------------------------------

    public ParadeController() {

    }

    // List -------------------------------------------------------------------

    @RequestMapping(value = "/brotherhood/list", method = RequestMethod.GET)
    public ModelAndView list() {
        final ModelAndView result;
        Collection<Parade> parades;

        parades = this.paradeService.findAllByBrotherhoodAccountId(LoginService.getPrincipal().getId());

        result = new ModelAndView("parade/brotherhood/list");
        result.addObject("parades", parades);
        result.addObject("requestURI", "parade/brotherhood/list.do");

        return result;
    }

    // Create -----------------------------------------------------------------

    @RequestMapping(value = "/brotherhood/create", method = RequestMethod.GET)
    public ModelAndView create() {
        final ModelAndView result;
        Parade parade;

        parade = this.paradeService.create();
        parade.setIsDraft(true);
        result = this.createEditModelAndView(parade, "create");

        return result;
    }

    // Edit -------------------------------------------------------------------

    @RequestMapping(value = "/brotherhood/edit", method = RequestMethod.GET)
    public ModelAndView edit(@RequestParam final int paradeId) {
        ModelAndView result;
        Parade parade;

        parade = this.paradeService.findOne(paradeId);
        Assert.notNull(parade);
        result = this.createEditModelAndView(parade, "edit");

        return result;
    }

    // Save -------------------------------------------------------------------

    @RequestMapping(value = "/brotherhood/edit", method = RequestMethod.POST, params = "save")
    public ModelAndView save(@ModelAttribute("parade") final ParadeForm paradeForm, final BindingResult binding) {
        ModelAndView result;
        Parade parade;
        Parade oldParade;

        parade = this.paradeService.reconstruct(paradeForm, binding);
        oldParade = this.paradeService.findOne(paradeForm.getId());

        try {
             for(AcmeFloat f : parade.getAcmeFloats()){
                Collection<Parade> parades = f.getParades();
                parades.add(parade);
                f.setParades(parades);
                this.acmeFloatService.save(f);
            }
            if(parade.getId() != 0){
                Collection<AcmeFloat> paradesRemoved = oldParade.getAcmeFloats();
                paradesRemoved.removeAll(parade.getAcmeFloats());
                for(AcmeFloat f : paradesRemoved){
                    final Collection<Parade> parades = f.getParades();
                    parades.remove(parade);
                    f.setParades(parades);
                    this.acmeFloatService.save(f);
                }
            }
            this.paradeService.save(parade);
            result = new ModelAndView("redirect:list.do");
        } catch (final ValidationException oops) {
            result = this.createEditModelAndView(parade, "edit");
        } catch (final Throwable oops) {
            result = this.createEditModelAndView(parade, "parade.commit.error", "edit");
        }

        return result;
    }


/*
            final Parade paradeUpdated = this.paradeService.reconstruct(paradeForm, binding);
            Collection<AcmeFloat> paradesRemoved = new ArrayList<>();
            if (paradeForm.getId() != 0)
                paradesRemoved = parade.getAcmeFloats();
            if (paradeUpdated.getId() != 0)
                paradesRemoved.removeAll(paradeUpdated.getAcmeFloats());
            final Parade paradeSaved = this.paradeService.save(paradeUpdated);
            for (final AcmeFloat f : paradeUpdated.getAcmeFloats()) {
                final Collection<Parade> parades = f.getParades();
                parades.add(paradeSaved);
                f.setParades(parades);
                this.acmeFloatService.save(f);
            }
            if (paradeUpdated.getId() != 0)
                for (final AcmeFloat f : paradesRemoved) {
                    final Collection<Parade> parades = f.getParades();
                    parades.remove(parade);
                    f.setParades(parades);
                    this.acmeFloatService.save(f);
*/



    // Delete -----------------------------------------------------------------

    @RequestMapping(value = "/brotherhood/edit", method = RequestMethod.POST, params = "delete")
    public ModelAndView delete(final Parade parade, final BindingResult binding) {
        ModelAndView result;

        try {
            this.paradeService.delete(parade);
            result = new ModelAndView("redirect:list.do");
        } catch (final Throwable oops) {
            result = this.createEditModelAndView(parade, "parade.commit.error", "edit");
        }

        return result;
    }

    // Save in Final Mode -----------------------------------------------------

    @RequestMapping(value = "/brotherhood/edit", method = RequestMethod.POST, params = "finalMode")
    public ModelAndView finalMode(@Valid final Parade parade, final BindingResult binding) {
        ModelAndView result;

        if (binding.hasErrors())
            result = this.createEditModelAndView(parade, "edit");
        else
            try {
                parade.setIsDraft(false);
                this.paradeService.save(parade);
                result = new ModelAndView("redirect:list.do");
            } catch (final Throwable oops) {
                result = this.createEditModelAndView(parade, "parade.commit.error", "edit");
            }

        return result;
    }

    // Show -------------------------------------------------------------------

    @RequestMapping(value = "/public/show", method = RequestMethod.GET)
    public ModelAndView show(@RequestParam final int paradeId) {
        ModelAndView result;
        Parade parade;

        parade = this.paradeService.findOne(paradeId);
        Assert.notNull(parade);
        Assert.isTrue(parade.getIsDraft());

        result = new ModelAndView("parade/public/" + "show");

        result.addObject("parade", parade);

        // result.addObject("messageCode", null);

        return result;
    }

    // Ancillary Methods ------------------------------------------------------

    protected ModelAndView createEditModelAndView(final Parade parade, final String method) {
        ModelAndView result;

        result = this.createEditModelAndView(parade, null, method);

        return result;
    }

    protected ModelAndView createEditModelAndView(final Parade parade, final String messageCode, final String method) {
        final ModelAndView result;
        final Brotherhood brotherhood;
        final Collection<AcmeFloat> acmeFloats;
        final UserAccount userAccount = LoginService.getPrincipal();

        brotherhood = this.brotherhoodService.findPrincipal();
        acmeFloats = this.acmeFloatService.findAcmeFloats(userAccount.getId());

        result = new ModelAndView("parade/brotherhood/" + method);
        result.addObject("brotherhood", brotherhood);
        result.addObject("acmeFloats", acmeFloats);

        result.addObject("parade", parade);

        result.addObject("messageCode", messageCode);

        return result;
    }

}

В случае создания поток выглядит следующим образом: когда в представлении создания после заполнения формы и отправки в методе ParadeController вызывается метод save (). Его входом является объект ParadeForm с id = 0. Объекты "parade" (новый Parade в этом случае и обновленный Parade в случае редакции) и объекты "oldParade" (в данном случае null, но Parade до обновления в случае обновления) создаются и объявляются в любом случае. Затем мы идем в try / catch. Во-первых, он получает acmeFloats парада, чтобы обновить их, добавив в свою коллекцию парадов только что созданный Парад. Но при первой попытке сохранения выдает следующее:

org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.TransientObjectException: object references an unsaved transient instance

Сохранение сначала нового Парада дает те же результаты. Я намеревался, в случае, если это издание (таким образом, Парад существовал раньше и мог иметь AcmeFloats), найти AcmeFloats, которые были удалены из Парада, обновить их и затем сохранить Парад. Поэтому мне нужно было использовать oldParade в случае редактирования, чтобы проверить, с каких AcmeFloats я должен удалить парад.

Кроме того, я не знаю, нужно ли мне делать все это с каскадом в @ManyToMany, а просто сохранить Парад после восстановления, но он все равно не работает, поэтому я решил опубликовать эту часть код, чтобы вы выяснили, как это будет работать без каскада.

У меня были проблемы с этим вопросом в течение последнего месяца и раньше. Заранее спасибо.

РЕДАКТИРОВАТЬ 1:

Когда я помещаю flush () после сохранения в хранилище, при сохранении выдается следующее исключение:

org.springframework.orm.jpa.JpaSystemException: Exception occurred inside getter of domain.Parade.acmeFloats; nested exception is org.hibernate.PropertyAccessException: Exception occurred inside getter of domain.Parade.acmeFloats
...