A onetomany B,B有id,code,name,group,language,A 的b字段指向了B的code,列表显示错误b的名称错误(由于对应group下的code才是正确的)。
请问这种情况是需要联合主键吗?该如何使用?
你好,能举个例子吗?
xml:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<window xmlns="http://jmix.io/schema/ui/window"
xmlns:c="http://jmix.io/schema/ui/jpql-condition"
caption="msg://AEntityBrowse.caption"
focusComponent="aEntitiesTable">
<data readOnly="true">
<collection id="aEntitiesDc"
class="com.company.jmixpm.entity.AEntity">
<fetchPlan extends="_base">
<property name="tagDict" fetchPlan="_base"/>
<property name="typeDict" fetchPlan="_base"/>
<property name="language" fetchPlan="_base"/>
</fetchPlan>
<loader id="aEntitiesDl">
<query>
<![CDATA[select e from AEntity e]]>
</query>
</loader>
</collection>
</data>
<facets>
<dataLoadCoordinator auto="true"/>
<screenSettings id="settingsFacet" auto="true"/>
</facets>
<actions>
<action id="lookupSelectAction"
caption="msg:///actions.Select"
icon="LOOKUP_OK"
primary="true"
shortcut="${COMMIT_SHORTCUT}"/>
<action id="lookupCancelAction"
caption="msg:///actions.Cancel"
icon="LOOKUP_CANCEL"/>
</actions>
<dialogMode height="600"
width="800"/>
<layout expand="aEntitiesTable" spacing="true">
<filter id="filter"
dataLoader="aEntitiesDl">
<properties include=".*"/>
</filter>
<groupTable id="aEntitiesTable"
width="100%"
dataContainer="aEntitiesDc">
<actions>
<action id="create" type="create"/>
<action id="edit" type="edit"/>
<action id="remove" type="remove"/>
</actions>
<columns>
<column id="code"/>
<column id="name"/>
<column id="tagDict"/>
<column id="typeDict"/>
<column id="language"/>
</columns>
<simplePagination/>
<buttonsPanel id="buttonsPanel"
alwaysVisible="true">
<button id="createBtn" action="aEntitiesTable.create"/>
<button id="editBtn" action="aEntitiesTable.edit"/>
<button id="removeBtn" action="aEntitiesTable.remove"/>
</buttonsPanel>
</groupTable>
<hbox id="lookupActions" spacing="true" visible="false">
<button action="lookupSelectAction"/>
<button action="lookupCancelAction"/>
</hbox>
</layout>
</window>
A entity:
package com.company.jmixpm.entity;
import io.jmix.core.DeletePolicy;
import io.jmix.core.entity.annotation.JmixGeneratedValue;
import io.jmix.core.entity.annotation.OnDeleteInverse;
import io.jmix.core.metamodel.annotation.JmixEntity;
import javax.persistence.*;
import java.util.UUID;
@JmixEntity
@Table(name = "A_ENTITY")
@Entity
public class AEntity {
@JmixGeneratedValue
@Column(name = "ID", nullable = false)
@Id
private UUID id;
@Column(name = "CODE", nullable = false)
private String code;
@Column(name = "NAME", nullable = false)
private String name;
@OnDeleteInverse(DeletePolicy.DENY)
@JoinColumn(name = "TAG", referencedColumnName = "code")
@ManyToOne(fetch = FetchType.LAZY)
private DictEntity tagDict;
@OnDeleteInverse(DeletePolicy.DENY)
@JoinColumn(name = "TYPE", referencedColumnName = "code")
@ManyToOne(fetch = FetchType.LAZY)
private DictEntity typeDict;
@OnDeleteInverse(DeletePolicy.DENY)
@JoinColumn(name = "LG", referencedColumnName = "code")
@ManyToOne(fetch = FetchType.LAZY)
private LanguageEntity language;
public UUID getId() {
return id;
}
public void setId(UUID id) {
this.id = id;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public LanguageEntity getLanguage() {
return language;
}
public void setLanguage(LanguageEntity language) {
this.language = language;
}
public DictEntity getTagDict() {
return tagDict;
}
public void setTagDict(DictEntity tagDict) {
this.tagDict = tagDict;
}
public DictEntity getTypeDict() {
return typeDict;
}
public void setTypeDict(DictEntity typeDict) {
this.typeDict = typeDict;
}
}
Dict entity:
package com.company.jmixpm.entity;
import io.jmix.core.DeletePolicy;
import io.jmix.core.entity.annotation.JmixGeneratedValue;
import io.jmix.core.entity.annotation.OnDeleteInverse;
import io.jmix.core.metamodel.annotation.JmixEntity;
import javax.persistence.*;
import java.util.UUID;
@JmixEntity
@Table(name = "DICT_ENTITY", uniqueConstraints = {
@UniqueConstraint(name = "IDX_DICT_UNQ", columnNames = {"code"})
})
@Entity
public class DictEntity {
@JmixGeneratedValue
@Column(name = "ID", nullable = false)
@Id
private UUID id;
@Column(name = "CODE", nullable = false)
private String code;
@Column(name = "NAME", nullable = false)
private String name;
@Column(name = "GROUP", nullable = false)
private String group;
@OnDeleteInverse(DeletePolicy.DENY)
@JoinColumn(name = "LG", referencedColumnName = "code")
@ManyToOne(fetch = FetchType.LAZY)
private LanguageEntity languageEntity;
public UUID getId() {
return id;
}
public void setId(UUID id) {
this.id = id;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGroup() {
return group;
}
public void setGroup(String group) {
this.group = group;
}
public LanguageEntity getLanguageEntity() {
return languageEntity;
}
public void setLanguageEntity(LanguageEntity languageEntity) {
this.languageEntity = languageEntity;
}
}
lgentity:
package com.company.jmixpm.entity;
import io.jmix.core.entity.annotation.JmixGeneratedValue;
import io.jmix.core.metamodel.annotation.JmixEntity;
import javax.persistence.*;
import java.util.UUID;
@JmixEntity
@Table(name = "LANGUAGE_ENTITY", uniqueConstraints = {
@UniqueConstraint(name = "IDX_LANGUAGE_UNQ", columnNames = {"code"})
})
@Entity
public class LanguageEntity {
@JmixGeneratedValue
@Column(name = "ID", nullable = false)
@Id
private UUID id;
@Column(name = "CODE", nullable = false)
private String code;
@Column(name = "NAME", nullable = false)
private String name;
public UUID getId() {
return id;
}
public void setId(UUID id) {
this.id = id;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
PS:
- 列表语言可以根据A的code显示对应的lg 的name
- dictTag和typeDict列表显示的不正确,因为a存的dict code在dictentity种不唯一(例如A的TAG字段存的test,在dictEntity表中code=test的有两条不同的数据,他们的group不同,因此我需要在锁定一下group才能让其匹配正确的name)
请问这个问题有什么方案吗?
你好,这里的DictEntity的主键并不是code,而是code+group的组合主键是吧?
主键有id,但是用的是code,code+group+lg才能确定唯一;因为要兼容老数据,所以看时候有方案处理
那怎么判断AEntity里面的 tagDict 是哪个group,哪个lg呢?
业务层面有固定的值,比如我开发当前这个功能就取group=‘A’,lg当前系统语言的。
目前就是不知道这个条件该如何加
好的,如果只是列表展示问题的话,可以用 ColumnGenerator
实现的。
这个应该是可以的,但是就意味着界面加载又加了很多单独查表的,感觉很不友好。一对多的entity这块是否能配置来处理这个问题?
这个没有办法的,因为在A实体内存的code对应多个dict实体。只能通过再一次查询确认具体对应哪一个。
如果担心效率问题,可以用 实体和查询的缓存 :: Jmix 文档 ,另外,如果dict实体的数量相对稳定,也可以自己写service在内存管理,提高查询速度。
发现不仅列表,编辑时候下拉选项也是匹配不上。
由于本质上列表查询,该字段已经赋予了框架查的字典对象,它已经有了id,code,group。在下拉选项中,找不到对用的option
只能在onAfterShow中,重新赋予一对多对象值