For example I have two entities : Enterprise, Department. Enterprise has many departments, department has one enterprise, so there is a column - Enterprise_ID in Department table.
I have a function for saving Department object
void save(Department department);
To add Enterprise_ID in the table I need to have either reference on Enterprise object or enterprise's id.
Which way is more suitable?
However I prefer do not have such information in department object but on this way how can I save Enterprise_ID in the table ? It seems to me Hibernate somehow doing it.
public class Department{
private long id;
private String name;
private DepartmentType type;
private List<Employee> employees;
//getters()/setters()
}
public class Enterprise{
...
private List<Department> departments;
...
}
Department does not have any information about Enterprise in which it exists. So using only department object I can't insert Enterprise_ID(FK) in department table. But hibernate's save method somehow doing it. How can I do it without hibernate using entities above;
I use JDBC.
To do it the same way as hibernate does, you would have a save(Enterprise) method that would persist the enterprise object to the db and also insert/update the foreign key association.
Hibernate supports both nullable and non-nullable foreign key. In the latter case, it will first insert the enterprise, obtaining its primary key value, and then insert the department's along with the correct foreign key value.
You could do the same. But the save(Department) method would only be able to do updates on the department table and not change the association to the enterprise table. To do that, you would have to change the collection in enterprise and save/update that to the db.
Hibernate will only save/update the foreign key if you change something in the Enterprise.departments collection. It's the only way to do it if you don't have the reverse relation.
In your code, you'll have to use the Enterprise object to update the foreign keys in the Department table.
You could create a bidirectional association, by putting a field 'enterprise' in your Department class, but then you need to keep both relations in synch manually...
Related
Suppose we have two database tables Instructor and Instructor_Details. They have one to one relationship such that each instructor can have one instructor detail and one instructor detail is associated with one instructor only.
In pure database terms, Instructor table should be the parent of Instructor_Details table and the primary key of Instructor table should be used as foreign key in Instructor_Details table.
I was learning Hibernate and most of the examples of #OneToOne on internet have modified the tables such that the Instructor_Details primary key is used as foreign key in Instructor table, which seems contradictory as Instructor should be the parent of Instructor_Details.
How can i implement both entities in best way such that i can use the primary key of Instructor as foreign key in Instructor_Details. Also please explain the fetch types and cascade in my desired implementation. Examples with code will be very helpful.
Edit
Let us say the attributes for the tables are as follows:
Instructor(instructor_id (primary key), first_name, last_name)
Instructor_Details(detail_id (primary key), dob, address, instructor_id (foreign key from instructor table))
Since in pure database terms you're modeling this as parent/child you're stuck with OneToMany. What I've done in this situation, so I can keep the relationship like that and take advantage of things like on cascade delete, etc. Is to have helper methods on the entities themselves. Since Hibernate uses reflection you don't actually need to implement public getters and setters to your private members.
So for example your accessor for InstructorDetails Instructor class can look like:
public class Instructor {
...
#OneToMany
private List<InstructorDetails> instructorDetails;
public Optional<InstructorDetails> getInstructorDetails() {
if (instructorDetails == null || instructorDetails.size() == 0) {
return Optional.empty();
} else if (instructorDetails.size() > 1) {
// Optional raise if you want to be aware of corrupt Instructors that have many details
throw Exception("There's corrupt data");
} else {
return Optional.of(instructorDetails.get(0));
}
}
...
}
Makes sense? Same for add ... you can have an add that takes a single detail, checks if there's one already and overwrites or throws, but internally it deals with the list. Whoever deals with Instructor will never know there's a list holding them inside.
I don't have a lot of experience with database design and i try to understand the general logic behind it with using an ORM like hibernate. I have two tables user and languages. User could know one or more languages so there is a one to many relation between two tables. But i have a fixed length of languages English , Spanish and French for example. As i understand with each new user instance persisted there will be duplicate entries in the language table with a foreign key of that person. Is there a way to prevent this duplicate entries ?
Your understanding is a little confused. You can map a OneToMany relationship using a Foreign Key, and there are good database reasons to do so, though generally a JPA provider recommends against it. However, you are describing a ManyToMany relationship. A User will (or could) have many Languages. A Language will have many Users. When you create a many to many relationship with annotations:
#Entity
public class Person {
#Id #GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
#ManyToMany
private List<Language> languages;
and
#Entity
public class Language {
#Id #GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
The JPA provider will create an association or Join Table, with an id from each Entity in it:
create table Person_Language (Person_id bigint not null, languages_id bigint not null)
When you create a language, an entry will be put in the language table. When you create a user, an entry will be put into the user table. When you add a language to a person's languages then an entry will be put into the Join Table.
insert into Person_Language (Person_id, languages_id) values (?, ?)
There will be only unique combinations of Person_id and languages_id in the join table, and so the database will be well normalized. You would not be able to assign a language to multiple users using a Foreign Key in the Language entity for the reason you pointed out: there would be only one foreign key column for any given language.
I have new JPA project using hibernate and I run into a difficulty while reading its code. I saw:
#Entity
public class Product {
#ManyToOne(optional = false, fetch = FetchType.LAZY)
private Manufacturer manufacturer;
...
}
and another Entity
#Entity
public class Manufacturer{
private ManufacturerId manufacturerId;
private String name;
private Manufacturer() {
}
...
Why there is not List/Set with Product(s) in the Manufacturer Entity class? ManyToOne relationship is Bidirectional? Why is this possible? How Manufacturer knows about its products, how this will be persisted on the DB table?
The many-side of an one to many association is optional. You can implement it if intended or skip it if not needed or even risky. A manufacturer could have many thousand of products. Than it makes no sense to fetch all of them at once. It's better to load via a query and use paging. Of course you could add the collection of products to your Manufacturer if you think this helps you.
Why there is not List/Set with Product(s) in the Manufacturer Entity class?
Either because not needed or as considered risky.
ManyToOne relationship is Bidirectional?
Of course yes. Even if the relationship is not impletemented it still exists.
Why is this possible? How this will be persisted on the DB table?
A OneToMany relationship is always implemented by an id on the one side. (ManufacturerId in Products in this case. Nothing else is needed. Even if you implement the products collection. This will not impact the way it's persisted.
How Manufacturer knows about its products?
It doesn't. But of course it's possible to query the database.
If you look at it at DB level, table Product will have something like manufacturer_id which is a foreign key to Manufacturer table. The table structure remains the same in both unidirectional and bidirectional mapping case.
Manufacturer will know its product by querying table Product with manufacturer_id = <its id>. On JPA level, in case of unidirectional mapping you could query it by from Product p where p.manufacturer.id = :man_id. In case of bidirectional mapping you could just do manufacturer.getProducts(), but it would translate to the same SQL.
Hi I'm new to JPA and I'm having trouble understanding how it handles inheritance.
I have a specific problem I need solved without changing the DB scheme, but if you can't find a solution I would appreciate solution suggestions with a different DB scheme (Hibernate/TopLink solutions welcome).
If I was unclear or you need more information, please tell me so. Thanks in advance!
I have this database:
TABLE Fruit
Id Varchar (10) Primary Key
size Varchar (10)
fruit_type Varchar(10)
TABLE Apple
Id Varchar (10) Primary Key Foreign Key references Fruit.Id
Apple_Property Varchar(10)
So far my entities look like this :
#Entity
#Inheritance(strategy=InheritanceType.JOINED)
#DiscriminatorColumn(name="fruit_type", discriminatorType=DiscriminatorType.Char)
#DiscriminatorValue(value="fruit")
public class Fruit implements Serializable {
#Id
protected String Id;
protected String size;
}
#Entity
#DiscriminatorValue(value="apple")
//#PrimaryKeyJoinColumn(name="Id" , referencedColumnName="Id")
public class Apple extends Fruit implements Serializable {
private String Apple_Property;
}
Currently I am able to persist Fruit objects without a problem..
Apple objects persist only when their Fruit object hasn't been persisted yet.
If I try to persist an apple object with an already persisted Fruit object :
Fruit fruit1 = new Fruit("1", "Small");
Apple apple1 = new Apple(fruit1, "red");
provider.create(fruit1);
provider.create(apple1);
I will get an error since JPA tries to create a new row on Fruit table with Id="1"
which already exists.
..
When using JPA to persist a child object (i.e provider.create(apple1) in your case) , a record will be inserted to the child table and all of its parent tables. So provider.create(apple1) will insert a record to the Fruit and a record to the Apple table.
In your example , if you only want to persist an apple object ,just call provider.create(apple1) is enough . It will persist the fruit reference inside the apple object too.
BTW , I suggest the Fruit Table 's PK to be a number type , and uses #GeneratedValue to mark the ID field of the Fruit bean. In this way , you can let the database to generate an ID for you and no longer need to set it explicitly in the java code to avoid this "ID already exist error" because of setting an already existing ID in the java code.
I think this is working exactly as designed. When you use joined inheritance and persist an apple object, JPA will automatically insert into both the apple and fruit tables. You don't need to model an additional relation or JoinColumn in your entity classes.
You are trying to use java inheritance concept while creating the db tables, which is somewhat not possible in this case. I could think one different approach for this problem. Have table fruit_type and fruit.
fruit_type(id, typename,desc)
fruit(id, name, type_id, desc) here type_id will be the foreign key.
I have the same issue and so far the only way I found was to query the parent and construct child with parent. Then remove parent and recreate both records.
This is something I'd really like to be able to do - resolve names based on id values without fetching the whole child model.
Here is an example of what I have, a Table say Employee and a Name_Details table
The Employee may look like this
Create Table Employee {
emp_idinteger not null generated by default as identity; -- generated pk
Department varchar(44);
emp_name_id Integer; -- fk to Name_Details table
...other details such as hire_date etc..
}
now emp_id is a foreign key to the name_details table which may look like this:-
Create Table Name_Details {
id Integer;
Name varchar(32);
Address Varchar(127);
Postcode Varchar(10);
--other details..
}
My question is that I'd like to model the first table Employee with a Java class but I am not interested in setting up a one-to-one relationship between the Employee class and the Name_Details table to fetch that whole Name_details table (as its quite large) the only information I want from this second class is just the Name field (found by joining the emp_name_id column with the Name_Details.id column.
So is it possible in JPA to say declare something like a transient variable in my Employee class called say String employeeName and have this retrieved by JPA based on the above relationShip?
This is a simplified example of what I have wgere there are several tables with name-value pairs and the master table has the values. I need this for reading and not updating/deleting etc.
I am not using JPA v1.x with EJB3 (and not hibernate) on WPS 6.1
Thx G
There are a few options.
The first is to just create a Name class that maps to Name_Details but only maps the name and id fields. Employee would then have a OneToOne to Name, and only the name would be read.
A second option is define Name_Details as a #SecondaryTable in Employee and map only the name from it. The JPA spec restricts the secondary table join to have to share the same id, but depending on what JPA provider you are using, using the 1-1 foreign key may be possible (EclipseLink does support this). You could also define a view the does the join and map to the view.
A third solution is to still map all of the Name_Details fields but define them as LAZY. If your JPA provider supports LAZY basics (or fetch groups), then these will not be fetch unless accessed.