有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java分离实体在保存一个对象时被传递到SpringData中,该对象包含一个映射,该映射的键已保存在DB中,并且现在已从中选择

我正在编写我的Harvest Spring Boot应用程序,我从表单中获取了一个非常复杂的对象,我想保存在DB中。这个对象是Tomatoes Season,它包含季节的year字段(整数)和带有Tomatoes Variety键和值Tomatoes Variety Specification的映射^创建时{}对象Tomatoes Season是从已经保存在数据库中的值中选择的Tomatoes Variety Specification是手动填写的表格,是一个新数据

当试图在数据库中保存这样的Tomatoes Season时,我在Tomatoes Variety上遇到了一个错误“分离的实体传递到持久化”。如果Tomatoes Variety是以前没有存储在数据库中的绝对新数据,则不存在此类错误,但我的情况并非如此

如果我在Tomatoes Season对象的@OneToMany映射注释中将级联类型从Cascade Type.ALL更改为Cascade Type.MERGE,我在Tomatoes Variety Specification对象上会出现另一个错误“对象引用未保存的临时实例”

对于如何解决这个问题,有什么建议吗?使用从DB中选择的映射键创建Tomatoes Season,并从表单中手动键入Tomatoes Varierty Specification

这是我的抽象课程Season

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Season {
    
    @Id
    @SequenceGenerator(name = "seasonSequence", sequenceName = "sequence_season", allocationSize = 1, initialValue = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seasonSequence")
    @Column(name = "season_id")
    private Integer id;

    @Column(nullable = false)
    @NotNull(message = "Field can't be empty!")
    private Integer year;

    public Season() {
    }

    public Season(Integer id, Integer year) {
        this.id = id;
        this.year = year;
    }

    public Season(Integer year) {
        this.year = year;
    }

    public Integer getId() {
        return id;
    }

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

    public Integer getYear() {
        return year;
    }

    public void setYear(Integer year) {
        this.year = year;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((id == null) ? 0 : id.hashCode());
        result = prime * result + ((year == null) ? 0 : year.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Season other = (Season) obj;
        if (id == null) {
            if (other.id != null)
                return false;
        } else if (!id.equals(other.id))
            return false;
        if (year == null) {
            if (other.year != null)
                return false;
        } else if (!year.equals(other.year))
            return false;
        return true;
    }
}

Tomatoes Season类:

@Entity
@Table(name = "tomatoes_season")
public class TomatoesSeason extends Season implements Serializable {
    private static final long serialVersionUID = 1L;
    
    @OneToMany(cascade = CascadeType.ALL)
    @JoinTable(name = "tomatoes_season_varieties", 
      joinColumns = {@JoinColumn(name = "season_id", referencedColumnName = "season_id")},
      inverseJoinColumns = {@JoinColumn(name = "variety_specification_id", referencedColumnName = "variety_specification_id")})
    @MapKeyJoinColumn(name = "variety_id")
    @Column(nullable = false)
    private Map<TomatoesVariety, TomatoesVarietySpecification> tomatoesSeasonVarieties;
    
    public TomatoesSeason() {
        super();
    }

    public TomatoesSeason(Integer id, Integer year) {
        super(id, year);
    }

    public TomatoesSeason(Integer year) {
        super(year);
    }

    public TomatoesSeason(Integer id, Integer year,
            Map<TomatoesVariety, TomatoesVarietySpecification> tomatoesSeasonVarieties) {
        super(id, year);
        this.tomatoesSeasonVarieties = tomatoesSeasonVarieties;
    }

    public TomatoesSeason(Integer year, Map<TomatoesVariety, TomatoesVarietySpecification> tomatoesSeasonVarieties) {
        super(year);
        this.tomatoesSeasonVarieties = tomatoesSeasonVarieties;
    }

    public Map<TomatoesVariety, TomatoesVarietySpecification> getTomatoesSeasonVarieties() {
        return tomatoesSeasonVarieties;
    }

    public void setTomatoesSeasonVarieties(Map<TomatoesVariety, TomatoesVarietySpecification> tomatoesSeasonVarieties) {
        this.tomatoesSeasonVarieties = tomatoesSeasonVarieties;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = super.hashCode();
        result = prime * result + ((tomatoesSeasonVarieties == null) ? 0 : tomatoesSeasonVarieties.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (!super.equals(obj))
            return false;
        if (getClass() != obj.getClass())
            return false;
        TomatoesSeason other = (TomatoesSeason) obj;
        if (tomatoesSeasonVarieties == null) {
            if (other.tomatoesSeasonVarieties != null)
                return false;
        } else if (!tomatoesSeasonVarieties.equals(other.tomatoesSeasonVarieties))
            return false;
        return true;
    }

    @Override
    public String toString() {
        return "Id=" + getId() + ", Year=" + getYear() + ", TomatoesSeasonVarieties=" + tomatoesSeasonVarieties;
    }
}

抽象类:

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Variety {

    @Id
    @SequenceGenerator(name = "varietySequence", sequenceName = "sequence_variety", allocationSize = 1, initialValue = 1 )
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "varietySequence")
    @Column(name = "variety_id")
    private Integer id;

    @Column(nullable = false)
    @NotBlank(message = "Значение поля не может быть пустым!")
    private String name;

    public Variety() {
    }

    public Variety(Integer id, String name) {
        this.id = id;
        this.name = name;
    }

    public Variety(String name) {
        this.name = name;
    }

    public Integer getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((id == null) ? 0 : id.hashCode());
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Variety other = (Variety) obj;
        if (id == null) {
            if (other.id != null)
                return false;
        } else if (!id.equals(other.id))
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;       
        return true;
    }
}

Tomatoes Variety类:

@Entity
@Table(name = "tomatoes_variety")
public class TomatoesVariety extends Variety implements Serializable {
    private static final long serialVersionUID = 1L;
    
    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "variety")
    @Column(nullable = false)
    private Set<TomatoesHarvesting> tomatoes;
    
    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "season_id")
    private TomatoesSeason tomatoesSeason;

    public TomatoesVariety() {
        super();
    }

    public TomatoesVariety(Integer id, String name) {
        super(id, name);
    }

    public TomatoesVariety(String name) {
        super(name);
    }

    public Set<TomatoesHarvesting> getTomatoes() {
        return tomatoes;
    }

    public void setTomatoes(Set<TomatoesHarvesting> tomatoes) {
        this.tomatoes = tomatoes;
    }

    public TomatoesSeason getTomatoesSeason() {
        return tomatoesSeason;
    }

    public void setTomatoesSeason(TomatoesSeason tomatoesSeason) {
        this.tomatoesSeason = tomatoesSeason;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = super.hashCode();
        result = prime * result + ((tomatoes == null) ? 0 : tomatoes.hashCode());
        result = prime * result + ((tomatoesSeason == null) ? 0 : tomatoesSeason.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (!super.equals(obj))
            return false;
        if (getClass() != obj.getClass())
            return false;
        TomatoesVariety other = (TomatoesVariety) obj;
        if (tomatoes == null) {
            if (other.tomatoes != null)
                return false;
        } else if (!tomatoes.equals(other.tomatoes))
            return false;
        if (tomatoesSeason == null) {
            if (other.tomatoesSeason != null)
                return false;
        } else if (!tomatoesSeason.equals(other.tomatoesSeason))
            return false;
        return true;
    }

    @Override
    public String toString() {
        return "Id=" + getId() + ", Name=" + getName();
    }
}

