How do I create association by joining non primary key column - grails

class Contact {
String name
String number
}
class Message {
String text
String number
Contact contactInfo //If any
}
I need to join on Message.number = Contact.number. Any thoughts on creating association in Grails/GORM with non primary key column?

I'm pretty sure this isn't possible in GORM, and I don't know if it's even possible in regular Hibernate. But you can fake it:
class Message {
String text
String number
static transients = ['contactInfo']
Contact getContactInfo() {
Contact.findByNumber(number)
}
void setContactInfo(Contact contact) {
number = contact.number
}
}

Burt, this is possible with hibernate using the property-ref attribute

Related

find list using createcriteria nested object property

I have a domain like this
Employee {
Address address
String name
String title
}
and another domain
Address {
String country
String locality
String city
}
and now i want to find the all the employee with given city something like that i tried
def employees = Employee.where {
address {
city == params.city
}
}
but this is not working , how can i achieve this
You can write it like following
List<Employee> employees=Employee.createCriteria().list{
'address'{
eq('city',params.city)
}
}
Note: When the eq('city',city) (same parameter name) is used, it will not work.
The syntax for accessing properties of associations differs between criteria and where queries.
Where query
def employees = Employee.where {
address.city == params.city
}
See https://grails.github.io/grails-doc/latest/guide/GORM.html#whereQueries
Criteria query
def employees = Employee.withCriteria {
address {
eq('city', params.city)
}
}
See https://grails.github.io/grails-doc/latest/guide/GORM.html#criteria

Need help creating Grails executeQuery based on domain and lookup table

I have two classes: sample, and parameter. I also have a sample_sample_parameter lookup table which exists to hold the sample id and the parameter id. This is mapped in my grails app.
I was able to write an sql query that works in squirrel:
select s.* from sample s, sample_sample_parameters sp where s.id = sp.sample_id and sp.sample_parameter_id = 41
where 41 would be replaced with the parameter.id variable passed from the gsp page to the action. I have also tried to make it work with executeQuery but it tells me that sample is not mapped.
How do I turn this query into a gorm recognizable form?
class Sample {
Date collectionDate // date the sample was collected
Date sampleReceivedDate // date the sample arrived on site
Date dateCreated
String sampleComments // details about the sample
String labAccessionID // internal reference
String sampleGender // is it from a male or female?
String sampleAge // the age of the animal the sample was taken from
String sampleBreed // the breed of animal
String sampleNameID // patient name
String filepath
String enteredby
String sg
String mosm
static searchable = true
static hasMany =[sampleParameters:SampleParameter, ficsruns:Ficsrun]//[tags:Tag]// a Sample can have many parameters
/* mappedBy allows two tables share a common table. It creates two join tables, one for each.
* SampleParameter is the table being shared by Sample and SampleType tables */
static mappedBy=[sampleParameters:"samples"]//[tags:"domainClass1s"]/*http://www.van-porten.de/2010/09/multiple-many-to-many-in-grails/*/
static belongsTo = [sampleType:SampleType, labFinding:LabFinding, sampleSource:SampleSource, species:SpeciesList] // creates dependencies
static constraints = {
sampleType(blank:false)
sampleNameID(blank:false)
collectionDate(blank:false)
sampleReceivedDate(blank:false)
sampleComments(nullable:true, maxSize:1000)
labAccessionID(nullable:true)
sampleGender(blank:false, inList:["M","F","NM","SF", "UNK"])
sampleAge(nullable: true)
sampleBreed(nullable:true)
sampleSource(blank:false)
species(blank:false)
labFinding(nullable:true)
filepath(nullable:true)
enteredby(nullable:true)
sg(nullable:true)
mosm(nullable:true)
dateCreated()
}
/* This section is for static mapping to the hematology database*/
static mapping = {
version false
id generator:'sequence', params:[sequence:'SHARED_SEQ']
}
String toString(){
"${sampleNameID}"
}
}
class SampleParameter implements Comparable{
String name
String value
static hasMany = [
samples:Sample, //domainClass1s: DomainClass1,
sampleTypes:SampleType //domainClass2s: DomainClass2
]
static mapping = {
version false
id generator:'sequence', params:[sequence:'SHARED_SEQ']
}
static mappedBy = [samples:"sampleParameters",sampleTypes:"sampleParameters"]//[domainClass1s: "tags", domainClass2s: "tags"]
static belongsTo =[Sample,SampleType] //[DomainClass1, DomainClass2]
static constraints = {
name(blank:false)
//value()
//value(unique:true)
value (unique: 'name')
}
#Override public String toString() {
return name + " " + value
}
#Override
public int compareTo(Object o) {
if (o == null || this == null) {
return 0;
} else {
return value.compareTo(o.value)
}
}
}
As a first suggestion, when you have the paramter's id, do the following.
Parameter p = Parameter.get(params.id) // or wherever your id is stored
List<Sample> samples = Sample.findAllByParameter(p) // this assumes, the parameter property is actually named 'parameter'
Of course there is no error handling in place right now, but you'll get the idea.
Welcome to GORM, welcome to Grails.
The problem is that you're not using a HQL query in your executeQuery method. Instead you're using native sql. From the manual:
The executeQuery method allows the execution of arbitrary HQL queries.
Take a look at the specification to see ways of doing that. Which, by the way, are way easier than native sql.
List<Sample> samples = Sample.findAllBySampleParameter(SampleParameter.get(variable))
Give it a try?

