I have a GORM class which is using an embedded instance in it. And the embedded instance is an immutable class. When I try to start the app, it is throwing the setter property is not found exception.
Caused by: org.hibernate.PropertyNotFoundException: Could not find a setter for property amount in class com.xxx.Money.
This is my GORM class:
class Billing {
static embedded = ['amount']
Money amount
}
And Money is defined as immutable:
final class Money {
final Currency currency
final BigDecimal value
Money(Currency currency, BigDecimal value) {
this.currency = currency
this.value = value
}
}
Anyway to resolve this without making Money mutable?
Thanks!
Grails and hibernate generally need full domain classes to be mutable to support all the features hibernate provides.
Rather than embedding a Money domain class, you can store the Money amount with a multi-column hibernate UserType. Here's an example of how to write the UserType:
import java.sql.*
import org.hibernate.usertype.UserType
class MoneyUserType implements UserType {
int[] sqlTypes() {
[Types.VARCHAR, Types.DECIMAL] as int[]
}
Class returnedClass() {
Money
}
def nullSafeGet(ResultSet resultSet, String[] names, Object owner) HibernateException, SQLException {
String currency = resultSet.getString(names[0])
BigDecimal value = resultSet.getBigDecimal(names[1])
if (currency != null && value != null) {
new Money(currency, value)
} else {
new Money("", 0.0)
}
}
void nullSafeSet(PreparedStatement statement, Object money, int index) {
statement.setString(index, money?.currency ?: "")
statement.setBigDecimal(index+1, money?.value ?: 0.0)
}
...
}
To use it in a domain class, map the field to the UserType instead of embedding it:
class Billing {
static mapping = {
amount type: MoneyUserType
}
Money amount
}