- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我是这些技术的新手,所以提前道歉。
我在我的应用程序中使用 springboot、Spring JPA、hibernate 和 mapstruct。
我已插入 id 为“1”的父记录。现在,当我尝试为 parent 插入一个 child 时,它会抛出
org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing : nested exception is java.lang.IllegalStateException: org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing :
/**
* Mapper class for the entity {@link Child} and its corresponding data transfer object {@link ParentTlDTO}.
*/
@Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.WARN, uses = {ParentMapper.class})
public interface ChildMapper extends EntityMapper<ChildDTO, Child> {
@Mapping(source = "parent.id", target = "parentId")
@Override
ChildDTO toDto(Child child);
@Mapping(source = "parentId", target = "parent.id")
@Override
Child toEntity(ChildDTO childDTO);
default Child fromId(String id) {
if (id == null) {
return null;
}
Child Child = new Child();
Child.setId(id);
return Child;
}
}
@Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE, uses = {})
public interface ParentMapper extends EntityMapper<ParentDTO, Parent> {
@Mapping(target = "childs", ignore = true)
Parent toEntity(ParentDTO parentDTO);
default Parent fromId(String id) {
if (id == null) {
return null;
}
Parent parent = new Parent();
parent.setId(id);
return parent;
}
}
@ApiModel(description = "Child holds the descriptive information of currencies translated into various languages supported by the application.")
@Entity
@Table(name = "child")
@Cache(usage = CacheConparentStrategy.NONSTRICT_READ_WRITE)
@Document(indexName = "child")
public class Child extends AbstractEntity {
private static final long serialVersionUID = 6419585975683709213L;
/**
* Identifier of the descriptive information.
*/
@Id
@GeneratedValue(generator = "system-uuid")
@GenericGenerator(name = "system-uuid", strategy = "uuid2")
@Column(name = "id", columnDefinition = "CHAR", length = 36, nullable = false)
private String id;
/**
* Name of the parent.
*/
@NotNull
@Size(min = 3, max = 120)
@Column(name = "entity_name", columnDefinition = "VARCHAR", length = 120, nullable = false)
private String entityName;
/**
* Brief description about the parent.
*/
@Size(max = 256)
@Column(name = "entity_desc", columnDefinition = "VARCHAR", length = 256, nullable = true)
private String entityDesc;
@ManyToOne(fetch = FetchType.EAGER)
@JsonIgnoreProperties("childs")
private Parent parent;
@ManyToOne(fetch = FetchType.EAGER)
private Language language;
/**
* Callback method that is triggered before persisting the descriptive information of the parent where default
* values are set for mandatory attributes and values are massaged without compromising on data integrity.
*/
@PrePersist
public void setDefaultValues() {
this.entityName = StringUtils.capitalize(StringUtils.trim(this.entityName));
this.entityDesc = StringUtils.trim(this.entityDesc);
}
/**
* @return the id
*/
public String getId() {
return id;
}
/**
* @param id the id to set
*/
public void setId(String id) {
this.id = id;
}
/**
*
* @return
*/
public String getEntityName() {
return entityName;
}
/**
*
* @param entityName
* @return
*/
public Child entityName(String entityName) {
this.entityName = entityName;
return this;
}
/**
*
* @param entityName
*/
public void setEntityName(String entityName) {
this.entityName = entityName;
}
/**
*
* @return
*/
public String getEntityDesc() {
return entityDesc;
}
/**
*
* @param entityDesc
* @return
*/
public Child entityDesc(String entityDesc) {
this.entityDesc = entityDesc;
return this;
}
/**
*
* @param entityDesc
*/
public void setEntityDesc(String entityDesc) {
this.entityDesc = entityDesc;
}
/**
*
* @return
*/
public Parent getParent() {
return parent;
}
/**
*
* @param parent
* @return
*/
public Child parent(Parent parent) {
this.parent = parent;
return this;
}
/**
*
* @param parent
*/
public void setParent(Parent parent) {
this.parent = parent;
}
public Language getLanguage() {
return language;
}
public Child language(Language language) {
this.language = language;
return this;
}
public void setLanguage(Language language) {
this.language = language;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Child child = (Child) o;
if (child.getId() == null || getId() == null) {
return false;
}
return Objects.equals(getId(), child.getId());
}
@Override
public int hashCode() {
return Objects.hashCode(getId());
}
@Override
public String toString() {
return "Child{"
+ "id=" + getId()
+ ", entityName='" + getEntityName() + "'"
+ ", entityDesc='" + getEntityDesc() + "'"
+ "}";
}
}
@ApiModel(description = "Parent class holds the primary definition of a parent such as parent code, parent symbol etc.")
@Entity
@Table(name = "parent")
@Cache(usage = CacheConparentStrategy.NONSTRICT_READ_WRITE)
@Document(indexName = "parent")
public class Parent extends AbstractEffectiveEntity {
private static final long serialVersionUID = 5671242791959882244L;
/**
* Identifier of the parent.
*/
@Id
@GeneratedValue(generator = "system-uuid")
@GenericGenerator(name = "system-uuid", strategy = "uuid2")
@Column(name = "id", columnDefinition = "CHAR", length = 36, nullable = false)
private String id;
/**
* Code assigned to the parent.
*/
@NotNull
@Size(min = 2, max = 5)
@Column(name = "parent_code", columnDefinition = "CHAR", length = 5, nullable = false, updatable = false)
private String parentCode;
/**
* Symbol associated with the parent.
*/
@NotNull
@Size(min = 2, max = 10)
@Column(name = "parent_symbol", columnDefinition = "VARCHAR", length = 10, nullable = false, updatable = false)
private String parentSymbol;
/**
* Flag to denote whether parent is installed in the product suite to support converting it to other currencies.
*/
@Column(name = "installed_flag", columnDefinition = "CHAR", length = 1, nullable = false)
private String installedFlag;
/**
* Bi-directional OneToMany is not the best and most efficient way to model a one to many relationship. But in this
* case we prefer to keep a collection of descriptive information (children) in Parent (parent) to retrieve the
* descriptive information via Parent, since the count of descriptive information shall be less (depending on the
* number of languages supported in the application for translation). Limitations of this are (1) inability to limit
* the number of descriptive information (Child) loaded and thus no support for pagination, (2) inability to sort
* descriptive information since @OrderColumn annotation can be expensive.
*/
@OneToMany(mappedBy = "parent")
@Cache(usage = CacheConparentStrategy.NONSTRICT_READ_WRITE)
private Set<Child> childs = new HashSet<>();
/**
* Callback method that is triggered before persisting the primary information of the parent where default values
* are set for mandatory attributes and values of key attributes are massaged without compromising on data integrity.
*/
@PrePersist
public void setDefaultValues() {
this.parentCode = StringUtils.upperCase(StringUtils.trim(this.parentCode));
this.parentSymbol = StringUtils.trim(this.parentSymbol);
this.installedFlag = StringUtils.upperCase(StringUtils.trim(this.installedFlag));
if (StringUtils.isBlank(this.installedFlag)) {
this.installedFlag = "N";
}
}
/**
* Returns the identifier of the parent.
*
* @return the parent identifier.
*/
public String getId() {
return id;
}
/**
* Sets the identifier of the parent.
*
* @param id the identifier to be set for the parent.
*/
public void setId(String id) {
this.id = id;
}
/**
* Returns the code associated with the parent.
*
* @return the parentCode
*/
public String getParentCode() {
return parentCode;
}
/**
* Sets the code associated with the parent.
*
* @param parentCode the parentCode to set
*/
public void setParentCode(String parentCode) {
this.parentCode = parentCode;
}
/**
* Sets the code of the parent in the Parent object.
*
* @param parentCode
* @return parent the Parent object with parentCode set.
*/
public Parent parentCode(String parentCode) {
this.parentCode = parentCode;
return this;
}
/**
* Returns the symbol associated with the parent.
*
* @return the parentSymbol
*/
public String getParentSymbol() {
return parentSymbol;
}
/**
* Sets the symbol associated with the parent.
*
* @param parentSymbol the parentSymbol to set
*/
public void setParentSymbol(String parentSymbol) {
this.parentSymbol = parentSymbol;
}
/**
* Sets the symbol of the parent in the Parent object.
*
* @param parentSymbol
* @return parent the Parent object with parentSymbol set.
*/
public Parent parentSymbol(String parentSymbol) {
this.parentSymbol = parentSymbol;
return this;
}
/**
* Return true if the parent is marked as installed in the product suite, otherwise false.
*
* @return the installedFlag
*/
public String getInstalledFlag() {
return installedFlag;
}
/**
* Setter method to specify whether the parent is marked as installed in the product suite or not.
*
* @param installedFlag the installedFlag to set
*/
public void setInstalledFlag(String installedFlag) {
this.installedFlag = installedFlag;
}
/**
* Sets the flag to denote whether the parent is installed in the product suite or note in the Parent object.
*
* @param installedFlag
* @return the Parent object with installedFlag set.
*/
public Parent installedFlag(String installedFlag) {
this.installedFlag = installedFlag;
return this;
}
/**
*
* @return
*/
public Set<Child> getChilds() {
return childs;
}
/**
*
* @param childs
* @return
*/
public Parent childs(Set<Child> childs) {
this.childs = childs;
return this;
}
/**
*
* @param child
* @return
*/
public Parent addChild(Child child) {
this.childs.add(child);
child.setParent(this);
return this;
}
/**
*
* @param child
* @return
*/
public Parent removeChild(Child child) {
this.childs.remove(child);
child.setParent(null);
return this;
}
/**
*
* @param childs
*/
public void setChilds(Set<Child> childs) {
this.childs = childs;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Parent parent = (Parent) o;
if (parent.getId() == null || getId() == null) {
return false;
}
return Objects.equals(getId(), parent.getId());
}
@Override
public int hashCode() {
return Objects.hashCode(getId());
}
@Override
public String toString() {
return "Parent{" + "id=" + getId() + ", parentCode='" + getParentCode() + "'" + ", parentSymbol='"
+ getParentSymbol() + "'" + ", installedFlag='" + getInstalledFlag() + "'" + "}";
}
}
最佳答案
您正在寻找的可能类似于 Passing the mapping target type to custom mappers或 lookup-entity-by-id例子。
您可以拥有一个抽象映射器,您可以在其中注入(inject)存储库并执行实体查找。或者您甚至可以将存储库作为 @Context
传递范围。
假设您有 ParentRepository
在里面你有findById(String id)
所以不要使用 ParentMapper
在您的 ChildMapper
您将使用 ParentRepository
.然后 MapStruct 将生成如下代码:
@Component
public class ChildMapperImpl implements ChildMapper {
@Autowired
private ParentRepository parentRepository;
@Autowired
private ChildFactory childFactory;
@Override
public Child toEntity(ChildDTO childDTO) {
Child child = childFactory.create(childDTO);
child.setParent(parentRepository.findById(childDTO.getParentId());
}
}
@Mapping(source = "parentId", target = "parent")
在
ChildMapper#toEntity
方法。
ChildFactory
在子映射器中也使用注释。
public class ChildFactory {
protected final ChildRepository childRepository;
public ChildFactory(ChildRepository childRepository) {
this.childRepository = childRepository;
}
@ObjectFactory
public Child create(ChildDTO childDTO) {
Child child = childRepository.findById(childDTO.getId());
return child == null ? new Child() : child;
}
}
关于hibernate - 使用 mapstruct 映射 Hibernate 实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51129128/
我可以在我们有 String 到 Enum 映射的地方找到答案,但我找不到如何将 Enum 映射到 String。 public class Result { Value enumValue; }
我想使用 MapStruct 映射一个没有源对象的 Target 对象。我试过了,但出现以下错误。 Can't generate mapping method with no input argume
我在单独的文件中有这 3 个类 public class Book { @Id @GeneratedValue private Long id; @NonNull
如何使用 MapStruct 对于以下场景进行 bean 映射。 class Source { private String sourceId; private List courses; //al
是否可以在针对目标 bean 中字符串类型的 bean 属性设置字符串值之前对其进行修剪? 例如,Dozer 通过其映射配置提供了这样的功能, true 另见 Dozer Global C
我收到编译错误: com/mycompany/hibernate5/Main.java:[10,46] cannot find symbol symbol: class Customer_
目前我们在项目中使用 ModelMapper。但是,在该站点中,我看到很多人喜欢 MapStruct。 不确定差异以及我们是否需要真正进行升级。 ModelMapper 和 MapStruct 有什么
我正在使用 map 结构用于在我的 中将 Dto 映射到实体,反之亦然 Spring Boot 应用。 I want to know that, is there a way that i can m
如何在 MapStruct 中完全禁用“构建器”?我根本不想使用它们,因为它们给我带来了各种各样的问题。 我在 META-INF 下创建了服务文件(我更喜欢一种将它分配给映射构建器 = 的方法,但我没
@Mapper @Mapper 将接口或抽象类标记为映射器,并自动生成映射实现类代码。 public @interface Mapper { // 引入其他其他映射器 Class&
我在其他地方看到过这个问题,但不是在相同的上下文中,也没有适合我们用例的答案。 假设我在源对象中有一个列表字段: List mySourceList; 和相应的目标字段: List myTargetL
我在 MapStruct 中使用 spring data jdbc。 POJO 与具有所有“仅限内部”数据(如代理键、审计信息等)的表结构保持一致,而域对象是分层的并且仅包含业务相关数据。我必须在特定
页面信息 public class PageInfoDto implements Serializable { private int currentPageNum; private
在 MapStruct 版本 1.1.0.Final 中,这是可能的.... @Mappings({ @Mapping(target = "transaction.process.detail
我有一个 list List我想映射到另一个列表 List .这些类型如下所示: public class Payment { @XmlElement(name = "Installment"
我要单例Mapper两者兼而有之 create和 update方法。 create 方法生成的代码很好,但是在更新的情况下,我想在目标中设置属性,前提是它们在源中不为空。 我该怎么做 mapStruc
我想使用 mapstruct 在这些对象之间进行映射: MyObj1 -List myObj2List --List myObj3List ---string field1 MyObj4 -List
如何映射以下内容: class Source { String name; List others; } class Other { String otherName; Lis
我想映射以下类 class Schedule { ZoneId timezoneId; List rules; } class AvailabilityRule { long
我是 MapStruct API 的新手,谁能说一下如何进行嵌套映射。 我有两个类,一个是我实际的purchaseOrder 类,它是我的目标类,另一个是EDPurchaseOrder 类,它被称为源
我是一名优秀的程序员,十分优秀!