Grails 3.1.6,Hibernate 4。复合外键
Grails 3.1.6, Hibernate 4. Composite foreign key
class Tooth {
Integer id
ToothDisease toothDisease
static mapping = {
table name: 'AK_TOOTH'
id generator: 'sequence', params: [sequence: 'SEQ_AK_TOOTH']
columns{
toothDisease {
column: 'FK_AK_TOOTH_ID'
column: 'FK_AK_TOOTH_NR_VERSION'
}
}
}
class ToothDisease implements Serializable{
Integer idColumn
Integer nrVersion
static mapping = {
table name: 'AK_TOOTH_DISEASE'
idColumn column: 'ID', generator: 'sequence', params: [sequence: 'SEQ_AK_TOOTH_DISEASE']
nrVersion column: 'NR_VERSION',
id composite ['idColumn','nrVersion']
int hashCode () {
def builder = new HashCodeBuilder ()
builder.append (idColumn)
builder.append (nrVersion)
builder.toHashCode ()
}
boolean equals (other) {
if (other == null) {
return false
}
def builder = new EqualsBuilder ()
builder.append (idColumn, other.idColumn)
builder.append (nrVersion, other.nrVersion)
builder.isEquals ()
}
}
当我尝试启动我的应用程序时,出现 BeanCreationException:
Caused by: org.hibernate.MappingException: Foreign key (FK_1rnajvolkf4rkav5w1hl0l9fk:AK_TOOTH [tooth_disease_id,FK_AK_TOOTH_ID,FK_AK_TOOTH_NR_VERSION,tooth_disease_id_column,tooth_disease_nr_version])) must have same number of columns as the referenced primary key (AK_TOOTH_DISEASE [ID,NR_VERSION]).
当我删除 Tooth 中的列映射部分时,如果没有这些列,我会遇到同样的错误
[tooth_disease_id,tooth_disease_id_column,tooth_disease_nr_version].
是否可以像hibernate 那样显式定义key column 和referencedColumnName?
为什么有三列?尤其是 tooth_disease_id and tooth_disease_id_column columns
同时。我尝试使用 'primaryKey' name 作为 Tooth 的复合主键和 'id' simple 作为 id 列,但是这样,我有同样的错误
Caused by: org.hibernate.MappingException: Foreign key (FK_1rnajvolkf4rkav5w1hl0l9fk:AK_TOOTH [tooth_disease_id,FK_AK_TOOTH_ID,FK_AK_TOOTH_NR_VERSION,tooth_disease_id_column,tooth_disease_nr_version])) must have same number of columns as the referenced primary key (AK_TOOTH_DISEASE [ID]).But there is only one referenced primary key.
不幸的是,我没有机会更改模式结构并避免组合键。
我认为错误是由于您在 Tooth 的映射中将 FK 声明为 ToothDisease 的方式造成的。
试试这个:
class Tooth {
Integer id
ToothDisease toothDisease
static mapping = {
table name: 'AK_TOOTH'
id generator: 'sequence', params: [sequence: 'SEQ_AK_TOOTH']
toothDisease {
column name: 'FK_AK_TOOTH_ID'
column name: 'FK_AK_TOOTH_NR_VERSION'
}
}
}
class ToothDisease implements Serializable{
Integer idColumn
Integer nrVersion
static mapping = {
table name: 'AK_TOOTH_DISEASE'
idColumn column: 'ID', generator: 'sequence', params: [sequence: 'SEQ_AK_TOOTH_DISEASE']
nrVersion column: 'NR_VERSION'
id composite: ['idColumn','nrVersion']
}
int hashCode () {
def builder = new HashCodeBuilder ()
builder.append (idColumn)
builder.append (nrVersion)
builder.toHashCode ()
}
boolean equals (other) {
if (other == null) {
return false
}
def builder = new EqualsBuilder ()
builder.append (idColumn, other.idColumn)
builder.append (nrVersion, other.nrVersion)
builder.isEquals ()
}
}
我从 Burt Beckwith 那里找到了 here 解决方法。
由于 GrailsAnnotationConfiguration 被替换为 HibernateMappingContextConfiguration.groovy 我在他的解决方案中做了一些更改:
class CompositeForeignKeyConfiguration extends HibernateMappingContextConfiguration {
private static final long serialVersionUID = 1
private static final String TOOTH_CLASS_NAME = 'com.project.TOOTH'
private static final String TOOTH_ID_FK = 'FK_AK_TOOTH_ID'
private static final String TOOTH_VERSION_FK = 'FK_AK_TOOTH_NR_VERSION'
private boolean _alreadyProcessed
@SuppressWarnings ("unchecked")
@Override
protected void secondPassCompile () throws MappingException {
for (PersistentEntity pc : hibernateMappingContext.getPersistentEntities ()) {
if (pc.name == TOOTH_CLASS_NAME) {
pc.getAssociations ().each { Association mp ->
if (mp.name == 'toothDisease') {
PropertyConfig config = (PropertyConfig) mp.getMapping ().getMappedForm ()
if (config.columns.size () == 1) {
config.columns.clear ()
final ColumnConfig fk1 = new ColumnConfig (name: TOOTH_ID_FK )
final ColumnConfig fk2 = new ColumnConfig (name: TOOTH_VERSION_FK )
config.columns << fk1
config.columns << fk2
}
}
}
}
}
super.secondPassCompile ()
if (_alreadyProcessed) {
return
}
_alreadyProcessed = true
}
}
class Tooth {
Integer id
ToothDisease toothDisease
static mapping = {
table name: 'AK_TOOTH'
id generator: 'sequence', params: [sequence: 'SEQ_AK_TOOTH']
columns{
toothDisease {
column: 'FK_AK_TOOTH_ID'
column: 'FK_AK_TOOTH_NR_VERSION'
}
}
}
class ToothDisease implements Serializable{
Integer idColumn
Integer nrVersion
static mapping = {
table name: 'AK_TOOTH_DISEASE'
idColumn column: 'ID', generator: 'sequence', params: [sequence: 'SEQ_AK_TOOTH_DISEASE']
nrVersion column: 'NR_VERSION',
id composite ['idColumn','nrVersion']
int hashCode () {
def builder = new HashCodeBuilder ()
builder.append (idColumn)
builder.append (nrVersion)
builder.toHashCode ()
}
boolean equals (other) {
if (other == null) {
return false
}
def builder = new EqualsBuilder ()
builder.append (idColumn, other.idColumn)
builder.append (nrVersion, other.nrVersion)
builder.isEquals ()
}
}
当我尝试启动我的应用程序时,出现 BeanCreationException:
Caused by: org.hibernate.MappingException: Foreign key (FK_1rnajvolkf4rkav5w1hl0l9fk:AK_TOOTH [tooth_disease_id,FK_AK_TOOTH_ID,FK_AK_TOOTH_NR_VERSION,tooth_disease_id_column,tooth_disease_nr_version])) must have same number of columns as the referenced primary key (AK_TOOTH_DISEASE [ID,NR_VERSION]).
当我删除 Tooth 中的列映射部分时,如果没有这些列,我会遇到同样的错误
[tooth_disease_id,tooth_disease_id_column,tooth_disease_nr_version].
是否可以像hibernate 那样显式定义key column 和referencedColumnName?
为什么有三列?尤其是 tooth_disease_id and tooth_disease_id_column columns
同时。我尝试使用 'primaryKey' name 作为 Tooth 的复合主键和 'id' simple 作为 id 列,但是这样,我有同样的错误
Caused by: org.hibernate.MappingException: Foreign key (FK_1rnajvolkf4rkav5w1hl0l9fk:AK_TOOTH [tooth_disease_id,FK_AK_TOOTH_ID,FK_AK_TOOTH_NR_VERSION,tooth_disease_id_column,tooth_disease_nr_version])) must have same number of columns as the referenced primary key (AK_TOOTH_DISEASE [ID]).But there is only one referenced primary key.
不幸的是,我没有机会更改模式结构并避免组合键。
我认为错误是由于您在 Tooth 的映射中将 FK 声明为 ToothDisease 的方式造成的。
试试这个:
class Tooth {
Integer id
ToothDisease toothDisease
static mapping = {
table name: 'AK_TOOTH'
id generator: 'sequence', params: [sequence: 'SEQ_AK_TOOTH']
toothDisease {
column name: 'FK_AK_TOOTH_ID'
column name: 'FK_AK_TOOTH_NR_VERSION'
}
}
}
class ToothDisease implements Serializable{
Integer idColumn
Integer nrVersion
static mapping = {
table name: 'AK_TOOTH_DISEASE'
idColumn column: 'ID', generator: 'sequence', params: [sequence: 'SEQ_AK_TOOTH_DISEASE']
nrVersion column: 'NR_VERSION'
id composite: ['idColumn','nrVersion']
}
int hashCode () {
def builder = new HashCodeBuilder ()
builder.append (idColumn)
builder.append (nrVersion)
builder.toHashCode ()
}
boolean equals (other) {
if (other == null) {
return false
}
def builder = new EqualsBuilder ()
builder.append (idColumn, other.idColumn)
builder.append (nrVersion, other.nrVersion)
builder.isEquals ()
}
}
我从 Burt Beckwith 那里找到了 here 解决方法。 由于 GrailsAnnotationConfiguration 被替换为 HibernateMappingContextConfiguration.groovy 我在他的解决方案中做了一些更改:
class CompositeForeignKeyConfiguration extends HibernateMappingContextConfiguration {
private static final long serialVersionUID = 1
private static final String TOOTH_CLASS_NAME = 'com.project.TOOTH'
private static final String TOOTH_ID_FK = 'FK_AK_TOOTH_ID'
private static final String TOOTH_VERSION_FK = 'FK_AK_TOOTH_NR_VERSION'
private boolean _alreadyProcessed
@SuppressWarnings ("unchecked")
@Override
protected void secondPassCompile () throws MappingException {
for (PersistentEntity pc : hibernateMappingContext.getPersistentEntities ()) {
if (pc.name == TOOTH_CLASS_NAME) {
pc.getAssociations ().each { Association mp ->
if (mp.name == 'toothDisease') {
PropertyConfig config = (PropertyConfig) mp.getMapping ().getMappedForm ()
if (config.columns.size () == 1) {
config.columns.clear ()
final ColumnConfig fk1 = new ColumnConfig (name: TOOTH_ID_FK )
final ColumnConfig fk2 = new ColumnConfig (name: TOOTH_VERSION_FK )
config.columns << fk1
config.columns << fk2
}
}
}
}
}
super.secondPassCompile ()
if (_alreadyProcessed) {
return
}
_alreadyProcessed = true
}
}