Can grails domain class include custom criteria in every query? - grails

I'm creating a domain class that will connect to an existing database. Unfortunately multiple domain objects are stored in the same table (the table is very generic), and I'm trying to find a way to include additional criteria in each query that is made through GORM.
For example, I have an Article domain class which exists in the exp_channel_data table. The table has site_id and channel_id columns, which will be used to indicate if the row is actually an Article (where site_id=2, and channel_id=3).
I can setup custom constraints to make sure that validation works properly:
static constraints = {
site_id validator: { it == 2}
channel_id validator: { it == 3}
}
But I want to prevent invalid Articles from even being returned in the first place (keeping things clean, and also for performance reasons).
What I'm envisioning is the ability to override every query that goes out from my domain class, and insert where site_id=2 and channel_id=3 so that I don't even see invalid rows.
Any thoughts would be appreciated, thanks in advance.
UPDATE
After using the hibernate-filter plugin (suggested below), this is what I'm using in the domain class to prevent unnecessary entries from being returned.
static hibernateFilters = {
site_idFilter condition: 'site_id=2', default: true
channel_idFilter condition: 'channel_id=3', default: true
}

From what you are describing here, since it's per domain class, this looks to be a perfect situation for using the Hibernate filters plugin for Grails. This way you can define default constraints to be applied to criteria from those domains. Well worth a look to see if it will meet your needs.

Related

Grails dynamic "inList"

This is almost identical to this old question: Dynamic define the inList constraint using database query which was essentially unaddressed, perhaps there have been advances in the years since that was asked.
I'd like to populate the inList parameter of a domain attribute with values from another domain. Due to auto-generated views (scaffolding, filterpane), this needs to come from inList rather than a custom validator.
class MyDomain {
String someValue
static constraints = {
someValue(nullable: true, maxSize: 50, inList: SomeOtherDomain.list()*.name)
}
}
This gives the following error on startup:
Caused by: java.lang.IllegalStateException: Either class [thepackage.SomeOtherDomain] is not a domain class or GORM has not been initialized correctly or has already been shutdown. Ensure GORM is loaded and configured correctly before calling any methods on a GORM entity.
I know, the "correct" way to handle this is to make someValue an instance of SomeOtherDomain instead of just storing the name, but that doesn't quite fit. We want to be able to delete an instance of SomeOtherDomain without breaking the saved value of the owning domain... the domain with the deleted value will be invalid going forward, and would have to be updated before saving, but archived/locked records will still exist and can be displayed.
You can specify value lists for filterpane like this:
<filterpane:filterPane domain="MyObject" filterPropertyValues="${['someValue':[values: SomeOtherDomain.list().collect{it.name}]]}" />
And then just use a custom validator to actually validate. I'm not sure what scaffolding might use the inList but easy enough to get around that if you're OK with replacing a few scaffolded pages with static ones.

use grails unique constraint only for generating DDL

I would like to generate multicolumn unique constraints in Grails such as one defined in following entity class
class Relationship {
Element source
Element destination
Type type
// other properties omitted
static constraints = {
type unique: ['source', 'destination']
}
}
but I don't want to have that constraint active during the validation as it consumes lot of resources (see alternative to grails multicolumn unique constraint (optimistic inserts)) for stats.
Is there any way to achieve that? What are the alternatives to generate the unique index automatically (with checking for existing one)?
I've done this in an app where I knew that a column's values were unique based on how they were generated, so I didn't want Grails to run a select query during validation, but wanted the database check just in case something weird happened.
I would do this using a database migration. Add whatever constraints and indexes you like, in addition to the updates that are needed to keep the code and database in sync (e.g. adding/removing columns or tables, changing column types, etc.)

How can we create our own custom validation

