Hibernate one-to-one and one-to-many - java

I currently have a one-to-many relation between 2 table: I have:
Table A (id, ...)
Table B (tableAId, ...) (has no id of it's own).
In the mapping this is done using <list>.
The issue I am having, is that I have to add another one to one relationship from A to B. Something like this:
class A {
public B b; // new part
public List<B> bs; // already existing part.
}
I have a boolean column in the table by which I should differentiate between the one-to-one and one-to-many. I'm not sure how to write the hibernate mapping for these tables. Could any of you help me out with this?

I think you can do this by using 'mappedBy', have you tried that?
http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html_single/#entity-mapping-association

Related

In which direction Hibernate orm-mapping works

I have a rather simple (probably) question, but somehow struggling to find an answer.
How does hibernate map nested entities to java objects? Does it starts its mapping from high-level entities and stops on encountering null-values in ResultSet, or it starts from the lowest-level entities and check all of the hierarchy?
The first path seems to be more natural, but yet I didn't find a concrete answer or any way to configure this
EDIT
By nested entities I suppose something like this:
#Entity
public class A {
public Long id;
public String foo;
}
#Entity
public class B {
public Long Id;
#OneToOne
#JoinColumn(name = "aId")
public A bar;
}
Where bar field is nested entity for B
One more edit
By ORM-mapping I meant mapping on select query call - so, if table B has no records and we execute any select-query to find entities of B, does Hibernate atempt to find and map entities of A ? Futhermore, if we have
#Entity
public class C {
public Long Id;
#OneToOne
#JoinColumn(name = "bId")
public B foobar;
}
and yet there are no records in table B, some in C and some in A, when we use any find methods for C, does Hibernate attempt to find and map entities of A?
Hibernate ORM won't create a proxy for *-to-one association that can be null (#OneToOne(optional=false)). If the element is missing in the db it will be null when the entity is created. So, using your example, C.foobar will be null if there is no row on the table B in the db. The same applies to the other *-to-one associations.
If the element is not optional, it might load it lazily and therefore assign a proxy to it.
To expand a bit about your question.
This is a one-to-one association. More in general, what you call nested is an association in Hibernate ORM. You can find all the details about these types of mapping in the Hibernate ORM documentation.
For your specific example:
#Entity
public class A {
#Id
#Column(name = "aId")
public Long id;
public String foo;
}
#Entity
public class B {
#Id
public Long id;
#OneToOne
#JoinColumn(name = "aId")
public A bar;
}
Hibernate ORM will create the following tables in Postgres:
create table A (aId int8 not null, foo varchar(255), primary key (aId))
create table B (Id int8 not null, aId int8, primary key (Id))
alter table if exists B add constraint FK3mifipyyn4ao31rn7kftqknuc foreign key (aId) references A
Basically:
Table A with columns aid and foo
Table B with columns id and aid
Table B column aid has a foreign constraint to Table A column aid
You can find all the details about one-to-one mapping in the Hibernate ORM documentation.
If you run the HQL query from B, Hibernate ORM will run the following SQL:
1. select * from B;
2. select * from A a.where a.aid = ?
if the HQL is from C
1. select * from C;
2. select * from B b left outer join A a on b.aId = a.aId where b.id=?;
In both cases, the second query only runs if there are results for the first one.
Keep in mind that this is a basic example and the type of queries executed
will change based on the configuration and the mapping of the entities.
You can actually tweak this behaviour with small changes to the mapping (Lazy/Eager fetching, optional, using bidirectional associations, ...) or the queries. I'm not going through all the possible mappings and you should write your own tests and check what SQL is logged.
Hibernate ORM might also skip some queries if some of the entities or the query has been cached.

#ManyToMany using 4 tables

How to join users and service through this two tables?
#JoinTable works perfect when you have relation through 1 table. But what to do in this case?
This is possible without creating separate entities for admins and admin_to_service?
You could try creating a view to function as the Join table. I don't know what your FK references are but something like:
create or replace view user_services_vw as
select
a.user_id,
ats.service_id
from
admins a
inner join
admin_to_services ats on ats.some_col. = a.some_col
You can then model as a simple #ManyToMany. This should work fine if the relationship is read only but you may have issues if the data needs to be updateable.
#Entity
public class User {
#ManyToMany
#JoinTable(name = "user_services_vw")
private Set<Service> services;
}

hibernate criteria. self join for denormalized table

Hello all and sorry for my English =)
I works with Hibernate using criteria API. Everything was fine, but I have several denormalized tables with data for reports, and I faced some troubles.
For one of that tables I created #Entity class for mapping like
#Entity
#Table(name= "table")
public class Report {
#Id
Integer id;
Integer product_id;
Integer warehouse_id;
String some_data;
}
with simple queries all works fine. But I need to make queries like pivot table or self join etc.
for example
select
t1.product_id,
t2.warehouse_id
from repost t1
join report t2
on t1.product_id = t2.product_id
and t1.warehoise_id = ?
where t1.some_data in (?)
Such query does not contain logical dependencies between entities like Primary_Key - Foreign_Key and can return custom object data (it can be Map<>, List<>, Pair<>, Long...)
Is it possible to make query like this without using HQL?
Thanks
ADDED
As I was understood it's not possible using HQL too