抽象Variety Specification类:

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class VarietySpecification {

    @Id
    @SequenceGenerator(name = "varietySpecificationSequence", sequenceName = "sequence_variety_specification", allocationSize = 1, initialValue = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "varietySpecificationSequence")
    @Column(name = "variety_specification_id")
    private Integer id;

    @Column(nullable = false)
    @NotBlank(message = "Значение поля не может быть пустым!")
    private String customId;

    public VarietySpecification() {
        super();
    }

    public VarietySpecification(Integer id, String customId) {
        this.id = id;
        this.customId = customId;
    }

    public VarietySpecification(String customId) {
        this.customId = customId;
    }

    public Integer getId() {
        return id;
    }

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

    public String getCustomId() {
        return customId;
    }

    public void setCustomId(String customId) {
        this.customId = customId;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((customId == null) ? 0 : customId.hashCode());
        result = prime * result + ((id == null) ? 0 : id.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        VarietySpecification other = (VarietySpecification) obj;
        if (customId == null) {
            if (other.customId != null)
                return false;
        } else if (!customId.equals(other.customId))
            return false;
        if (id == null) {
            if (other.id != null)
                return false;
        } else if (!id.equals(other.id))
            return false;
        return true;
    }
}

Tomatoes Variety Specification类:

@Entity
@Table(name = "tomatoes_variety_specification")
public class TomatoesVarietySpecification extends VarietySpecification implements Serializable {
    private static final long serialVersionUID = 1L;

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "variety_id")
    private TomatoesVariety tomatoesVariety;
    
    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "tomatoesVarietySpecification")
    @Column(nullable = false)
    private Set<TomatoesGardenbed> tomatoesGardenbeds;

    public TomatoesVarietySpecification() {
    }

    public TomatoesVarietySpecification(Integer id, String customId) {
        super(id, customId);
    }

    public TomatoesVarietySpecification(String customId) {
        super(customId);
    }

    public TomatoesVarietySpecification(Integer id, String customId, Set<TomatoesGardenbed> tomatoesGardenbeds) {
        super(id, customId);
        this.tomatoesGardenbeds = tomatoesGardenbeds;
    }

    public TomatoesVarietySpecification(String customId, Set<TomatoesGardenbed> tomatoesGardenbeds) {
        super(customId);
        this.tomatoesGardenbeds = tomatoesGardenbeds;
    }

    public TomatoesVariety getTomatoesVariety() {
        return tomatoesVariety;
    }

    public void setTomatoesVariety(TomatoesVariety tomatoesVariety) {
        this.tomatoesVariety = tomatoesVariety;
    }

    public Set<TomatoesGardenbed> getTomatoesGardenbeds() {
        return tomatoesGardenbeds;
    }

    public void setTomatoesGardenbeds(Set<TomatoesGardenbed> tomatoesGardenbeds) {
        this.tomatoesGardenbeds = tomatoesGardenbeds;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = super.hashCode();
        result = prime * result + ((tomatoesGardenbeds == null) ? 0 : tomatoesGardenbeds.hashCode());
        result = prime * result + ((tomatoesVariety == null) ? 0 : tomatoesVariety.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (!super.equals(obj))
            return false;
        if (getClass() != obj.getClass())
            return false;
        TomatoesVarietySpecification other = (TomatoesVarietySpecification) obj;
        if (tomatoesGardenbeds == null) {
            if (other.tomatoesGardenbeds != null)
                return false;
        } else if (!tomatoesGardenbeds.equals(other.tomatoesGardenbeds))
            return false;
        if (tomatoesVariety == null) {
            if (other.tomatoesVariety != null)
                return false;
        } else if (!tomatoesVariety.equals(other.tomatoesVariety))
            return false;
        return true;
    }

    @Override
    public String toString() {
        return "Id=" + getId() + ", CustomId=" + getCustomId() + ", TomatoesGardenbeds=" + tomatoesGardenbeds;
    }
}

