How to Map Reference to Object with Composite Key ID - grails

Suppose I have the following:
class ObjectA implements Serializable {
Foo foo
String objectType
static mapping = {
version false
id composite: ['foo', 'objectType']
foo column: 'foo'
objectType column: 'objecttype'
}
}
Now, I need to reference this object from another Domain.
class ObjectB {
ObjectA objectA
columns {
objectA{
column name: 'foo'
column name: 'objecttype'
}
}
}
When I try and load an ObjectB, I get the following:
Cannot treat multi-column property as a single-column property
How should I be mapping this?

What are you attempting to do with the columns section, I only ask because I have am unfamiliar with that concept? This stack overflow link may help.
But, as show in link, if you want to reference the object you should create a relationship (the one in the example is unidirectional) between the two domains.
class Object B {
static hasOne[objectA:ObjectA]
....
}
There really isn't much more to it then that. You can access the fields from objectA within you views just by using ObjectBInstance.objectA.channelName.

Related

Grails does not fill in foreign-key field for one-to-many relation

I'm new to grails and must be missing something important in trying to define a one-to-many mapping without using a join-table.
I have a domain object Foo
class Foo {
static hasMany = [remarks: ChangeRemark]
static mapping = {
remarks column:'PART_REMARKS_ID', joinTable:false
}
}
and another domain object ChangeRemark
class ChangeRemark {
String remark
String name
}
I initialize a Foo object, and add two ChangeRemark objects to it as such
ChangeRemark remark = new ChangeRemark(remark:"test", name:"t").save(flush:true)
ChangeRemark remark2 = new ChangeRemark(remark:"test2", name:"y").save(flush:true)
Foo foo = new Foo().save(flush:true)
foo.addToRemarks(remark).save(flush:true)
foo.addToRemarks(remark2).save(flush:true)
When I print out the size of the remarks on foo it is indeed 2, however the database column for the foreign key PART_REMARKS_ID on the ChangeRemarks table is empty. This means after I restart my application the connection between the object and the remarks can't be made
What am I missing to have grails insert the Foo id in the table.
To avoid the join table use belongsTo to create a reference from ChangeRemark to Foo.
class Foo {
static hasMany = [remarks: ChangeRemark]
}
class ChangeRemark {
String remark
String name
static belongsTo = [foo: Foo]
}
When you do this, the change_remark table gets a foo_id foreign key. This means a ChangeRemark instance can reference only a single Foo instance; which I'm assuming is your intention.
This changes how you add ChangeRemarks:
ChangeRemark remark = new ChangeRemark(remark:"test", name:"t")
ChangeRemark remark2 = new ChangeRemark(remark:"test2", name:"y")
Foo foo = new Foo()
foo.addToRemarks(remark)
foo.addToRemarks(remark2)
foo.save(flush: true)
Basically, Foo is responsible for persisting itself and the ChangeRemarks.

Is there any way to return a Map with some fields from a createCriteria in Grails?

I have an object where I need to query and return it as a Map, but I don't want to iterate over the object again as I'm already doing a query and it can get a bad performance.
List<MyObject> myObjectList = MyObject.createCriteria().list(params) {
...
}
But what I need is a Map like:
myObjectList.each { MyObjectList myObject ->
myMap.add([person: myObject.person, myObject: myObject, listIntoObject: myObject.listInsideObject as List])
}
I found another way to get a map like this but it still not the better way to get a Map from a List that I'm querying with GORM...
myMap = myObjectList.collect{ [person: it.person, myObject: it, listIntoObject : it.invoiceDetails as List] }
Is there a better way to get a Map using GORM?
You can use org.hibernate.transform.Transformers to transform the result to an entity map
import org.hibernate.transform.Transformers
def criteria = MyObject.createCriteria()
criteria.resultTransformer(Transformers.ALIAS_TO_ENTITY_MAP)
def myObjectList = criteria.list(params) {
...
}
You can also fall back to HQL as well. Refer the UPDATE section of a similar answer for more details.
You can use import org.hibernate.criterion.CriteriaSpecification with withCriteria() to transform the result in a Collection object, with properties chosen by you only:
import org.hibernate.criterion.CriteriaSpecification
def criteria = User.withCriteria(){
resultTransformer CriteriaSpecification.ALIAS_TO_ENTITY_MAP
createAlias 'personalData', 'p'
eq 'id', params.id
// ...and so on, then
projections {
property 'id', 'myId' // a property called 'myId', from User
property 'p.name', 'userName' // from personalData, a property mapped by a fk in User
property 'p.age', 'age'
}
}