JPA: Modelling m:n relationship & join-table values

having a m:n real-world relationship between some entities, e.g. user <---> group
Now I want to model this relationship and store additional information based on it, e.g. a field "quality".
I heard that I would have to create a new join table user_group as follows:
id | user_ref | group_ref | quality
----------------------------------
1 1 1 0.5
2 1 2 1.3
... ... ... ...
The corresponding entity has two related entities (private members) user and group, annotated with the #ManyToOne-annotation.
On the other hand, both, my user and my group have a set of related user_group-entities, both private members and declared with the #OneToMany-annotation.
I have three questions:
Is this the right way to model the problem of additional fields in JPA 2.0?
I not allowed to use both user and group in user_group as primary key
since they are not valid primary key types. Is it really necessary to declare a new primary.
Is this a common workflow with these join-tables/entities?
...
EntityManager em = ...
...
em.getTransaction().begin();
User u = new User("Pete");
Group g = new Group("Anonymous workaholics")
UserGroup ug = new UserGroup();
ug.addUser(u);
ug.addGroup(g);
em.persist(u); em.persist(g); em.persist(ug);
em.getTransaction().commit();
em.close()
Thanks a lot!
Yes, it's the good way to do it.
It's possible to have a composite primary key consisting of two ManyToOne associations, but it's much more complex, both in the mapping and in the rest of the application, to handle that, and it's also less efficient. You have an entity, so just do like for all the other entities and use an auto-generated, single-column primary key. The fact that this entity used to be a join table of a many-to-many association is irrelevant.
Yes, that seems OK, except the addUser() and addGroup() methods should be named setUser() and setGroup(): there's only one user and one group for a given UserGroup. I would also use another name for the entity itself. Something like "Membership" for example.

Hibernate Annotation for Entity existing in more than 1 catalog

I have a Person entity mapped by Hibernate to a database table in a database catalog "Active". After a period of time, records in this database table in the "Active" catalog are archived/moved to an exact copy of the table in a database Catalog "History". I have the need to retrieve from both the Active and History Catalogs. Is there a better way to model this with Hibernate annotations than making an abstract class that 2 classes extend from.
This is what I have now.
#MappedSuperclass
public abstract class Person {
#Id
private Integer id;
private String name;
}
#Entity
#Table(name="Person", catalog="Active")
public class PersonActive extends Person {
}
#Entity
#Table(name="Person", catalog="History")
public class PersonHistory extends Person {
}
To my knowledge, that would be the right way to do it with annotations (you kinda have two tables so you need two entities). Then run a polymorphic query on the Person entity. I find this pretty clean by the way.
PS: Can you add a pointer on how to do this with mapping files, I'm really curious.
My thought would be to write a query to select both tables from db A and B. then create a query with hibernate and map it to your class.
example:
#Entity
#NamedNativeQuery(
name="GetAllPerson",
query="select * from A.Person inner join B.Person on A.Person.Id = B.Person.Id"
)
public class Person {
...
}
Not sure if it could work, your question made me also curious about the best way to do it :). I'll test it tonight after work and see if its any good.
I think there is a subproject of hibernate named shards. It is designed to work with multiple relational databases. If you want to use it, you may need big changes in your code.

Categories