I am having a domain class arHistory as follows:
package ars
import ars.AccessRequest
import gra.Users
class ArHistory {
Long id =2340
Users updatedby
Date updatedon
String requeststatus
static hasMany=[accessrequests:AccessRequest]
static constraints = {
requeststatus(blank:false, nullable:false)
}
Now after I run the application the GORM create tables ar_history and ar_history_access_request (the join table for one to many relationship)
The join table above has only 2 foreign keys, the table itself has no primary key id
I wanted to know 3 things,
1) do I need to have a primary key id for the join table
2) if yes how do I create the id (do I create it manually through mysql)
3) whats the advantage of having hasMany() instead of having a class variable AccessRequest defined in ArHistory, is it just normalised data?
Regards
Priyank
You don't need primary key in join table, since you don't allow duplicates with hasMany. Read the documentation of hasMany: "Grails will automatically inject a property of type java.util.Set into the domain class based on the hasMany setting". Thus, primary key is not needed.
What do you mean by third question? hasMany allows you to add many AccessRequest objects to a collection.
Related
I have one table called countries which has a field i.e ID with primary key and the other table is customers which has a field called primary_country. I want to join both the tables in cakephp way, but always it is taking customers.country_id which is not present in the table. I am using primary_country because the table also has alternate_country field. so i can't use country_id. Please provide me any solution so that I can fetch the country names on the basis of primary_country and alternate_country.
You'll need to modify your table object with the foreign key, as mentionned here:
https://book.cakephp.org/3.0/en/orm/associations.html
It could be something like that, in your case :
class CustomersTable extends Table
{
public function initialize(array $config)
{
$this->belongsTo('Countries')
->setForeignKey('primary_country');
}
}
But i must say that if your model is still under conception, you may want to make an third table customer_countries and make an 'hasMany' relation between 'customers' and 'countries'. Limiting records for one customer to only two countries, and ordering them between 'primary' and 'alternate' is part of you business logic.
Hi I have a simple problem.
My domain class is like this:
class Example {
long seq
hasMany = [example_array: ExampleData]
long count
}
class ExampleData {
String type
long description
static belongsTo = Example
static constraints = {
}
}
This results in 3 tables, like a many to many relation.
Why is this?
Thanks
The reason for the extra table is that you've modeled the relation only in one direction - an Example can access its ExampleData instances via the example_array Set that's added to your class bytecode because of the hasMany property, but an ExampleData instance has no way to reference its owning Example.
You added a belongsTo property, but only specified the class name. That's sufficient to configure ownership, cascaded deletes, etc. but doesn't provide a property in the class to access the Example instance.
If you change it to the other supported syntax it will work as you expected:
static belongsTo = [example: Example]
Here example will end up being the name of an Example property (and you can change it and/or example_array to any valid property name), which is basically the same as declaring
Example example
Now that both sides can access the other, the relationship is bidirectional and you no longer need the third table. That's because a 1-many is typically implemented using a foreign key in the child table, in this case in the table for ExampleData that points to the table for Example. That wasn't possible without a property in the class to wire up to that column, so the join table was necessary.
I believe that you have to map the BelongsTo, like this:
static belongsTo = [example:Example]
Hope it helps :)
From the definition of hasMany Grails will, by default, map this kind of relationship with a join table.That join table is the 3rd table you mentioned.No need to worry about that.
Well the one-to-many relationship is constructed by having additional table (i.e. Example_ExampleData) containing two columns each id fields from tables of the entities forming the relationship(i.e. Example and ExampleData).
The newly added table is child to parent tables – Example and ExampleData.
So in your case when you run your application the 3rd table gets created by Grails by default as your table relationship falls under the one-to-many relationship.
In a Grails relationship when an Owner domain class owns an Owned domain class, I've seen this declared two different ways in the Owned domain class:
static belongsTo [ owner : Owner ]
and sometimes as
static belongsTo [ Owner ]
what is the difference between these two other than the syntax?
The difference is being able to indicate the name of the owned by property. In the second case it's going to assume the bean name convention of the class owner where as the first you are being explicit about the name of the property.
It's about flexibility. The first option is there if the second doesn't do what you intend or want.
The first is bidirectional, since you have an instance of Owner defined in your class. The key of that map is typically the lowercase name of the domain class, but it can be any legal variable name. An AST transformation adds a property to your domain class (you can see this by decompiling the .class file), basically
Owner owner
or
Owner theOwner
if you had declared the belongsTo as
static belongsTo = [theOwner: Owner]
Don't add this yourself though - it's already there in the bytecode.
This is similar to declaring a hasMany, where the key of that map defines a collection (by default a Set but optionally a List). E.g. declaring
static hasMany = [owned: Owned]
creates the equivalent of
Set<Owned> owned
in the bytecode.
The second isn't bidirectional since there's no direct way to get to the owning instance.
Directionality has an impact on the table structure. In the first, you get what you probably expect - an owner_id column in the Owned domain class table which is a foreign key to the Owner domain class table. But in the second, there isn't a domain class property to associate with a foreign key, so in that case a third table is created to be the join table, similar to what happens for a many-to-many relationship.
I find that the schema-export script is very helpful for stuff like this. For each variant of the syntax, run
grails compile
grails schema-export
and view the contents of target/ddl.sql to see the resulting table structure for your domain classes.
it's as simple as that:
if you define the
static belongsTo = [ owner : Owner ]
then you can can access the owner as a variable: obj.owner. If you write:
static belongsTo = [ Owner ]
then you can't (you will get NoSuchPropException I guess).
In both cases the foreign-key relation is created
Single Table Inheritance using ActiveRecord. Since we can use #test = Employee.all and find all the employees created. How does rails do this? Since we only use a User Table. How does it know about employees and retrieve only employees? Rails Magic? Explanation anyone? Thank you in advance.
Base Class : Person (inherits ActiveRecord)
Sub-Class: Employee, Supervisor, Manager (each inherit Person)
So my Person table needs to have a _type and _id field to make the table polymorphic.
My next question is how do I get Employee Associated to the Person table and when you save an employee, how do you get it to actually put in Employee in the person_type field?
To indicate to Ruby on Rails that the
users table needs to support Single
Table Inheritance you need to add a
column named ‘type’ to the users
table. Here is my users table
definition:
CREATE TABLE users ( id INT NOT
NULL AUTO_INCREMENT, user
VARCHAR(15) NOT NULL UNIQUE, pass
VARCHAR(40) NOT NULL, type
VARCHAR(20) NOT NULL, PRIMARY KEY (id) );
In the column named type you
should store the name of the class,
the class type, that should be used
for each user. To mark an certain user
as an admin set his type to
‘Administrator’. By setting a user’s
type to ‘Administrator’ you are giving
him full administrator privileges as
defined in your Administrator model
class.
http://juixe.com/techknow/index.php/2006/06/03/rails-single-table-inheritance/
Single table inheritance uses a type column on the table to indicate the type of the object. ActiveRecord knows that your Employee class is using single table inheritance (it has no matching table and the users/people table has a type column).
So when you ask for Employee.all it knows to looks for all entries in the users/people table where type == 'Employee'.
If you look at the logs the SQL will be displayed for these queries and you'll see the 'magic' happening.
I have these two domains Car and Driver which have many-to-many relationship. This association is defined in table tblCarsDrivers which has, not surprisingly, primary keys of both the tables BUT additionally also has another boolean field deleted. Herein lies the problem. When I find/get query on domain Car, I am fetched all related drivers irrespective of their deleted status in tblCarsDrivers, which is expected.
I need to put a clause/constraint to
exclude the deleted associations from the
list of fetched records.
PS: I tried using an association domain CarDriver in joinTable name but that seems not to work. Apparently it expects only table names, not maps.
PPS: I know its unnatural to have any other fields besides the mapping keys in mapping table but this is how I got it and it cant be changed.
Car domain is defined as such -
class Car {
Integer id
String name
static hasMany = [drivers:Driver]
static mapping = {
table 'tblCars'
version false
drivers joinTable:[name: 'tblCarsDrivers',column:'driverid',key:'carid']
}
}
Thanks!
I know its unnatural to have any other
fields besides the mapping keys in
mapping table but this is how I got it
and it cant be changed.
This is not at all unusual. If you want to store properties about the relationship, this is the obvious solution. You should reinstate your association domain CarDriver which has a deleted property in addition to a relationship to Car and Driver, and you should then be able to write a query which excludes the deleted drivers.
A comprehensive example of how to define such a mapping is provided here.