GORM mongodb mapping to existing collection structure

I'm new to Grails&GORM so this may be a quick question. We are currently looking at using GORMs mongo support and I am having a few issues mapping to existing collection data. I basically want to map to a hierachical object structure whereby my object "Merchant" has reference to another parent merchant. The BSON structure is fairly simple i.e.:
{
name: "name",
parent_id: ObjectId("[Object Id ref]")
}
In my model I attempted to map this relationship as follows:
class Merchant {
ObjectId id
String name
Merchant parent
static belongsTo = [parent: Merchant]
static mappedBy = [parent: "parentId"]
static mapping = {
collection "merchants"
}
static constraints = {
}
}
This resulted in the following BSON:
{
"_id" : ObjectId("4ea6be91ce5f56cd49f43ab8"),
"name" : "where will you g",
"version" : NumberLong(1),
"parent" : {
"$ref" : "merchants",
"$id" : ObjectId("4ea6be91ce5f56cd49f43ab8")
}
}
This has two issues, namely:
- The name of the parent merchant field is "parent" and not "parent_id", which is required.
- The value of the parent field has additional meta infomation other than the id in i.e. $ref : "merchants".
Is there anyway I can keep our existing BSON structure and still have a rich object mapping.
Cheers, Chris.
For the two issues, you need an additional mapping:
static mapping = {
collection 'merchants'
parent attr:'parent_id', reference:false
}
You should also drop the mappedBy block, since you only need it when there are multiple fields of the same type.
Finally, note that reference:false is the default in recent versions of the plugin (1.2+ I think). Note that 'attr' is named 'columnName' in other flavours of GORM.

How to use a custom id column in GORM

I have a domain object that has a property that i want to be used as the id by GORM, the reason being is that ill be saving lists of this object and i want existing rows to be updated if the id already exists in the database
Lets assume that my property i want as the PK is called listId
Ive seen several approaches to this, which is best?
1:
id generator: 'identity', column: 'listId'
2:
static mapping = {
id generator:'assigned'
}
def getKey = {
return listId;
}
or something entirely different?
static mapping = {
id generator: 'assigned', name: "listId", type: 'string'
}

Issue with multiple hasMany relationships to the same domain class when using composite id

I am getting this exception: org.hibernate.MappingException: collection foreign key mapping has wrong number of columns: Room.cellsOrig type: component[locationX,locationY]
class Room implements Serializable {
Integer locationX;
Integer locationY;
List cellsOrig = []
List cells = []
static hasMany = [cellsOrig: Cell, cells: Cell]
static mapping = { id composite['locationX', 'locationY']
cells joinTable:'room_cells'
cellsOrig joinTable:'room_cells_orig'
}
static constrants = { locationX(nullable: false) locationY(nullable: false)
cells(nullable: false) cellsOrig(nullable: false)
}
}
I think I am doing the joinTable wrong, but without the joinTables any access to a Room instance's cell or cellOrig properties would cause org.hibernate.HibernateException: null index column for collection: Room.cells.
Any suggestions for how to do the joinTable in such a way that it can handle the composite id?
If you want to create one to many from the class. in the Cells class which an class add belongs to the Room that would take care of it....
Harjit

Resources