How to map Domain Object Properties to Columns - grails

I have this domain class.
class Book {
String code
String description
static mapping = {
table 'Book'
version false
}
}
and I have table BookStore with columns COD and DSC.
I need map to this table.
How can I achieve this?

If I understand your question correct, the sections within Mapping in the documentation should help you
For your example, the following should work:
class Book {
String code
String description
static mapping = {
table 'BookStore'
version false
code column: 'COD'
description column: 'DSC'
}
}
Also, within DataSource.groovy, make dbCreate = "update" under the appropriate environment that you are using. Refer the documentation on DataSource for this.
Hope this helps.

class Book implements Serializable {
String code
String description
static mapping = {
table 'BookStore'
version false
id composite: ['code']
code column: 'COD'
description column: 'DSC'
}
boolean equals(other) {
if (!(other instanceof Book)) {
return false
}
other.code == code
}
int hashCode() {
def builder = new HashCodeBuilder()
builder.append code
builder.toHashCode()
}
}

Related

How to get value in my show page in Grails

How to get the value as following codes with my show view page on Grails?
Person.groovy
package com
class Person {
String person
static constraints = {
person blank:false,nullable:true
}
static hasMany=[task:Task]
String toString(){return person}
static mapping={
}
}
Task.groovy
package com.moog
class Task {
String task
static constraints = {
task blank:false,nullable:true,unique:true
}
static belongsTo=[person:Person]
static hasMany=[tag:Tag]
String toString(){return task}
}
Tag.groovy
package com
class Tag {
String tag
static constraints = {
tag blank:false, nullable:true
}
static belongsTo=[task:Task]
String toString(){
return tag
}
}
First of all try a better wording for your collections
static hasMany=[tasks:Task] // in Person.groovy
static hasMany=[tags:Tag] // in Task.groovy
In your person show.gsp try something like
<g:each in=${person.tasks} var="task">
<p>${task}</p>
</g:each>
If you do not use scaffolding and write you own controller methods to create your entities than maybe this helps you further:
def task = new Task(task:"Clean room")
def person = Person.get(1)
person.addToTasks(task)
person.save()

Grails: Legacy DB - Record with composite Id won't update

I'm having problems trying to update a record on a Grails 2.3.7 Project
I don't want to modify the fields that are part of the composite Id, I just want to update the other fields.
Just one class, few properties, but every time I try to update, it throws me the "not unique error" when this lines runs:
personInstance.validate()
if (personInstance.hasErrors()) {
respond personInstance.errors, view:'create'
return
}
My class looks like this:
class Person implements Serializable {
static constraints = {
name(unique: lastName)
}
static mapping = {
id generator: 'assigned'
id composite: ["name", "lastName"]
}
//Override equals and hashcode methods
boolean equals(other) {
if (!(other instanceof Person)) {
return false
}
other.name == name && other.lastName == lastName
}
int hashCode() {
def builder = new HashCodeBuilder()
builder.append name
builder.append lastName
builder.toHashCode()
}
String name
String lastName
String description
}
And the controller action:
def update() {
def personInstance = Person.get(new Person(name:params.name, lastName:params.lastName))
personInstance.properties = params
personInstance.validate()
if (personInstance.hasErrors()) {
respond personInstance.errors, view:'create'
return
}
personInstance.save flush:true
request.withFormat {/*etc...*/}
}
When I use validate(), it throws me a Grails unique key error, when I avoid validation its a BD not unique PK error.
Is like Grails didn't know if I want to do an insert or an update when I personInstance.validate().
Is there a way to manage this in a correct way that I'm not seeing?
Or am I forced to avoid validation?
am I doing something wrong?
Thanks in advance.
I believe the GORM mapping DSL expects just one id definition. Try combining your two id lines into just this one:
id generator: 'assigned', composite: ["name", "lastName"]
Also, in addition to implementing Serializable, your domain class should override equals and hashCode, as described under "Composite Primary Keys" here: http://grails.org/doc/latest/guide/single.html#identity

Grails createCriteria on abstract domain

I am quite curious how one would use the criteria builder to access fields of an inherited class.
Let's assume we have the following class:
class A {
String fieldOne
String fieldTwo
static hasMany = [childs: AbstractChildClass]
}
and the abstract child class would look like this:
abstract class AbstractChildClass {
Integer valueOne
Integer valueTwo
A a
static mapping
tablePerHierarchy false
}
}
of course there are several extending classes such as:
class ExtendingClassOne extends AbstractChildClass {
DesiredObject desiredObject
static mapping = {
tablePerHierarchy false
}
}
let's also assume there is the class DesiredObject which looks like this:
class DesiredObject {
String infoA
String infoB
}
The question is how one would get the fields infoA and infoB by creating a criteria for class A. My approach so far is this:
A.createCriteria().list {
childs {
desiredObject {
ilike('infoA', '%something%')
}
}
}
This of course does not work because in the table ExtendingClassOne is only the id of the desiredObject and I have no clue how to join the object with the criteria builder to get its fields.
Thank you for reading.
Marco
don't expect 100% match between your domain model and the DB schema it's related to.
In your case the polymorphism would work only with tablePerHierarchy true for AbstractChildClass.
If you do want to stick with tablePerHierarchy false, you can define your class like:
class A {
static hasMany = [ childrenOne:ExtendingClassOne, childrenTwo:ExtendingClassTwo ]
}
thus your query would be as simple as:
A.withCriteria{
for( String c in [ 'childrenOne', 'childrenTwo' ] ){
"$c"{
desiredObject {
ilike('infoA', '%something%')
}
}
}
}

