I am trying to use code first with an existing db. So far it went well, but now I am failing at a one to many to one relationship.
There is a table customer and a table address in the db where address does NOT have any customerid but a foreign one to many key FK_Address_Customer.
The auto created classes from the edmx look like
Customer:
public int CustomerID (PK)
public Address Address
Address:
public int AddressID (PK)
public HashSet<Customer> Customers
Whatever I do in the fluent API either fails with invalid column Address_AddressID or Multiplicity conflicts with the referential constraint error.
I assumed:
//Customer has one address, address can have multiple customers<br/>
pModelBuilder.Entity<Customer>().HasRequired(m => m.Address).WithMany(x => x.Customers);
//Address has multiple customers, customer has one address<br/>
pModelBuilder.Entity<Address>().HasMany(m => m.Customers).WithRequired();
I got this correct on other tables where there where NO foreign keys in the db by using HasForeignKey, but in the above scenario it does not work. I also tried via MapKey passing the foreign key name also with no luck.
Ho do I get this simple relationship going ?
Thanks
You must tell EF the name of FK in Customer table otherwise it will use default Address_AddressID. HasForeignKey will do the magic.
pModelBuilder.Entity<Customer>()
.HasRequired(c => c.Address)
.WithMany(a => a.Customers)
.HasForeignKey(c => c.AddressID);
Where AddressID is FK property in your Customer entity. If you don't have FK property in the Customer entity you need to use Map:
pModelBuilder.Entity<Customer>()
.HasRequired(c => c.Address)
.WithMany(a => a.Customers)
.Map(m => m.MapKey("AddressID"));
Where AddressID is a name of FK column in Customer table. You always need that column to have one-to-many relation.
The difference between having and not having FK property in your entity make difference between two types of associations supported by EF.
Related
I'm using Laravel and Mysql.
I'm trying to come up with a name for my pivot table where one column is a foreign key to the products table and the other column is a foreign key to the users table. I want the table name to be product_point_of_contact. I don't want to call the table product_user as that doesn't really explain what the table does. My columns would be product_id and user_id. I don't want to name the user_id column point_of_contact_id because I don't have a point_of_contacts table.
What is the convention and best option for this? Would you also create a PointOfContact model and extend it to use the User model?
The Laravel convention is:
To determine the table name of the relationship's intermediate table, Eloquent will join the two related model names in alphabetical order. However, you are free to override this convention. You may do so by passing a second argument to the belongsToMany method:
return $this->belongsToMany(Role::class, 'role_user');
In addition to customizing the name of the intermediate table, you may also customize the column names of the keys on the table by passing additional arguments to the belongsToMany method. The third argument is the foreign key name of the model on which you are defining the relationship, while the fourth argument is the foreign key name of the model that you are joining to:
return $this->belongsToMany(Role::class, 'role_user', 'user_id', 'role_id');
So, if your models are Product and User, and you name the intermediate table as product_point_of_contact, and the fk product_id and user_id.
In your User model use:
return $this->belongsToMany(Product::class, 'product_point_of_contact');
In your Product model use:
return $this->belongsToMany(User::class, 'product_point_of_contact');
And you will not need to specify the foreign keys, since these do comply with the convention.
Said that...
What is the convention and best option for this?
IMO, the one you (and your team) can understand, and makes sense in the business logic of your application. Even if you/they read the code or the name of the tables within 6 months.
Would you also create a PointOfContact model and extend it to use the User model?
Not needed, you can use the User model. What I would do here would be to name the relationship with the meaning I want to give. For example:
class Product extends Model
{
/**
* The product point of contact (which is an user).
*/
public function pointOfContact()
{
return $this->belongsToMany(User::class, 'product_point_of_contact');
}
}
product_user will be the best since laravel itself will create the table name in alphabetical order, i advice you use product_user.
I have a two tables which are USER entity have
#OneToMany
#JoinTable(name="user_roles")
private List<Role> roles;
Role Entity have User
#ManyToOne
private User user;
Desc of table user_role is
Name Null
USER_RECORD_ID NOT NULL NUMBER(19)
ROLE_RECORD_ID NOT NULL NUMBER(19)
NOTE: A user can have multiple roles,and i have already created roles through script,have Id:10001,10002,10003 etc
In user_role role table i am inserting one user 800001 with all the roles so the table looks like
USER_RECORD_ID ROLE_RECORD_ID
800001 10001
800001 10002
800001 10003
800002 10001 ///This record will through me unique constraint error
So if i try to give a role to new user where role is predefined it throughs me this error
INSERT INTO USER_ROLE(USER_RECORD_ID,ROLE_RECORD_ID) VALUES(800002,10001)
Error report -
SQL Error: ORA-00001: unique constraint (SYSTEM.UK_LPLHY51JOJA1LP4465QK2E0AF) violated
00001. 00000 - "unique constraint (%s.%s) violated"
*Cause: An UPDATE or INSERT statement attempted to insert a duplicate key.
For Trusted Oracle configured in DBMS MAC mode, you may see
this message if a duplicate entry exists at a different level.
*Action: Either remove the unique restriction or do not insert the key.
I think the error is caused by the use of #ManyToOne/#OneToMany while the relation you have is #ManyToMany. This is so because in the example you give the USER_RECORD_ID with the value 800001 has multiple ROLE_RECORD_ID and the ROLE_RECORD_ID with the value 10001has multiple USER_RECORD_ID.
Therefore try using #ManyToManyinstead, this should fix your problem.
Here is a reference in case you need it: https://en.wikibooks.org/wiki/Java_Persistence/ManyToMany
You have setup your mappings incorrectly, as it seems you have intended to have a bidirectional relationship that uses a relation table but instead have setup two independent relationships. The first, User.roles uses the relation table, but the otherside
#ManyToOne
private User user;
is telling JPA to setup a Role-User relation that uses a foreign key in the Role table. This doesn't seem to be the source of your problem, but will cause you other issues and doesn't match what you are asking for- Your role can only reference a single User, yet you are asking for roles to be assigned multiple users. Try:
#ManyTooMany
#JoinTable(name="user_roles")
private List<Role> roles;
.. and in the Role entity:
#ManyTooMany(mappedby"roles")
private List<User> users;
Also make sure you drop the database schema and let JPA recreate the database using these new mappings.
I'm using hibernate for my project and what i'm essentially trying to do is figure out how to auto-map the values with foreign keys from my table in the database to a data object.
For example, I have a users table with the following columns
id - INT
username - VARCHAR
password - VARCHAR
email - VARCHAR
firstName - VARCHAR
lastName - VARCHAR
This is fairly straightforward to map as there are no foreign keys involved. The code I have is:
SQLQuery q = session.createSQLQuery("SELECT * FROM users WHERE username=? AND password=?");
q.setString(0, username);
q.setString(1, password);
q.addEntity(User.class);
List<User> users = q.list()
Now supposing I add some foreign keys to my user table such as
userlevel_id - INT
department_id - INT
Which reference the user level a user belongs to and the department. How do I get hibernate to map the user level name from the userlevel table and the department name from the department table? It wont be of much use if I just store the id's in the User data object as I will need to display the values to my views later on. Any help will be greatly appreciated, Thanks!!
Use an eagerly loaded #ManyToOne mapping on your User object. Make an object to represent both your Departmentand your UserLevel and add them as fields into your User object. The reason that you should have this mapping as eagerly loaded is that there is never a situation where you don't want to load a User without their Department or UserLevel. Hibernate will automatically map your User object to the appropriate Department and UserLevel.
If you want too, you can make the relationship bi-directional so you can get all users in a department by selecting a department. Anything you can do in SQL you can map using Hibernate.
Have a read of the documentation and see if that helps.
I want a basic syntax of relation and their parameters
i need these clarification
Difference Between BELONGS_TO and HAS_ONE ?
I want to use the relation on CGridView (That relation refers the another table element as a Foreign key )
For Eg
I have Three tables
Messenger
UserLogin
Userprofile
I am in Messenger Admin Grid
I have Primary key of UserLogin table
That userlogin have userprofile Primary key
Now i want to access the userProfile fields in my grid
i already try the (through) in relation like
its in Messenger model
'relationeg'=>array(self::HAS_ONE,'Userprofile',array('user_id'=>'id'),'through'=>'user'),
'user'=>array(self::BELONGS_TO, 'UserLogin','user_id'),
i access this on my grid
.....
....
array(
'name'=>'message_by',
'value'=>'$data->relationeg->username'
),
....
...
But i got the wrong data's that are totally differ by the key of base table record
i have doubt on this line
'relationeg'=>array(self::HAS_ONE,'Userprofile',array('user_id'=>'id'),'through'=>'user'),
in this self::HAS_ONE means?
when i add the where condition of the join query how will add the condition on this
Advance thanks
Your answer welcome
KEY POINT : A BELONGS_TO relation says that a field in this model points to the primary key in another model; in this case, the current model owns the linking field.
KEY POINT : A HAS_ONE relation says that some other model has a linking field pointing to this model's primary key; in this case, the related model owns the linking field.
We can thik that a PARENT table will be the one that doesn't have a foreign key, and a CHILD table as the one who "depends" on the parent table, that is, it has a foreign key.
Given that, a CHILD BELONGS_TO a PARENT and a PARENT HAS_ONE CHILD.
The answer is here
I have the below tables.
create table logical_id_seq (
logical_id int auto_increment,
primary key(logical_id)
);
create table mytable (
physical_id int auto_increment,
logical_id int not null references parent(logical_id),
data varchar(20),
primary key(physical_id)
);
The second table uses first table auto-generated value as its value. I am not sure how to model this in hibernate.
I read http://docs.jboss.org/hibernate/core/3.3/reference/en/html/mapping.html#mapping-declaration-onetoone, but I doesn't seem to understand.
It's actually hard to say, I don't know what you want to represent at the object level: is it a one-to-one foreign key association? a many-to-one association? is the association bi-directional? Using an ORM means thinking objects more than tables and it usually help to provide the object model.
I'll assume this is a one-to-one foreign key association. Here is what Java Persistence with Hibernate recommends:
7.1.2 One-to-one foreign key associations
Instead of sharing a primary key, two
rows can have a foreign key
relationship. One table has a foreign
key column that references the primary
key of the associated table. (The
source and target of this foreign key
constraint can even be the same table:
This is called a self-referencing
relationship.)
Let’s change the mapping from a User
to an Address. Instead of the shared
primary key, you now add a
SHIPPING_ADDRESS_ID column in the
USERS table:
<class name="User" table="USERS">
<many-to-one name="shippingAddress"
class="Address"
column="SHIPPING_ADDRESS_ID"
cascade="save-update"
unique="true"/>
</class>
The mapping element in XML for this
association is <many-to-one> — not
<one-to-one>, as you might have
expected. The reason is simple: You
don’t care what’s on the target side
of the association, so you can treat
it like a to-one association without
the many part. All you want is to
express “This entity has a property
that is a reference to an instance of
another entity” and use a foreign key
field to represent that relationship.
The database schema for this mapping
is shown in figure 7.3.
Figure 7.3 A one-to-one foreign
key association between USERS and
ADDRESS
An additional constraint enforces this
relationship as a real one to one. By
making the SHIPPING_ADDRESS_ID
column unique, you declare that a
particular address can be referenced
by at most one user, as a shipping
address. This isn’t as strong as the
guarantee from a shared primary key
association, which allows a particular
address to be referenced by at most
one user, period. With several foreign
key columns (let’s say you also have
unique HOME_ADDRESS_ID and
BILLING_ADDRESS_ID), you can
reference the same address target row
several times. But in any case, two
users can’t share the same address for
the same purpose.
Let’s make the association from User
to Address bidirectional.
Inverse property reference
The last foreign key association was
mapped from User to Address with
<many-to-one> and a unique
constraint to guarantee the desired
multiplicity. What mapping element can
you add on the Address side to make
this association bidirectional, so
that access from Address to User is
possible in the Java domain model?
In XML, you create a <one-to-one>
mapping with a property reference
attribute:
<one-to-one name="user"
class="User"
property-ref="shippingAddress"/>
You tell Hibernate that the user
property of the Address class is the
inverse of a property on the other
side of the association. You can now
call anAddress.getUser() to access
the user who’s shipping address you’ve
given. There is no additional column
or foreign key constraint; Hibernate
manages this pointer for you.
If what you have is actually a real many-to-one association, it should be pretty easy to adapt the above solution.