Hi, the full problem is described here: http://stackoverflow.com/q/41168878/1499667 Basically I have a CompositeUserType, that is contained in an Embeddable that is used multiple times in a domain object. Object mapped via a CompositeUserType (using it as an Embeddable is not possible by design):
public class Amount {
private BigDecimal value;
private CurrencyCode currency;
}
Embeddable that uses this CompositeUserType:
@Embeddable
public class AccountBalance {
@Type(type = Amount.TYPE_DEF)
@Columns(columns = {
@Column(name = "value", precision = Amount.PRECISION, scale = Amount.SCALE),
@Column(name = "currency", length = CurrencyCode.FIELD_LENGTH)})
private Amount amount;
Domain object that uses this Embeddable:
public class AccountStatement {
@AttributeOverrides(value = {
@AttributeOverride(name = "amount.value", column = @Column(name = "openingBalanceAmount") ),
@AttributeOverride(name = "amount.currency", column = @Column(name = "openingBalanceCurrency") )})
@Embedded
@Basic(optional = true)
private AccountBalance openingBalance;
But this does not work and throws
Caused by: org.hibernate.MappingException: Repeated column in mapping for entity: ...AccountStatement column: amount (should be mapped with insert="false" update="false")
When hibernate evaluates all the @AttributeOverride annotations, it's building a map with all the overrides specified on the property (AbstractPropertyHolder.buildColumnOverride called from setCurrentProperty) which looks like that:
{
...AccountStatement.closingBalance.amount.value=[Ljavax.persistence.Column;@1c34365c,
...AccountStatement.closingBalance.amount.currency=[Ljavax.persistence.Column;@348137e8
}
In Ejb3Column.buildColumnFromAnnotation it has the "actualCols" from the Embeddable and looks if these are overridden (which they are in the domain object). But what it does is it uses the key `...AccountStatement.closingBalance.amount` to get the overrides out of its map and therefore gets nothing. I think it should look for overrides for every column that is defined on the CompositeUserType ("amount.value" and "amount.currency") and not just for the field name of the Embeddable (just "amount"). Solution: It's a bit hacky, but it does the job and shows how to solve this issue. I replaced the following call in Ejb3Column.buildColumnFromAnnotation (Line 511)
javax.persistence.Column[] overriddenCols = propertyHolder.getOverriddenColumn(String)
with a call to this new method:
private static javax.persistence.Column[] getOverriddenColumns(
PropertyHolder propertyHolder,
String path,
javax.persistence.Column[] actualCols) {
final javax.persistence.Column[] overriddenColsOldMethod = propertyHolder.getOverriddenColumn(path);
if (overriddenColsOldMethod != null) {
return overriddenColsOldMethod;
}
if (actualCols == null) {
return null;
}
final List<javax.persistence.Column> overriddenCols = new ArrayList<>();
for (final javax.persistence.Column column : actualCols) {
final javax.persistence.Column[] overriddenColumn = propertyHolder.getOverriddenColumn(path + "." + column.name());
if (overriddenColumn != null && overriddenColumn.length == 1) {
overriddenCols.add(overriddenColumn[0]);
}
}
return overriddenCols.size() > 0 ? overriddenCols.toArray(new javax.persistence.Column[overriddenCols.size()]) : null;
}
This works and gets the @AttributeOverride annotations for every column correctly. As a possible alternative the @AttributeOverride annotation could get a "columns" attribute, that can hold multiple @Column annotations for the same key, or multiple @AttributeOverride annotations with the same name get "merged" together. Greetings Marty |