Assigned domain class id wierdness with Grails

I want to set the id manually on grails 1.3.7
This compiles but the id is always 0
//in bootstrap
def it1 = new ItemType(id:4,name:'feature')
it1.save()
//domanin class
class ItemType {
String name
int id
static constraints = {
id(unique:true,blank:false)
name(blank:false)
}
static mapping = {
id column: 'ItemTypeId', generator:'assigned'
name column: 'Name'
version false
}
}
This compiles and id 4 (as required)
//in bootstrap
def it1 = new ItemType(name:'feature')
it1.id=4
it1.save()
//domanin class
class ItemType {
String name
//int id
static constraints = {
id(unique:true,blank:false)
name(blank:false)
}
static mapping = {
id column: 'ItemTypeId', generator:'assigned'
name column: 'Name'
version false
}
}
So my question is there a way to have id as prop but assigned?
Had the same problem a few days ago: my own id in GORM
It seems that it is a feature :-)

Grails one-to-many mapping with joinTable

I have two domain-classes. One is a "Partner" the other is a "Customer". A customer can be a part of a Partner and a Partner can have 1 or more Customers:
class Customer {
Integer id
String name
static hasOne = [partner:Partner]
static mapping = {
partner joinTable:[name:'PartnerMap',column:'partner_id',key:'customer_id']
}
}
class Partner {
Integer id
static hasMany = [customers:Customer]
static mapping = {
customers joinTable:[name:'PartnerMap',column:'customer_id',key:'partner_id']
}
}
However, whenever I try to see if a customer is a part of a partner, like this:
def customers = Customer.list()
customers.each {
if (it.partner) {
println "Partner!"
}
}
I get the following error:
org.springframework.dao.InvalidDataAccessResourceUsageException: could not execute query; SQL [select this_.customer_id as customer1_162_0_, this_.company as company162_0_, this_.display_name as display3_162_0_, this_.parent_customer_id as parent4_162_0_, this_.partner_id as partner5_162_0_, this_.server_id as server6_162_0_, this_.status as status162_0_, this_.vertical_market as vertical8_162_0_ from Customer this_]; nested exception is org.hibernate.exception.SQLGrammarException: could not execute query
It looks as if Grails is thinking partner_id is a part of the Customer query, and it's not... It is in the PartnerMap table, which is supposed to find the customer_id, then get the Partner from the corresponding partner_id.
Anyone have any clue what I'm doing wrong?
Edit: I forgot to mention I'm doing this with legacy database tables. So I have a Partner, Customer and PartnerMap table. PartnerMap has simply a customer_id and partner_id field.
Given the way 1-many works when you want a join table, I think it's not possible with standard GORM to make it bidirectional and access a Customer's Partner. But you can map the join table with a domain class and access things that way:
Customer:
class Customer {
String name
def getPartner() {
PartnerMap.findByCustomer(this)?.partner
}
}
Partner:
class Partner {
String name
def getCustomers() {
PartnerMap.findAllByPartner(this)*.customer
}
}
PartnerMap:
import org.apache.commons.lang.builder.HashCodeBuilder
class PartnerMap implements Serializable {
Partner partner
Customer customer
boolean equals(other) {
if (!(other instanceof PartnerMap)) {
return false
}
other.partner?.id == partner?.id &&
other.customer?.id == customer?.id
}
int hashCode() {
def builder = new HashCodeBuilder()
if (partner) builder.append(partner.id)
if (customer) builder.append(customer.id)
builder.toHashCode()
}
static PartnerMap get(long partnerId, long customerId) {
find 'from PartnerMap where partner.id=:partnerId and customer.id=:customerId',
[partnerId: partnerId, customerId: customerId]
}
static PartnerMap create(Partner partner, Customer customer, boolean flush = false) {
new PartnerMap(partner: partner, customer: customer).save(flush: flush, insert: true)
}
static boolean remove(Partner partner, Customer customer, boolean flush = false) {
PartnerMap instance = PartnerMap.findByPartnerAndCustomer(partner, customer)
instance ? instance.delete(flush: flush) : false
}
static void removeAll(Partner partner) {
executeUpdate 'DELETE FROM PartnerMap WHERE partner=:partner', [partner: partner]
}
static void removeAll(Customer customer) {
executeUpdate 'DELETE FROM PartnerMap WHERE customer=:customer', [customer: customer]
}
static mapping = {
id composite: ['customer', 'partner']
version false
table 'PartnerMap'
}
}
Since you're not using hasMany, you lose the addToXXX dynamic method, but you can call PartnerMap.create() to relate two instances. You also lose the collection and back-ref in the domain classes, but I added utility methods for those.

Resources