I was wondering if it is possible to assign a default value to a variable in a child class when it is defined in the parent class.
For the sake of an example, I'll take the environment of a camping site (couldn't think of a better one)
We have a lodging class (parent). A lodging can be either a tent site, a mobile home, chalets...etc. Only the tent site doesn't have a patio (by default). The other may or may not have one and also have some special specification that a tent site doesn't (dishes, covers...etc).
Now...I'm lazy and prefer to put the variable patio (boolean) in the lodging class and then, declare in the tent class patio has false by default.
Or should I create a patio variable in every child class ?
class Lodging{
String description
int capacity
Boolean patio
}
class Tent extends Lodging{
static mapping = {
patio defaultValue: false
}
}
When I create a new Tent instance, the mapping rules will be followed ? Or will it throw me an error that it doesn't recognize the variable ?
I haven't tried anything, but it crossed my mind and didn't manage to get the answer from the grails doc (or here).
Hope my explanations and question were understandable :)
you can use an initializing block in child classes like:
class Lodging{
String description
int capacity
Boolean patio
}
class Tent extends Lodging{
static mapping = {
patio defaultValue: false
};
{
patio = false
}
}
Please note the semi-colon that has to be there before the initializing block
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 want to include "created" and "modified" fields in all of my domain classes and would like to embrace the DRY principle if possible. I don't want to extend each class as I cannot do that for a second time so instead, I'm trying to implement an interface.
Consider:
interface AutoTimeStamp{
Date created
Date modified
}
class Dog implements AutoTimeStamp{
String breed
}
class Cat implements AutoTimeStamp{
String noOfLives
}
But when I try to create a new Dog or Cat I get:
Cannot set the property 'created' because the backing field is
final.
Any idea as to why this appears to be illegal? This works like a charm as an extended class.
The above answer is correct, to define an interface that has properties you need to do:
interface AutoTimeStamp{
Date getCreated()
void setCreated(Date created)
Date getModified()
void setModified(Date modified)
}
Then in the implementing classes you can define the properties
Date created
Date modified
dateCreated and lastUpdated is available in domain class by default.
If you want to disable autoTimestamp then use:
static mapping = {
autoTimestamp false
}
You should not forget that Groovy interfaces follow the same philosophy as Java interfaces. As such for every property in a Groovy interface:
PropertyType propertyName
means:
public static final PropertyType propertyName
You can also have a look here, please have a look on Guillaume Laforge's posts ;)
http://groovy.329449.n5.nabble.com/RFE-interface-properties-td386038.html
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
I have a Grails application with a bunch of domain classes, some with many fields, some of which have a hasMany relationship with the domain class in question. For this particular application I only have one "constraint", that is that every instance of every domain class must be unique. I don't care if an arbitrary field has the same value across multiple instances of the same domain class, so long as each instance is made unique by the value of some other field in that domain class. So basically I want validation to take place at a domain class instance level instead of the domain class field level. Right now I am doing that by using the very groovy #EqualsAndHashCode annotation to generate my equals and hashCode methods, then calling equals in a custom validator on some arbitrary field of a domain class.
Two questions:
Is there a more efficient way of validating a domain class is unique?
If no, then is there a way I can call my custom validator code on the domain class instance itself instead of going through one of the fields of the domain class instance?
#groovy.transform.EqualsAndHashCode
class MyDomainClass {
String some
int arbitrary
boolean field
static constraints = {
// The field I chose to validate on is irrelivant, I just need to run the validation code **somewhere**
arbitrary validator: { val, obj ->
return !MyDomainClass.getAll().contains(obj)
}
}
}
I should also add I'm looking for a generic (hopefully efficient) way to do this. I realize calling getAll() is very inefficient and instead calling some variant of find or performing an HQL query on the exact fields of each domain class would be much more efficient... it just takes a lot longer to write!
Examples
assert MyDomainClass.getAll().isEmpty() // true
def myDomainClass1 = new MyDomainClass( some: "foo", arbitrary: 1, field: true)
assert MyDomainClass.getAll().contains(myDomainClass1); // false
myDomainClass1.save(flush:true)
def myDomainClass2 = new MyDomainClass( some: "bar", arbitrary: 1, field: true)
assert MyDomainClass.getAll().contains(myDomainClass2); // false. Even though this has the same `arbitrary` value as myDomianClass1, it has a different `some` value which makes it unique.
myDomainClass2.save(flush:true)
def myDomainClass3 = new MyDomainClass( some: "foo", arbitrary: 1, field: false)
assert MyDomainClass.getAll().contains(myDomainClass3); // false. Even though this has the same `some` value as myDomainClass1 and the same `arbitrary` value as myDomainClass1 and myDomainClass2, it has a different `field` value which makes it unique.
myDomainClass3.save(flush:true)
This will ensure the combination of the 3 fields in the domain are unique. This also ensures the constraint is on the database level, instead of just application level.
class MyDomainClass {
String some
int arbitrary
boolean field
static constraints = {
some(unique: ['arbitrary', 'field'])
}
}
when i design database.I use embedded to embed common fields.but it's can't init dateCreated and createdBy,what'd i do?extends domain or embedded is right way to handle common fields?
code to say?
class Created {
Date dateCreated
Long createdBy
def beforeInsert()
{
dateCreated= new Date()
createdBy=0
}
}
class Updated {
Date lastUpdated
Long updatedBy
//it works?
def beforeUpdate(){
lastUpdated=new Date()
updatedBy=0
}
//it works?
def beforeInsert(){
lastUpdated=new Date()
updatedBy=0
}
}
class CreatedUpdated {
Created created
Updated updated
//Must use the embedded option, or the type of exception, can not find CreatedUpdated
static embedded = ['created','updated']
}
class Term {
String name
CreatedUpdated createdUpdated
static embedded = ['createdUpdated']
Term parent
static hasMany =[terms:Term]
static mapping = {
version false
}
String toString()
{
name
}
static constraints = {
name unique:true,size: 1..20
parent nullable: true
createdUpdated display:false,nullable:true
terms display:false
url url: true
}
}
or use extends?
class Term extends CreatedUpdated{
String name
Term parent
static hasMany =[terms:Term]
static mapping = {
version false
}
String toString()
{
name
}
static constraints = {
name unique:true,size: 1..20
parent nullable: true
terms display:false
url url: true
}
}
`
what is right to me?
I'd definitely make this example embedded rather than inherited. I don't think you should make this call based solely on the fact that objects contain common fields. Instead, you should use inheritance if it makes sense for your model using standard OO design techniques. For example, if "myClass is a myBaseClass" doesn't hold true, inheritance is probably the wrong solution.
In general, I'd stay away from classes like CreatedUpdated that are just a collection of properties and not an actual object from your domain. Java/Groovy has only single inheritance, so this only works if you have one base class like this.
Also, for that particular case, created and updated timestamps can automatically be applied by GORM. If you're using spring security, check out the audit-trail plugin for automatically creating createdBy and updatedBy columns.
In this particular case audit-trail plugin should suffice the requirements. However if you have such requirement for other fields wherein no plugin is available, then one of the possible solution could be to inject such common fields at compile time via AST Transformation. Internally audit-trail plugin uses this concept to inject those fields. Depending upon your requirement you can either use Global AST Transformations or Local AST Transformations.