以及我的控制器创建方法:

    @PostMapping("/create")
    public String createTomatoesSeason(String refererURI, String superRefererURI, @Valid TomatoesSeason tomatoesSeason, @RequestParam(name = "tomatoesVariety.id") TomatoesVariety tomatoesVariety, TomatoesVarietySpecification tomatoesVarietySpecification,  TomatoesGardenbed tomatoesGardenbed, BindingResult bindingResult, Model model) {
        if (bindingResult.hasErrors()) {
            Map<String, String> errors = ControllerUtils.getErrors(bindingResult);
            model.mergeAttributes(errors);
            model.addAttribute("refererURI", refererURI);

            if (superRefererURI != "") {
                model.addAttribute("superRefererURI", superRefererURI);
            }

            return "tomatoesSeasonCreator";
        }

        tomatoesVarietySpecification.setTomatoesGardenbeds(new HashSet<TomatoesGardenbed>(Collections.singleton(tomatoesGardenbed)));
        HashMap<TomatoesVariety, TomatoesVarietySpecification> tomatoesSeasonVarieties = new HashMap<TomatoesVariety, TomatoesVarietySpecification>();
        tomatoesSeasonVarieties.put(tomatoesVariety, tomatoesVarietySpecification);
        tomatoesSeason.setTomatoesSeasonVarieties(tomatoesSeasonVarieties);
        boolean tomatoesSeasonExists = tomatoesSeasonService.createTomatoesSeason(tomatoesSeason);
        
        if (tomatoesSeasonExists) {
            model.addAttribute("seasonExistsMessage", "Such season already exists!");
            model.addAttribute("refererURI", refererURI);
            
            if (superRefererURI != "") {
                model.addAttribute("superRefererURI", superRefererURI);
            }
            
            return "tomatoesSeasonCreator";
        }
        
        if (superRefererURI != "") {
            return "redirect:" + refererURI + "?superRefererURI=" + superRefererURI;
        }
        
        return "redirect:" + refererURI;
    }

Tomatoes Season Service类:

@Service
public class TomatoesSeasonService {
    Logger logger = LoggerFactory.getLogger(TomatoesSeasonService.class);
    
    @Autowired
    private TomatoesSeasonRepository tomatoesSeasonRepository;

    public List<TomatoesSeason> findAll() {
        logger.trace("Getting all tomatoes seasons from database...");
        
        return tomatoesSeasonRepository.findAll();
    }

    public boolean checkIfExists(TomatoesSeason tomatoesSeason) {
        logger.trace("Checking if stored tomatoes season already exists in database...");
        
        Optional<TomatoesSeason> tomatoesSeasonFromDb = tomatoesSeasonRepository.findByYear(tomatoesSeason.getYear());
    
        if (tomatoesSeasonFromDb.isPresent() && tomatoesSeason.getId() != tomatoesSeasonFromDb.get().getId()) {
            logger.warn("Tomatoes season of \"" + tomatoesSeasonFromDb.get().getYear() + "\" year already exists in database...");
            return true;
        }
        return false;
    }
    
    public boolean createTomatoesSeason(TomatoesSeason tomatoesSeason) {
        logger.trace("Adding new tomatoes season to database...");
        
        if (checkIfExists(tomatoesSeason))
            return false;

        logger.trace("Saving new tomatoes season in database...");
        tomatoesSeasonRepository.save(tomatoesSeason);
        return true;
    }

    public boolean updateTomatoesSeason(TomatoesSeason tomatoesSeason) {
        logger.trace("Updating tomatoes season in database...");
        
        if (checkIfExists(tomatoesSeason))
            return false;
        
        logger.trace("Saving updated tomatoes season in database...");
        tomatoesSeasonRepository.save(tomatoesSeason);
        return true;
    }

    public void deleteTomatoesSeason(TomatoesSeason tomatoesSeason) {
        logger.trace("Deleting tomatoes season from database...");
        
        tomatoesSeasonRepository.delete(tomatoesSeason);
    }
}

共 (0) 个答案