简体   繁体   中英

Grails: Search with inheritance in domain class

I have this two domain models in my Grails application

class Pet {
    String prop1
    String prop2
}

and this

class Cat extends Pet {
    String prop3
    String prop4
}

Now, in my app, I have many classes that is extending Pets and I want to search Pet with criteria, specifying some properties that cannot exists in other pets.

How can I make possible this operation? If I try to make a search, when a result not contains the property, raise an exception.

I think, the thing you are trying is not possible. But you can achieve it using two queries:

First do a lower level query:

// Inject the bean
def sessionFactory

String statement = "select id from pet where prop1 = 'foo' or prop3 = 'bar'";
def session = sessionFactory.getCurrentSession()
def queryResult = session.createSQLQuery(statement)

Since the parent class Pet will have all the fields so doing the above lower level query with any field will work.

Now, get the domain instances using ids:

def pets = Pet.getAll(queryResult)

What you're trying to do is impossible due to how object-oriented programming works.

class Foo { }
class Bar extends Foo { }

In this example, an instance of Bar is a Foo also. But, an instance of Foo is not a Bar . In other words, a super-class does not know anything about its subclasses, where as a subclass knows about its super-class.

Back to your example, you cannot access prop3 nor prop4 from Pet simply because they are not Pet properties.

Working toward a solution

Given your classes as they are, I agree with Shashank Agrawal's solution. An SQL (not HQL or any other GORM query) is the only way to access all of the properties (actually the columns) by querying the pet table. Of course, this assumes you're using the default table-per-hierarchy inheritance. It will not work with table-per-subclass inheritance.

Given the assumption of table-per-hierarchy means you're already accepting nullable properties in all of Pet 's subclasses. It's a requirement. So, what you can do is

  1. Abandon the subclasses
  2. Put all of the properties in Pet
  3. Add a property to Pet to specify the pet type.

Note that this is basically what table-per-hierarchy already does at the database level. The difference is that it would not be inheritance, which makes all of the properties available from Pet .

def pets = Pet.withCriteria { eq('prop3', 'whatever') }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM