The definition of Map is
class Map {
MapCoordinate center
Integer zoom
List path
static hasMany = [path: MapCoordinate]
static hasOne = [center: MapCoordinate]
static constraints = {
}
}
The definition of MapCoordinate is
class MapCoordinate {
BigDecimal latitude
BigDecimal longitude
static belongsTo = [map: Map]
static mapping = {
latitude scale: 9
longitude scale: 9
}
static constraints = {
}
}
This simple script fails with the following exception
Map map = new Map()
def cent = new MapCoordinate(latitude: 0.123, longitude: 0.2424)
map.center = cent
map.zoom = 5
map.save(flush:true, failOnError: true)
Exception
org.springframework.dao.DataIntegrityViolationException: could not insert: [MapCoordinate]; SQL [insert into map_coordinate (version, latitude, longitude, map_id, path_idx) values (?, ?, ?, ?, ?)]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not insert: [MapCoordinate]
Can someone please explain to me what is the cause of this error? I appreciate your help! Thanks!
I think the problem here is that the MapCoordinate
has got only one belongsTo
definition. On the other hand, you have got hasOne
and hasMany
within the Map
. I suggest you change the structure of your domain classes to the following (including Randall's suggestion). With the mappedBy
you make sure grails is able to identify the two relations correctly.
class Map {
Integer zoom
SortedSet path
static hasMany = [path: MapCoordinate]
MapCoordinate center
static mappedBy = [path: "mapPath", center: "mapCenter"]
static constraints = {
center nullable: true
}
}
class MapCoordinate implements Comparable {
BigDecimal latitude
BigDecimal longitude
static belongsTo = [mapPath: Map, mapCenter: Map]
static mapping = {
latitude scale: 9
longitude scale: 9
}
static constraints = {
mapPath nullable: true
mapCenter nullable: true
}
int compareTo(other) {
if (id) {
id.compareTo(other.id)
}
else {
return -1
}
}
}
By adding the SortedSet
you should be able to preserve the ordering of the MapCoordinate
entries. However, the MapCoordinate
class then has to implement the Comparable
interface. Eventually, try to change the code as follows:
Map map = new Map()
def cent = new MapCoordinate(latitude: 0.123, longitude: 0.2424)
map.center = cent
map.zoom = 5
map.addToPath(new MapCoordinate(latitude: 0.33, longitude: 0.33))
map.addToPath(new MapCoordinate(latitude: 0.34, longitude: 0.34))
map.save(flush: true, failOnError: true)