I have an Employee entity class with (Id,Name,EmployeeType). EmployeeType entity (Id, Description) where Description can be either REGULAR/MANAGER.
I am confused on how to map Employees who are of type REGULAR to their corresponding MANAGER type Employees. Should I just add an extra field to the Employee entity itself so that it now becomes (Id, Name, EmployeeType, ManagerEmployeeId)? Or should I instead have a lookup table Employee_Manager (Id, RegularEmployeeId, ManagerEmployeeId)?
I am considering going with the Employee_Manager lookup table and am not sure how that entity class would look like. The following below is what comes to my mind. Am I on the right track here?
#Entity
#Table(name="EMPLOYEE")
public class Employee{
#Id
int id;
#Column(name="NAME")
String name;
#ManyToMany(mappedBy = "regularEmployee")
Collection<Employee> regularEmployee
#ManyToMany
Collection<Employee> managerEmployee;
}
ps. I am using JPA with Hibernate as the persistence provider.
If you're trying to have an employee have exactly one manager, then first of all you're doing a many-to-one relation (not many-to-many) and having the ManagerEmployeeID in the table as a foreign key reference to the same table is just fine.
Use a lookup table if you want to allow an employee to potentially have more than one managerial-type role. You can also use this if you want to assign a particular "role" to these manager-type people:
create table Supervisors (
eid int,
sid int,
role varchar(16)
);
Then you could use role for "Supervisor" vs "Manager" vs "Slavedriver" vs who knows what.
Sorry, I don't know any JPA/Hibernate, so the concepts (and pseudo-SQL) is the best I can give you.
Hope that helps a bit.
Related
I'm building my entities, I want to know 2 things please :
1) I have for example a class named "Order" and a class named "Order_Details" , I want to make them OneToOne on both side , how can I make it?? (Same thing with Order and Order_Validation).
2) I created a class "User" and Inherited many classes ("Client"/"Manager"/"Accountant" ...) "Manager" is related to other classes ("Order" for example ) so my question is in the "Order" table should I put a relation with "User" or "Manager"?? (I don't have an ID in )
Thank you
About #2...
It depends. Are you planning on having different tables for them? If this is the case, then you should put the relationship in Manager.
1) For your first question
Order Table
#OneToOne(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "order")
private OrderDetail orderDetail;
Order_details Table. ( It will have a order_id column in it)
#OneToOne(optional = false)
#JoinColumn(name = "ORDER_ID")
private Order order;
2) Depending on what you want to do.
I would recommend going with USER table and USER_TYPE table. If a user will always belong to only on user type, then have a USER_TYPE_D key in USER table. If not have a one-to-many table like USER_TYPE_MAP table. Regarding the actions a user type can take, have a ROLES reference table and a separate table called USER_TYPE_ROLES which maps what role a user can play. So in JPA, you can User, UserType, Roles, UserTypeRoles etc and do a one-to-one or one-to-many mapping accordingly.
I have a new table in my DB which simply aggregates some data which I don't want to hold as a reference in any of my entities. Because of above I don't have an entity of that type in my application. Now the problems starts when I want to create simple query from that table. We use named queries and criteria api in our application as a standard. Since my query is simple and is going to be asked a lot of times the perfect solution would be to use JPQL and named query. But how might I achieve this without having an entity related to this table... As far as I remember there is COLUMN('xxx') expression which can be used to obtain column which isn't used in entity, so maybe there is something similar to do the trick with whole table?
So let me recap, because It's possible that You may have a problem to understand me well :)
#Entity
public class Person {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
}
#Entity
public class Pet {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
}
Let's say that besides above two tables I have third one which I don't want to use neither in Pet nor in Person. So:
CREATE TABLE ANY_OTHER_TABLE(
PERSON_ID BIGINT NOT NULL,
PET_ID BIGINT NOT NULL
);
So now question is how should JPQL look like to produce SQL like this:
SELECT * FROM ANY_OTHER_TABLE WHERE PET_ID = 1;
I'm having a hard time finding the exact answer to this question, so my apologies if this is redundant.
So I have 3 tables defined such that:
Person :PersonId, FirstName, LastName
Company: CompanyId, CompanyName
Order: OrderId, PersonId, CompanyId
On the Order table, there is a foreign key defined on the PersonId and CompanyId columns, thus, my Order entity class generated by EF has a navigation properties of type Person (not PersonId) and Company.
So, to insert into the Order table, I first need to query the person and company tables to get the person and company entities. Then I can construct the Order object using the Person and Company entities and save it to the db.
In my scenario, I am being passed a PersonId and CompanyId.
In classic SQL I would just do INSERT INTO Order Set (CompanyId, PersonId) - 1 database call. But with EF, I have to do 3 db calls. This seems like overkill.
Is there any way around this?
PS - I'm using EF 6. I know I could generate an expression and make it single call..but that would still yield two subselects.
You can just include foreign key properties in addition to the navigation properties and then set them using the ids you have. If you do this will not have to go to the database to get related entities for just a sake of setting the relationship.
The JPA specification gives the following explanation of the annotation #GeneratedValue(strategy=TABLE):
The TABLE generator type value indicates that the persistence provider must assign primary keys for the entity using an underlying database table to ensure uniqueness.
But what does "using an underlying database table" mean in practice? Does it mean using an auxiliary table? Or by scanning the entity-table to find an ID not in use? Or something else?
Check out JavaDoc for TableGenerator, it has a nice example of how it works:
Example 1:
#Entity public class Employee {
...
#TableGenerator(
name="empGen",
table="ID_GEN",
pkColumnName="GEN_KEY",
valueColumnName="GEN_VALUE",
pkColumnValue="EMP_ID",
allocationSize=1)
#Id
#GeneratedValue(strategy=TABLE, generator="empGen")
int id;
...
}
Example 2:
#Entity public class Address {
...
#TableGenerator(
name="addressGen",
table="ID_GEN",
pkColumnName="GEN_KEY",
valueColumnName="GEN_VALUE",
pkColumnValue="ADDR_ID")
#Id
#GeneratedValue(strategy=TABLE, generator="addressGen")
int id;
...
}
Basically ID_GEN is an internal (non-business) table of key-value pairs. Every time JPA wants to generate ID it queries that database:
SELECT GEN_VALUE
FROM ID_GEN
WHERE GEN_KEY = ...
and incremenets the GEN_VALUE column. This mechanism can be used to emulate sequences or to take even further control of generated ids.
In the case of EclipseLink, it uses an auxiliary table. The documentation says
By default, EclipseLink chooses the TABLE strategy using a table named SEQUENCE, with SEQ_NAME and SEQ_COUNT columns
I have to create an entity framework model for a badly designed database. The database uses table per type inheritance but it does so with using a PK->FK relationship, not a PK->PK relationship. E.g.
Person
PersonID (PK)
Name
Employee
EmployeeID (PK)
PersonID (FK)
DateStarted
HourlyEmployee
HourlyEmployeeID (PK)
EmployeeID (FK)
HourlyRate
Obviously this is just badly designed, but I can't change it. Table per type inheritance in the entity framework essentially wants EmployeeID not to exist and the PK for Employee to be PersonID. Is it possible to create a model for this database, or do I choose another tool? any recommendations?
You will not map this as TPT inheritance because your database is configured in the way that doesn't allow you cheating EF.
If Employee.EmployeeID is auto-generated in the database and Employee.PersonID is unique (uniqueness must be enforced in the database) you should be able (not tested) to cheat EF by simply mapping:
public Employee : Person {
public DateTime DateStarted { get; set; }
}
This class will tell EF that Employee inherits key from Person (PersonID) and you will hide the real key from EF - this should work if the real key is auto-generated.
The problem is your next level of inheritance which breaks this pattern. To make this work your HourlyEmployee will have to reference PersonID - not EmployeeID. EF now doesn't know about EmployeeID existence so it even cannot map relation with HourlyEmployee.
TPT inheritance in code first has one additional limitation - PK column must have the same name in all tables.
You can create a model from the database if it exists but it might not be what you expect. EF sometimes doesn't work that great with weird database structures.