I'm trying to model a isA relationship with Aqueduct. It is a one-to-one relationship but I need to make the #Relate column the primary key, however I cannot set both a #Relate and #Column tag. What would be the way to do this ?
Let's say I have a "user" table and a "admin" table. An admin is a user with more fields, for example user has an id, email, username and password, and admin has a user_id, access_level, fullname. Fields that are not needed for a regular user.
The way I'm coding this is like this:
class _User
{
#primaryKey
int id;
String email;
String username;
String password;
Admin admin;
}
class _Admin
{
#Relate(#admin)
User user;
int access_level;
String fullname;
}
But the migration can't be generated because I didn't declare a primary key for admin, and if I try to add #primaryKey or #Column above User user, I get an error that I can't both set Column and Relate metadata.
Related
Say I have a Domain Object User which contains an Organization field. I can map that using a foreign key and let hibernate take care of the rest like so:
class User {
String id
String firstName
Organization organization
static mapping = {
table 'user'
id column: "user_id", generator:'assigned'
organization column: 'organization_Id'
}
}
class Organization {
String id
String name
String address
static mapping = {
table 'organization'
id column: "organization_id", generator:'assigned'
}
}
This works fine, but when I want to query for all users in an organization I might have to do something like this
String orgId = "some id"
Organization org = Organization.findById(orgId)
List<User> users = User.findAllByOrganization(org)
It would be convenient to not have to pass the Organization domain object and instead just pass the Organization.Id which is the foreign key on the User table.
How I want my code to look is the following:
String orgId = "some id"
List<User> users = User.findAllByOrganization(orgId)
After researching, it seems like this is not possible, I need to first query for the Organization and then use that object. Is there a way I am unaware of?
One way I like to do it is to use a proxy of your domain object instead of a hydrated instance of it. You can use load() to obtain the proxy. This means no database call is made as long as you don't access any of the domain object's properties beyond the id.
def users = Users.findByOrganization(Organization.load(orgId))
You can use a Criteria:
String orgId = "some id"
List<User> users = User.createCriteria().list {
organization {
idEq(orgId)
}
}
You have two options there:
add a redundant orgId field to you User class and use it for the
lookup.
Use a fake object for your lookup:
.
Organization org = new Organization()
org.id = 'someId' // looks strange, but you can not use id inside constructor
def users = Users.findAllByOrganization org
using asp mvc 4.
When the user goes to a student record, the URL says:
http://studentTracker.org/Record/Student?studentId=380
Currently a user can change the studentId right there in the url and get that students record, unless it doesn't exist. How can I either hide the query string part of the url, or detect/validate at the controller if the user has changed the url?
First, you cannot stop a user from doing anything, really, especially something like changing an id in a URL. What you can do is ensure that if they do so, they get something like a 404 or 403, instead of the actual content.
The way to do that is to do object-level permissioning, which basically just means tying the object to the user(s) allowed to view/edit it in some way. Usually, this will done via foreign key to something like your "user" entity or something broader like a group or role.
For example, if the "Student 380" record is owned by jdoe, then you can prevent access to it by anyone but jdoe by first adding a foreign key to your "user" entity on your "student" entity. (Assuming Identity, since unspecified):
public class Student
{
...
[ForeignKey("Owner")]
public string OwnerId { get; set; }
public virtual ApplicationUser Owner { get; set; }
}
Then, in your action, instead of querying by just the id, you query by both the id in the URL and the id of the authenticated user:
var userId = User.Identity.GetUserId();
var student = db.Students.SingleOrDefault(m => m.Id == studentId && m.OwnerId == userId);
if (student == null)
{
return new HttpNotFoundResult();
}
Now, if the user changes studentId but is not set as the "owner" of the student that matches, they'll get a 404.
I have a table called person with primary key as id and in the same table I have a foreign key as master_id that references id (primry key) in the same table person. How do I create my domain class in grails for person. ?
Table Person
Integer person_id PK auto_increment
String name
String address
String city
Integer FK master_id references Person(person_id)
Just create a field of the appropriate type with a name of master:
class Person {
Person master
}
I am new to Grails and GORM and I am trying to One to Many relationship but not with default id field. Here is my scenario:
Table structure in the database:
USERPROFILE
iduserprofile
username
ROLE
idrole
rolename
USER_ROLE
iduserprofile
idrole
Domains:
class Userprofile {
long iduserprofile
String username
static mapping = {
datasource 'ALL'
id name: 'iduserprofile'
version false
}
class Role {
long idrole;
String rolename;
static mapping = {
datasource 'ALL'
id name: 'idrole'
version false
}
}
class UserRole {
Userprofile user
Role role
static mapping = {
datasource 'ALL'
version false
}
}
When I try to get the user or role object from UserRole domain, it is always looking for user_id or role_id in the USER_ROLE table.
Why is it not looking for iduserprofile or idrole? How can i change the code to look for isuserprofile or idrole?
Thanks
GORM by convention will use/generate id as identifier for your domains. If you have legacy tables or just a desire to break convention, you'll need to specify your custom column names. For example for Role mapping, add the following:
static mapping = {
datasource 'ALL'
id name: 'idrole', column: 'idrole'
version false
}
It seems to me that the easiest thing to do would be to copy your database and then change the names of the id fields if you have legacy tables. If not then just make life simple by conforming to convention.
I'm new to Groovy and HQL querying but I can't find a solution to this anywhere so it's driving me nuts.
I have two Domain classes which have a one to many relationship defined (a user can have many companies) and I effectively need to do (what would traditionally be called) 'a table join' but clearly with objects.
The classes go like this:
class User {
transient springSecurityService
static hasMany = [company: Company]
String username
String password
boolean enabled
boolean accountExpired
boolean accountLocked
boolean passwordExpired
...
...
...
}
... and the company class
class Company {
static scaffolding = true
String name
String address1
String address2
String address3
String address4
String postCode
String telephone
String mobile // mobile number to receive appointment text messages to
String email // email address to receive appointment emails to
static hasMany = [staff: Staff]
static belongsTo = [user: User]
...
...
...
}
Gorm has created an user_id field within the company table but any attempt to use this in a query returns an error.
So how would I do something like:
select * from user u, company c, where u.id = c.user_id;
What is the best way to do this?
You can effectively use join on the association something like:
HQL
select * from User as u inner join fetch u.company as companies where u.id = ?
Note that using fetch in the query would eagerly fetch the associated collections of companies for a user
findAll()
User.findAll("from User as u inner join fetch u.company as companies where u.id = ?", [1])
Benefit of using findAll instead of HQL is that you can easily implement pagination something like:
User.findAll("from User as u inner join fetch u.company as companies where u.accountExpired = true", [max: 10, offset: 5])
To get a concrete implementation and really understand things in details I would insist to have a look at findAll and HQL associations.