I have a contact entity that has >1 phone number contact[contact, name, cell,work,home...] and want to create a lookup table phone_number[uid,contactuid,telephonenumber] so that I can search through this table by telephone number to find the contact.
With JPA - how would I configure to;
Map the phone_number entity so that the entity will populated from the contact entity
remove the phone_number record when the contacts number remove (or the contact is removed, remove all records)
change phone_number record when the contacts number changes?
I was hoping to do all this in the DAO as this isn't really domain logic..
**Update - is the contact->phone_number relationship sensible to define in JPA or just map it using SQL in the DAO?
Many Thanks in advance
If I understand correctly, you already have a Contact entity with several phone number fields:
cellPhone
workPhone
homePhone
And you would like to find a contact given a phone number. If so, you don't need any additional table to do that:
select c from Contact c
where c.cellPhone = :phoneNumber
or c.workPhone = :phoneNumber
or c.homePhone = :phoneNumber
But maybe you should have a Phone entity with a phoneNumber and a type (work, cell, etc.) fields, and have a bidirectional OneToMany association between Contact and Phone. Your query would then be
select c from Phone p
inner join p.contact c
where p.phoneNumber = :phoneNumber
which would certainly be more efficient.
Related
I am currently working with tables with multiple many-to-one relationships and I'm trying to implement all of them using Hibernate.
For example, three tables I have are:
Product(id, pname), Users(id, pid, gid, uname), Group(id, gname)
Group is in an one-to-many relationship with Users
Product is also in an one-to-many relationship with Users
Users is in a many-to-one relationship with both Product and Group.
A sample of data I would receive is below:
Line 0: pname uname gname
Line 1: Razer Billy admin
Line 2: Razer Sally admin
Line 3: Razer Benji admin
Line 4: Yahoo Molly admin
...
My correct flawed loop for the data goes like this:
// Three lists of same size created,
// each list is a column of the sample data from above
// ...
for(int i = 0; i < plist.size; i++){
Product ptemp = new Product(plist.get(i));
Group gtemp = new Group(glist.get(i));
Users utemp = new Users(ptemp, gtemp, ulist.get(i));
Set<Users> users = new HashSet<Users>();
users.add(utemp);
ptemp.setUsers(users);
gtemp.setUsers(users);
session.save(ptemp);
session.save(gtemp);
}
Playing around with hibernate, I have also noticed that when I change my for loop to
for(int i = 0; i < plist.size; i++){
Product ptemp = new Product(plist.get(i));
Group gtemp = new Group(glist.get(i));
Users utemp = new Users(ptemp, gtemp, ulist.get(i));
session.save(ptemp);
session.save(gtemp);
session.save(utemp);
}
The results on the database are the same as before.
Is the second way a better way in hibernate? Or is the practice of storing a dependent entity directly to database something unacceptable in hibernate?
Thanks a lot for your help!
If I understand correctly what you are asking is in what order should the related objects be persisted when it comes to parent/child relationship in Hibernate?
What you have is a Group object that has a collection of User objects in a bidirectional relationship and a Product object that is related to a collection of User objects also bidirectionally. How to manage these types of relationships is documented below:
http://docs.jboss.org/hibernate/orm/4.3/manual/en-US/html_single/#example-parentchild
Hibernate recommends to manage the state of the relationship meaning the link from child to parent object from the state of the child object.
The first and second approach may work but they may result in different number of sql statements issued to insert the individual objects. It all depends on how you map the relationships.
I have 4 tables:
Teacher, Student, Course and their common join table TeacherStudentCourse.
The first three tables all have one to many relationship with the last table.
Here is a screenshot from my DB DataBase sample
Hence, for example, I should be able to get the desire Students by providing Teacher ID and Course ID.
I had previously asked a question on join table. Previous Question
And I do get the answer.
I was trying to improve based on the previous codes
Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
List<Object> list = session.createQuery("select s from Student s join s.teacherStudentCourses tsc where tsc.teacher = :teacher and tsc.course = :course")
.setParameter("teacher", teacher)
.setParameter("course", course)
.list();
session.getTransaction().commit();
session.close();
But I do not seem to get it working after countless tries. Maybe the query just cannot create in that way? Any helps will be appreciated!
[UPDATE]
The error I get is:
org.hibernate.QueryException: could not resolve property: teacherStudentCourses of: model.Student [select s from model.Student s join s.teacherStudentCourses tsc where tsc.teacher = :teacher and tsc.course = :course]
Here tables are associated to each other with foreign key so all child table (teacher,cource,student) should have a parent type variable in their POJO.
Let this is "TeacherStudentCource tsc" in Student.class.
Now the query will be..
select s.studentId,s.name,s.gender,s.birthdate, from Student s inner join s.tsc b where b.teacherId=:tid and b.courceId=:cid;
Teacher ID=tid
Course ID =cid
I was always taught to use IDs in my code to refer to records into the database.
But let's take the case we have same roles in the table Role. Now I want to query only the records related to the role Player:
ID ROLE
1 Admin
2 Organizer
3 Player
I don't know in my code the ID of Player, but I want to retrieve all the players, so with Hibernate I wrote:
String queryString = "from User u where u.role.role = ?";
Query queryObject = getSession().createQuery(queryString);
queryObject.setParameter(0, "player");
return queryObject.list();
As you can see I wrote "player" in the code. I think this is not the best way and I should use an ID instead. But I don't know the ID and it may change depending on the server on which I run the application. A second problem with my solution is that "player" can be capitalized into the database and this may be changed over time.
So, what should be the solution to all these problems? Is there any way to use the ID instead? Or any other way to improve this code?
In this case it seems that role should be an enum and your query would look something like:
queryObject.setParameter(0, Role.PLAYER);
Also, you might take a look at the criteria API which will help you create more type-safe queries that are more robust vs. refactoring.
You should create a enum class like this.
public enum Role {
Admin(1),
Organizer(2),
Player(3);
}
And change your code to
String queryString = "from User u where u.id= ?";
Query queryObject = getSession().createQuery(queryString);
queryObject .setParameter(0, Role.PLAYER);
return queryObject.list();
You can do using create a mapping table like ,
UserRoleMapping
ID - Incremental,
UserId - Refers to user table,
RoleId - Refers to role table
As one user can have more than one role so it will satisfy that thing too.
to Get the roles using query
select role.id from userrolemapping urm innerjoin on user u.id = urm.id where u.id = ?
using IDs or string/vachar etc. lookup is all dependent on the data that you have in the database. Some organization keep the id static and some keep the name/description static. So, make sure you have good understanding of your DB data and what will stay static . However, if the role is static you can use HQL ignore case like the example I provided for you below (I'm not adding information about the ID static path because others have already provided information about it for and don't want to duplicate it ).
--note you can take the percentages out if you only want "player"
String queryString = "from User u where lower( u.role.role ) like lower('%"+ ? +"%')";
Query queryObject = getSession().createQuery(queryString);
queryObject.setParameter(0, "player");
return queryObject.list();
I am new to hibernate so I am pretty sure that some of you would be amused by this question. It has been driving me crazy. This is a hibernate query question.
I have two tables, Assuming one is outlet and one is flyers
outlet - outlet name,outlet address, merchantName
flyers - flyerId, flyerName, merchantName
so flyers belong to a merchant and a merchant has many outlets etc,
using hibernate, to get a simple query like to get the different outlets from the outlet table using the merchantName, I use the code:
public List<Outlet> getDealOutlet(#PathParam("merchant") String merchant) {
some code here....
outletsList = session.createQuery("from Outlet as outlet where outlet.merchantName = :merchant").setString( "merchant", merchant ).list();
some code here
}
And that works.
My question is how do I return the lists of outlets for a particular flyerId.
Any help is appreciated thanks
Is the question "How can I return the list of outlets for the merchant associated with a particular flyerId?"
If so, do you have a table merchants that's mapped to a class Merchant? That's the path to go down; Hibernate can easily let you query across joins, but if Hibernate doesn't know about the join because all you've got is a magic String called merchantName that you know happens to be the same in the two tables, then Hibernate can't help you out.
(Though of course you could run two queries, but I doubt that's what you're looking for.)
It depends on your mappings, if there is an Merchant entity, and both other entities have an association to it, it can be written as:
select o
from Outlet o
join o.merchant m
join m.flyers f
where f.id = :flyersId
Other wise you can do something like you do in SQL:
select o
from Outlet o, Flyers f
where o.merchant = f.merchant and f.id = :flyersId
I am new to the Hibernate and HQL. I want to write an update query in HQL, whose SQL equivalent is as follows:
update patient set
`last_name` = "new_last",
`first_name` = "new_first"
where id = (select doctor_id from doctor
where clinic_id = 22 and city = 'abc_city');
doctor_id is PK for doctor and is FK and PK in patient. There is one-to-one mapping.
The corresponding Java classes are Patient (with fields lastName, firstName, doctorId) and Doctor (with fields doctorId).
Can anyone please tell what will be the HQL equivalent of the above SQL query?
Thanks a lot.
String update = "update Patient p set p.last_name = :new_last, p.first_name = :new_first where p.id = some (select doctor.id from Doctor doctor where doctor.clinic_id = 22 and city = 'abc_city')";
You can work out how to phrase hql queries if you check the specification. You can find a section about subqueries there.
I don't think you need HQL (I know, you ask that explicitly, but since you say you're new to Hibernate, let me offer a Hibernate-style alternative). I am not a favor of HQL, because you are still dealing with strings, which can become hard to maintain, just like SQL, and you loose type safety.
Instead, use Hibernate criteria queries and methods to query your data. Depending on your class mapping, you could do something like this:
List patients = session.CreateCriteria(typeof(Patient.class))
.createAlias("doctor", "dr")
.add(Restrictions.Eq("dr.clinic_id", 22))
.add(Restrictions.Eq("dr.city", "abc_city"))
.list();
// go through the patients and set the properties something like this:
for(Patient p : patients)
{
p.lastName = "new lastname";
p.firstName = "new firstname";
}
Some people argue that using CreateCriteria is difficult. It takes a little getting used to, true, but it has the advantage of type safety and complexities can easily be hidden behind generic classes. Google for "Hibernate java GetByProperty" and you see what I mean.
update Patient set last_name = :new_last , first_name = :new_first where patient.id = some(select doctor_id from Doctor as doctor where clinic_id = 22 and city = abc_city)
There is a significant difference between executing update with select and actually fetching the records to the client, updating them and posting them back:
UPDATE x SET a=:a WHERE b in (SELECT ...)
works in the database, no data is transferred to the client.
list=CreateCriteria().add(Restriction).list();
brings all the records to be updated to the client, updates them, then posts them back to the database, probably with one UPDATE per record.
Using UPDATE is much, much faster than using criteria (think thousands of times).
Since the question title can be interpreted generally as "How to use nested selects in hibernate", and the HQL syntax restricts nested selects only to be in the select- and the where-clause, I would like to add here the possibility to use native SQL as well. In Oracle - for instance - you may also use a nested select in the from-clause.
Following query with two nested inner selects cannot be expressed by HQL:
select ext, count(ext)
from (
select substr(s, nullif( instr(s,'.', -1) +1, 1) ) as ext
from (
select b.FILE_NAME as s from ATTACHMENT_B b
union select att.FILE_NAME as s from ATTACHEMENT_FOR_MAIL att
)
)
GROUP BY ext
order by ext;
(which counts, BTW, the occurences of each distinct file name extension in two different tables).
You can use such an sql string as native sql like this:
#Autowired
private SessionFactory sessionFactory;
String sql = ...
SQLQuery qry = sessionFactory.getCurrentSession().createSQLQuery(sql);
// provide an appropriate ResultTransformer
return qry.list();