How to indicate a field in domain class not to be created in the database

I have a domain class like:
class Product {
String name
String number
}
and I only want name field be created in the database as a column, I will generate the number field in the code, I don't want it to be a column of the Product table in the database.
What's the best way to do that?
class Author {
String name
String getUpperCaseName() { name.toUpperCase() }
static transients = ['upperCaseName']
}
See http://www.grails.org/doc/latest/ref/Domain%20Classes/transients.html

Grails - How to implement a foreign key relationship not using an id column?

Have been trying to look for an answer for hours, but have so far not managed to come up with an adequate solution, so I'm hoping someone here might have some more experience with Grails, and implementing custom relationships in it.
My problem is that I have two classes:
Company
OrderConfig
OrderConfig contains two references to Company. 1 for a consignee, 1 for a shipper. I implemented the relationship (see below), and everything looks dandy, with my order_config table containing both a consignee_company_id column and a shipper_company_id column.
However, I do not want or need a company_id column at all. I would prefer using the CompanyName as the identifying column. How can I prevent Grails from automatically adding the id column to the company table, and instead use the companyName column as the primary key, thus ensuring my order_config table will be generated containing the companyName and not the company_id?
I tried embedding the company in the orderconfig class, and wrestled with all kinds of other options including the mappings, however I ran into trouble with each and every one of them.
Thanks in advance!
My code so far:
class OrderConfig {
static hasMany = [consignee:Company, shipper:Company]
String toString() {
return "${consignee}"
}
static constraints = {
consignee (blank:false, maxSize:10)
shipper (blank:false, maxSize:10)
}
Company consignee
Company shipper
}
class Company {
String toString() {
return "${companyName}"
}
static constraints = {
companyName(blank:false, maxSize:10)
companyAddress1(blank:false, maxSize:40)
companyAddress2(blank:false, maxSize:40)
companyAddress3(blank:false, maxSize:40)
companyAddress4(blank:false, maxSize:40)
companyZipCode(blank:false, maxSize:36)
companyCountry(blank:false, maxSize:36)
}
String companyName
String companyAddress1
String companyAddress2
String companyAddress3
String companyAddress4
String companyZipCode
String companyCountry
}
You need to look at the advanced GORM config options in the documentation, in section 5.5.2.1
There is an example
class Person {
String firstName
static hasMany = [addresses:Address]
static mapping = {
table 'people'
firstName column:'First_Name'
addresses joinTable:[name:'Person_Addresses', key:'Person_Id', column:'Address_Id']
}
}
there you can see how they are specifying the key and column name on which to do the stuff.
Edit -- I reread your question: if you are asking how to change it so Company has an assigned id, you might be able to do something like this example
static mapping = {
id generator:'assigned', column:'column_name',name:'propertyName'
}
where more options are available here: http://www.grails.org/doc/1.3.x/ref/Database%20Mapping/id.html

Grails: use domain method in named query

in my domain model, I have a method that does something with my data.
e.g.
class Person {
String lastname
String firstname
String bigname() {
return lastname.toUpperCase()
}
static namedQueries = {
withBigname { name ->
eq(this.bigname(), name)
}
}
}
I want to use this method like a property in the named query, but this.bigname() only throws a java.lang.IncompatibleClassChangeError-Exception.
Does anyone know how to use domain methods in criteria and named queries?
Update: I now tried this:
class Person {
String lastname
String firstname
String bigname
static transients = [ 'bigname' ]
def getBigname() {
return lastname.toUpperCase()
}
static namedQueries = {
withBigname { name ->
eq('bigname', name)
}
}
}
But it only results in a "could not resolve property: bigname"-exception...
You cannot use class methods in queries, because queries are actually translated to SQL.
You might be able to get what you need by using writing the complexity in SQL a "SQL Restriction". Search for "SQL Restriction" on http://grails.org/doc/2.0.x/guide/GORM.html
HTH
Try to name the method in JavaBean getter and setter notation.
Rename method bigname() to getBigname().
On a static closure, you don't have a this. You'll either need to store the bigname in the Database, do some sort of case insensitive criteria.
looks like you are trying to accomplish this:
class Person {
String lastname
String firstname
static namedQueries = {
withName { name ->
eq('lastname', name, [ignoreCase: true])
}
}
}

Resources