I am using grails 2.4.3 with database Neo4j with SDN ,We don't use Grails plugin so grails doesn't support Neo4j and if we create our domain classes in domain package then it gives us an error.
So We create our domain in Services package. My First Question is:
We are right or we have to do another thing?
My another question is to provide the validation in this concept. We use the Command Object for it. So now we need some Custom validation for unique. I know we can use Validator for it, but we want that our logic only remain in Services. So can we create something like this?
static constraints = {
username size: 5..15
password size: 5..15, blank: false
userEmail email: true
}
username email:true
userName name:unique
I don't understand why you're so fixated on having to use a service for this. Creating a service annotated with #Validateable and using it as a non-GORM domain class seems very weird. If it works, cool, but it's sort of like driving to work in reverse the whole way. You'll get there (until you burn out the transmission) but it'll be a stressful drive looking in the rear view mirror and seeing everthing reversed the whole time.
Why not just put the classes in a sensible package under src/groovy and annotate those? You just need to register them in Config.groovy, e.g.
grails.validateable.classes = [
com.mycompany.myapp.User, com.mycompany.dto.Account]
You can do a uniqueness check, but not with the standard unique constraint. That's tied to GORM; it looks at the table or backing store for you domain class and runs a datastore-specific uniqueness query, but that doesn't apply here. But you can easily do the same thing yourself. Use a custom validator:
email validator: { value, obj ->
// run a Neo4j query checking to see if value has
// been used, the equivalent of
// "select count(email) from person where email=?"
// and return false if the count is not zero
}

Custom Join table in grails

I have a following domains
User (in database called usermanagement) and
Account (in another database xyz)
Its an old system so i cannot really change the architecture of the system. I have been assigned task to implement a system that a certain users can only access certain accounts. This is a classic case of many-to-many relationship but the problem lies in the fact that these two domains are in two different databases. I googled if that was possible but i realized that it was not possible. So I now am thinking of creating a custom join table to store info on which user are allowed access to which accounts. The table can have two columns 'accountId' and 'userId'. So for this, do i have to create a new domain in grails or is there any cleaver way of doing this ?
Thanks in advance.
If you create joinTable in which DB you are going to create it and how you are going handle updates in main (Account,User) tables and ceep your join table up2date ?
I think (for this case) you don't need join table, you need handle business logic in application level.
You cane have 2 Domain classes each one pointed to different dataSource(DataBase).
http://grails.org/doc/latest/guide/conf.html#multipleDatasources
As I searched for solution of this, I did not find any sustainable solutions. I eventually narrowed down the probable solutions to two:
1. Create a domain table (only) using sql, some sort of patch and use hard-coded queries in grails to write and access data to and from the table.
2. Create a domain class like AccountUser having properties clientId and userId
I choose the 2nd option, I wrote some additional methods and created a service to return user and client instance and I am done ! Anyways, thanks guys.
If the databases are "visible" to each other (on the same server or there is a db link between them), you should be able to map the domain classes using the fully qualified table names ('schema.tablename') in the mapping closure.
psuedocode:
class User {
static mapping = {
table "usermanagement.user"
}
static hasMany = [Account:accounts]
}
class Account {
static mapping = {
table "xyz.account"
}
}
http://grails.org/doc/latest/guide/GORM.html#tableAndColumnNames

add user define properties to a domain class

i have a requirement to allow the user to define some custom field in one of the system entities. do you have any suggestion/pattern/plugin that will help me add this feature to my application.
thanks,
Meni
You can add a Map property to your domain class and store arbitrary data there. It's rather limited though. It will generate a table with varchar(255) keys and values, so you need to manage any type conversions yourself, e.g.
class Thing {
String name
Map extraProperties = [:]
}
int age = 123
def thing = new Thing(name: 'whatever')
thing.extraProperties.age = age.toString()
thing.save()
...
def thing = Thing.get(thingId)
int age = thing.extraProperties.age.toInteger()
See section "5.2.4 Sets, Lists and Maps" at http://grails.org/doc/latest/ for the brief online docs.
Sounds like you want your application to be an infinitely adjustable wrench that users can modify at will. Is that fair?
I don't think it's possible or desirable. Think about what happens when you add an attribute to an existing domain object in Grails. The attribute is added to the ORM mapping, which means the tables have to be modified. The UI has another text box added for data entry; the list page has another column added to its table.
There's a lot going on when you add an attribute. How will you manage multiple users modifying the app all at the same time? What happens when one user is modifying a table while another is accessing the old version?
You ask too much. I don't think it's a reasonable requirement. Grails' sweet spot is rapid development of web-based CRUD applications. I don't think that includes modification by users at runtime.

Resources