У меня проблема с попыткой определить отношения между parent record
и child records
родителя. Я использую одну таблицу, где, если запись обновляется, вставляется новая, а старая становится неактивной - с parent_id
, установленным на id
из новой записи. Вот мой оператор CREATE для таблицы:
CREATE TABLE `templates` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`region_id` int unsigned NOT NULL,
`name` varchar(80) NOT NULL,
`description` text,
`is_active` tinyint unsigned NOT NULL DEFAULT '0',
`parent_id` int unsigned DEFAULT NULL,
`created_by` int unsigned DEFAULT NULL,
`updated_by` int unsigned DEFAULT NULL,
`created` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `reg_id_idx` (`region_id`),
CONSTRAINT `td_templates_cms_regions_2812` FOREIGN KEY (`region_id`) REFERENCES `cms_regions` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
И Entity
, который есть в моей java IDE:
/*
* 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 com.vw.asa.entities.template;
import com.vw.asa.entities.cms.CmsRegions;
import javax.persistence.*;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
/**
* @author Barry Chapman
*/
@Entity
@Table(name = "templates", schema = "asa")
@XmlRootElement
@NamedQueries({
@NamedQuery(name = "Templates.findAll", query = "SELECT t FROM Templates t"),
@NamedQuery(name = "Templates.findById", query = "SELECT t FROM Templates t WHERE t.id = :id"),
@NamedQuery(name = "Templates.findByName", query = "SELECT t FROM Templates t WHERE t.name = :name"),
@NamedQuery(name = "Templates.findByIsActive", query = "SELECT t FROM Templates t WHERE t.isActive = :isActive"),
@NamedQuery(name = "Templates.findByParentId", query = "SELECT t FROM Templates t WHERE t.parentId = :parentId"),
@NamedQuery(name = "Templates.findByCreatedBy", query = "SELECT t FROM Templates t WHERE t.createdBy = :createdBy"),
@NamedQuery(name = "Templates.findByUpdatedBy", query = "SELECT t FROM Templates t WHERE t.updatedBy = :updatedBy"),
@NamedQuery(name = "Templates.findByCreated", query = "SELECT t FROM Templates t WHERE t.created = :created"),
@NamedQuery(name = "Templates.findByModified", query = "SELECT t FROM Templates t WHERE t.modified = :modified")})
public class Templates implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "id")
private Integer id;
@Basic(optional = false)
@NotNull
@Size(min = 1, max = 80)
@Column(name = "name")
private String name;
@Lob
@Size(max = 65535)
@Column(name = "description")
private String description;
@Basic(optional = false)
@NotNull
@Column(name = "is_active")
private short isActive;
/*@Column(name = "parent_id")
private Integer parentId;*/
@Column(name = "created_by")
private Integer createdBy;
@Column(name = "updated_by")
private Integer updatedBy;
@Basic(optional = false)
@NotNull
@Column(name = "created")
@Temporal(TemporalType.TIMESTAMP)
private Date created;
@Basic(optional = false)
@NotNull
@Column(name = "modified")
@Temporal(TemporalType.TIMESTAMP)
private Date modified;
@JoinColumn(name = "region_id", referencedColumnName = "id")
@ManyToOne(optional = false, fetch = FetchType.LAZY)
private CmsRegions regionId;
@JoinColumn(name = "parent_id", referencedColumnName = "id")
@ManyToOne(optional = false, fetch = FetchType.LAZY)
private Integer parent_id;
public Templates() {
}
public Templates(Integer id) {
this.id = id;
}
public Templates(Integer id, String name, short isActive, Date created, Date modified) {
this.id = id;
this.name = name;
this.isActive = isActive;
this.created = created;
this.modified = modified;
}
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;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public short getIsActive() {
return isActive;
}
public void setIsActive(short isActive) {
this.isActive = isActive;
}
public Integer getParentId() {
return getParent().getId();
}
public void setParentId(Integer parentId) {
this.parent_id = parentId;
}
public Integer getCreatedBy() {
return createdBy;
}
public void setCreatedBy(Integer createdBy) {
this.createdBy = createdBy;
}
public Integer getUpdatedBy() {
return updatedBy;
}
public void setUpdatedBy(Integer updatedBy) {
this.updatedBy = updatedBy;
}
public Date getCreated() {
return created;
}
public void setCreated(Date created) {
this.created = created;
}
public Date getModified() {
return modified;
}
public void setModified(Date modified) {
this.modified = modified;
}
public Templates getParent() {
return parent;
}
public void setParent(Templates parent) {
this.parent = parent;
this.parent_id = parent.getId();
}
public CmsRegions getRegionId() {
return regionId;
}
public void setRegionId(CmsRegions regionId) {
this.regionId = regionId;
}
@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 Templates)) {
return false;
}
Templates other = (Templates) object;
return (this.id != null || other.id == null) && (this.id == null || this.id.equals(other.id));
}
@Override
public String toString() {
return "com.vw.asa.entities.Templates[ id=" + id + " ]";
}
}
Я попытался добавить следующий блок в Объект, но он сгенерировал ошибку, указанную после этого блока:
@JoinColumn(name = "parent_id", referencedColumnName = "id")
@ManyToOne(optional = false, fetch = FetchType.LAZY)
private Integer parent;
Чтобы добавить это, я добавил следующий метод получения / установки:
public Integer getParentId() {
return getParent().getId();
}
public void setParentId(Integer parentId) {
this.parent_id = parentId;
}
Это ошибка, сгенерированная во время компиляции:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.MappingException: Repeated column in mapping for entity: com.vw.asa.entities.template.TdTemplates column: parent_id (should be mapped with insert="false" update="false")
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.MappingException: Repeated column in mapping for entity: com.vw.asa.entities.template.TdTemplates column: parent_id (should be mapped with insert="false" update="false")
Очевидно, что это имеет отношение к parent_id, имеющему более одного определения, но как мне структурировать эту сущность так, чтобы можно было выполнять следующие операции?
template.getParent().getId(); // returns parent_id
template.setParent(template); // set the parent object
Есть ли методы / свойства, которые можно удалить и которые здесь избыточны?
РЕДАКТИРОВАТЬ
Одна вещь, на которую стоит обратить внимание, это то, что я не определил окончательно шаблон проектирования для того, как родитель -детские отношения сработают.
Может оказаться, что запись oldest
будет родительской, а newest
- дочерней, или запись current/master/active
может быть родительской, а остальные - вниз. дерево может быть ребенком жэнь. Мне еще предстоит решить, какой метод является лучшим подходом здесь.