I have two tables Users and Role
These two tables should have bi-directional relationship for security purposes, so I have followed hasOne combination in Users table and belongs to in Role table. But bi-directional relationship is not happening.
Can anyone please help in this ?
class User
{
Long number
Integer inhabitants
static hasOne = [ role: Role]
static constraints = {
role nullable: true, unique: true
}
}
class Role
{
Users user
static belongsTo = [user: Users ]
static constraints = {
}
}
Change Role to
class Role
{
Users user
static belongsTo = [user: User ] //you previously had Users here
static constraints = {
}
}
I use Grails Plugin spring-security-core and these two pages to help me setup.
Simplified Spring Security with Grails and
Tutorials - Reference Documentation.
It creates a table called UserRole that takes care of all that.
Related
i have two domain : User and Task such as :
1) a user can be the author of many tasks
2) a user can participate in many tasks,in the same time,a task can have many users which participate in
so,i want to define a one-to-many for 1) and a many-to-many for 2)
User{
static hasMany = [createdTasks : Task, //for one-to-many
assignedTasks : Task //for many-to-many
]
static mappedBy = [createdTasks : author]
}
Task{
User author
static hasMany = [assignedUsers : User]// for many-to-many
}
i think i have to define the owner side of my many-to-many relationship(assignedTasks-assgnedUsers)
?
anyone have a idea for defining the correct relationship satisfying my specification 1) and 2)?
thanks :)
I think you could accomplish this an easier way:
Really the relationships can just be on the task. The only reason to do what you are trying to do is to create a bi-directional relationship. This can be achieved simpler with declaring methods on the user to get the objects you want.
User{
Set<Task> getCreatedTasks() {
Task.findAllByAuthor(this)
}
Set<Task> getAssignedTasks() {
Task.executeQuery("""
Select t
from Task t join t.assignedUsers as tu
where tu = :user
""", [user: this])
}
}
Task{
User author
static hasMany = [assignedUsers : User]
}
Try this. Note the quotation in mappedBy.
User {
static hasMany = [
createdTasks: Task, // for one-to-many
assignedTasks: Task // for many-to-many
]
static mappedBy = [
createdTasks: 'author'
]
}
Task {
User author
static hasMany = [
assignedUsers: User // for many-to-many
]
static belongsTo = [
User
]
}
These are my domain classes:
class Game {
static hasMany = [players: User]
static belongsTo = [owner: User]
}
class User {
static hasMany = [games: Game]
}
If I try to use them as they are I get No owner defined between domain classes. So I need to set the owner of the relationship. Adding static belongsTo = Game to User causes Domain classes cannot own each other in a many-to-many relationship.
The only other option I can think of is to add static belongsTo = User to the Game class but I already have a belongsTo there.
How do I model this?
class Game {
User owner
static hasMany = [players: User]
static belongsTo = User
}
class User {
static hasMany = [games: Game]
}
You will have to specify one side of the relationship, as the owner, by doing this you will make User domain class as the owner of the many to many relationship.
The belongsTo field controls where the dynamic addTo*() methods can be used
from. we’re able to call User.addToGames() because Game belongsTo
User. we can’t call Game.addToPlayers().
Try this:
class Game {
User owner
static hasMany = [players: User]
static belongsTo = User
}
maybe it would be better not to use "belongsTo" at all? I mean using simple field reference like
class Game {
User owner
static hasMany = [players: User]
}
FYI,
I would be careful with using "owner" field name, it might cause problems when used somehow in a closure which has its own "owner" reference (e.g. in criteria builder)
I know it caused problems back in grails 1.3.X, I don't know if it's still the case
try this:
class Game {
User owner
static hasMany = [players: User]
static belongsTo = User
}
class User {
static hasMany = [games: Game, owns: Game]
static mappedBy = [games:'players', owns: 'owner']
}
this settings work for me. And here is a good thread for mappedBy: GORM mappedBy and mapping difference
I have a relationship between two domain class: User and Bank, user has many of bank and bank has many of user, the result table I call it as mm_user_banks that keep both table IDs for MM relationship.
class User {
String name
String password
Date createdAt = new Date()
Date loginAt
static hasMany = [banks:Bank]
static fetchMode = [banks: 'eager']
static constraints = {
}
static mapping = {
banks joinTable: [name: 'mm_user_banks', key: 'mm_user_id']
}
}
and Bank...
class Bank {
Long id
String name
static belongsTo = User
static hasMany = [users:User]
static constraints = {
}
static mapping = {
id generator: 'assigned'
users joinTable: [name: 'mm_user_banks', key: 'mm_bank_id'], lazy: false
}
}
I can save users with banks as well, but the problem is when I try to retrieve bank list from an user instance and it only fetch one row even if there is more than one row for this user in mm_user_banks table.
E.g:
User u = new User(name: 'user', password: 'pwd')
u.addToBanks(Bank.findById(1))
u.addToBanks(Bank.findById(2))
u.addToBanks(Bank.findById(3))
u.save(flush: true)
In database it is OK, fetching 3 rows, but when I get the user and see its bank list:
def user = User.findById(1) //OK
println "Size ${user.banks?.size()}" //only 1??? How?
Thanks in advance!
Just tested it out - "user.banks?.size()" returns "3". Are you sure that data in DB is OK?
Anyway, if you want to use eager fetching for collections then define it in "mapping" of User class (instead of "fetchMode" static field):
static mapping = {
banks joinTable: [name: 'mm_user_banks', key: 'mm_user_id'], fetch: 'join'
}
in Bank class use fetch: 'join' in mapping instead of lazy: false
Thanks so much, Sergei, but didn't worked out.
I fixed it in an ugly way, but this is was my remaining way out.
I created another domain class to mapping the MM table, so I did a mm_user_banks class. I use it to fetch records from bank or user and worked OK. To save banks for a user I actually do it in the old way as well, not changed from that. I guess this mighty not be the best way, but like I said, worked out.
I've tried "fetch: 'join'" and "lazy: false" and "static fetchMode = [banks: 'eager']" without success.
The new domain class is:
class UserBanks {
User user
Bank bank
static constraints = {
}
static mapping = {
table name: 'mm_user_banks'
user column: 'mm_user_id'
bank column: 'mm_bank_id'
}
}
I had the similar problem but in my case I had another relation between my equivalents to User and the Bank. This made the hasMany statement to use the wrong relation to map the many to many relation. In my case it was solved by adding a mappedBy statement to the relation:
class Bank{
...
static mappedBy=[users:'banks']
...
}
and
class User{
...
static mappedBy=[banks:'users']
...
}
or as it was in my case, since it was a uni-directional relation:
class ArticleGroup {
String name
static hasMany = [articles:Article]
static mappedBy = [articles: 'none']
static constraints = {
name(nullable:false, blank:false, unique:true, maxSize:100)
}
static mapping = {
table 'article_group'
sort 'name'
articles joinTable: [name:'article_group_article', key: 'articleGroup_id', column:'article_id'], fetch: 'join'
}
So essentially I have two classes:
Class User {
String Name
}
Class Project {
User requestedBy
static hasMany =
[
assignedTo: User
]
}
Now, I can set the requestedBy to say, User 1.
I can also do Project.addToAssignedTo(User 1).
The problem comes when I want to remove the user from assigned to when they already exist as the requestedBy. I can remove other users without problem:
Project.removeFromAssignedTo(User 1).save(failOnError: true, flush: true)
I get no errors of any kind, the data just simply does not get removed. Any help would be appreciated!
Thanks!
When defining multiple relationships to the same class, you should define the bidirectional relationship, and use the mappedBy property to define both sides of that relationship:
class User {
String Name
hasMany = [requestedProjects: Project, assignedProjects: Project]
}
class Project {
User requestedBy
static hasMany =
[
assignedTo: User
]
static mappedBy = [requestedBy: 'requestedProjects', assignedTo: 'assignedProjects']
}
Hopefully that solves your problem.
I have a User domain class, and a List one.
Each list must have an author (a user) and each user must have a "primary list". Only some of the lists will have the "primaryList" statute.
So.. somthing like
User:
List primaryList
List:
User author
static belongsTo = User
Of course this does not work as intended because the two relations are mistakenly taken as only one. I should also add a hasMany on the User and other belongsTo to the List..., but I don't want to complicate the example because I want to get the right answer from you.
You may need to use mappedBy to explain how the fields in User and List line up. Here are a couple domains that I wrote that allow a User to author many Lists but only set one to be "primary". There are a couple extra nullable constraints so you can use the scaffolded UI without getting into a chicken-and-egg scenario.
class User {
String name
FooList primaryList
static hasMany = [authoredLists: FooList]
static mappedBy = [primaryList: 'primaryOwner', authoredLists: 'author']
static constraints = {
primaryList nullable: true, unique: true
authoredLists nullable: true
}
String toString() { name }
}
I named this class "FooList" just to avoid confusion with the standard List class:
class FooList {
static belongsTo = [author: User, primaryOwner: User]
static constraints = {
primaryOwner nullable: true, display: false
}
}
Try using the map belongsTo approach:
static belongsTo = [user:User]
That way Grails should see the 2 properties as separate.