I have two classes in my Grails application. One is derived from the other. Is there any way to easily get the last instance of the second class created for the first class. Please see example:
class korridor {
String name
String description
static hasMany = [exceptions: Exception];
}
class Exception extends TerminKorridor{
String type;
static belongsTo = [terminKorridor: TerminKorridor]
}
I want to get the last exception created for a specific korridor.
Something like this: terminKorridor.exceptions.getLast()
There is no "last"
exceptions in your case is a Set. A Set has no order. Change your collection type to a List in the korridor class and then it will have an order. Mind you this requires a schema change to store the index.
Here is the link to the section of the user guide that explains this http://grails.org/doc/latest/guide/GORM.html#sets,ListsAndMaps
Related
I'd like to use an Enum or String in place of column class to map on table inheritance in Grails.
For exemple
#Entity
#Table(name = "person")
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#DiscriminatorValue("USR")
#DiscriminatorColumn(length = 3, discriminatorType = DiscriminatorType.STRING, columnDefinition = "CHAR(3) NOT NULL", name = "type")
public class People implements Serializable {
I couldn't find a way to change it into documentation.
Going to try to answer your question but in all honesty unsure where your point is wavering towards since it is left open ended as to to the actual question raised Inheritance and there appears to be no signs of inheritance on example provided.
My first pointer would be here.
This does work or had it working on default grails 3.2.8 but upon updates to latest gorm there was issues with updating existing records. I gave up and did it as separate classes at the time.
If your question relates to having table per class then above setup is what you need for grails.
Typically you would do :
abstract class Something {
static mapping = {
cache true
//tablePerConcreteClass false
tablePerHierarchy false
//discriminator value: 'institution'
}
}
class SomethingElse extends Something {
static mapping={
//discriminator value: 'somethingElse'
}
}
The abstract class definition vs non abstract has different adverse effects into how your tables get created and how your whole model will then work. It all depends on the requirement.
The problem with above is when it comes to querying the class in HQL I faced a problem where when I tried to query instance.class I got a numeric number back from HQL rather than actual domainClass instance and obviously discriminator was first point of reach.
The actual trick in these extended classes is if in HQL something.class does not return actual class name to try
String query = """ select new map(type(s) as className,s.id as id) from Something s """
The type(s) will now return actual string class name. (Maybe where you are stuck)
Usually you can do in HQL:
when s.class = SomethingElse then do something
and HQL will work out the actual className based on that matching domainClass name.
Somehow I don't think this is what you are after though
I have 2 domains:
Incident:
class Incident {
String title
String description
}
static mapping = {
tablePerHierarchy(false)
}
And IncidentWithTimers which extends Incident:
class IncidentWithTimers extends Incident {
int currentResponseTime
Date responseTimeEndDate
}
IncidentWithTimers is not an actual table in the database, it's a database view.
Now when I try to get an Incident instance from a controller, it somehow returns an IncidentWithTimers instance:
def index() {
Incident curIncident = Incident.get(params.incident)
println(curIncident.getClass())// "class IncidentWithTimers"
}
Since this domain is a view, I disabled all modifications by throwing exceptions in the beforeInsert/Update/Delete, in the IncidentWithTimers class.
When I try to modify and save the curIncident, it tries to access the beforeUpdate(), and throws the error, while I never wanted to change the IncidentWithTimers in the first place.
What can I do about this?
The problem is that the view includes every Incident, not a subset of them as would happen with a subclass. As you said, every IncidentWithTimers is an Incident.
The solution is to either use a query instead of a subclass, or make IncidentWithTimers an independent duplicate class rather than a subclass.
I think the former is the best option because the intent is clear.
My class User.groovy in a grails projects contains the following Set
Set<GlobalRole> globalRoles
static hasMany = [globalRoles: GlobalRole]
whereas GlobalRole is an enum
enum GlobalRole {
GLOBALROLE_MGR('Manager'),
...
GlobalRole(String id) {
this.id = id
}
}
in one of the views (edit) i present the following select on the user
from="${com.path.classification.GlobalRole?.values()}"
which works fine.
however: this needs to be dynamic and needs to work with various enums. All of them are in
com.path.classification
eg
com.path.classification.LocalRole
com.path.classification.InvestmentType
the only thing i have available is the member of the hosting class (here user), for example:
${domainInstance}?.${property.name}
which yields the Set user.globalRoles
my question: is there a way to deduct the values of an enumeration by having access to a Set containing some of them?
e.g. something in the way of this (not working!)
user.globalRoles.elements.class
to be able to generate the source dynamically?
Found a solution:
${userInstance?.domainClass.getPropertyByName('mySetName').getReferencedPropertyType().values()}
to get a list of all possible enum values.
I'm facing a issue regarding inheritance in Grails.
I have a domain class Person.grooy:
class Person{
String name
String contactNumber
Address address
}
Now I'm extending Person.groovy for Employee and Customer like:
class Employee extends Person{
String designation
}
class Customer extends Person{
String interest
}
Now I want separate table in my database for Employee and Customer having columns of Person i.e name,contactNumber and associate address key.
How could I achieve this. I searched every where but there is nothing for this aspect.
Is this one approach is not possible in GORM.
Please answer.
Thanks Guys
Finally I managed to get what I want just by placing a grails.persistence.Entity annotation to my child domain classes. I also make my parent i.e. Person.groovy abstract and place in src/groovy.
Now I have database hierarchy as I expected but some scaffold issues in controller still persist that will also sorted out with your help.
You need to disable table-per-hierarchy, which is by default enabled in Grails
class Employee extends Person{
String designation
static mapping = {
tablePerHierarchy false
}
}
table-per-hierarchy Ref
If you put your Person class in src/java or src/groovy it won't be mapped to the db.
Remember to import it into your Employee and Customer classes
import com.yourPackage.Person
class Employee extends Person{
}
It looks like inheritance is not the approach we need to follow here. You should create composition with Person class and it will store the properties of Person class in Employee.
class Employee {
Person person
String designation
static embedded = ['person']
}
Gorm Composition
you can put it inside src/java, but that solution will not be standard, as it really will not be treated as a grails domain example once you get deeper into the application.
For example, if you want to create a controller or a test script on the extended domain as per the previous answer, it will be complicated.
As of grails 2.2.x I believe, grails provides you with mapWith. You can use that for a more maintainable solution
class Employee{
static mapWith = "none"
}
We use dynamic scaffolding in our project and hence place maximum coding in Domain itself.
I have a requirement where I want to retrieve a collection for a Domain class property from the same domain class.
Example :
class Person{
String name
String school
}
school property should be a dropdown containing list of all schools so far available in the Person table. If no value available, it can be empty dropdown.
Any suggestions to achieve this in domain class itself?
That is what
static hasMany is for: http://grails.org/doc/latest/ref/Domain%20Classes/hasMany.html
in your case, something like below will work , once you create a School Domain object:
class Person{
...
static hasMany = [schools: School]
...