How to create Many-One Mapping in hibernate?
I want to create Many-One Mapping between two tabels, Expense(ID, NAME, CATEGORY) and Category(ID, NAME). In my class i have created a field 'Category category' and its setters and getters. I did them after seeing some stuff from internet. What are all the changes i have to do in my Category.java class. For now, its looks like,
public class Category{
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int catId;
private String catName;
public Category() {
}
public int getCatId() {
return this.catId;
}
public void setCatId(int catId) {
this.catId = catId;
}
public String getCatName() {
return this.catName;
}
public void setCatName(String catName) {
this.catName = catName;
}
}
I dont want t开发者_高级运维o do mappings with xml config. I think, annotations is good for a beginner like me.
And my Old! SQL query looks like,
SELECT EXPENSES.EXPNS_ID, EXPENSES.CAT_ID, EXPENSES.NAME, CATEGORY.CAT_NAME FROM EXPENSES INNER JOIN CATEGORY ON EXPENSES.CAT_ID = CATEGORY.CAT_ID WHERE USER_NAME="+currentUserName
How to use inner join in Hibernate?
Any Suggestions!!
Thanks!
Update
Thanks for all answerers, I tried what you told and it returns a empty list.
To, test i set the 'userName=Tamil' which is in the table. The query generated by Hibernate is looks like below,
select expens0_.expnsId as expnsId1_, expens0_.catId as catId1_, expens0_.category_catId as category7_1_, expens0_.userName as userName1_ from Expens expens0_ inner join Category category1_ on expens0_.category_catId=category1_.catId where expens0_.userName=?
As a beginner, i have some doubts in JPQL, I want catName
from Category[catId, catName]
table. And the catId
is also available in Expens[expnsId, catId, userName]
.
By adding the below lines in Expens.java class, how it will give me catName
along with the other variables in the Expens
table.
@ManyToOne
private Category category
// getters, setters
I cant able to understand it. Without understanding this i cant move further, i have to give more mappings in my project. If clear with this mapping, i can move to the rest with confidence.
The query i used is pascal's version: Query query = hSession.createQuery("SELECT e FROM Expens e JOIN e.category c WHERE e.userName = :userName").setParameter("userName", userName);
For me, the query generated by hibernate is looks like same as my Old SQl query. I cant able to find problem here.
Actually, a big part of the documentation that would be useful in your case is located in the Hibernate Annotations Reference Guides (links provided below). Reading it would be very worth it.
That being said, regarding your specific question, the simplest possible mapping would be:
@Entity
public class Expense {
@Id @GeneratedValue
private Long;
@ManyToOne
private Category category
// getters, setters
...
}
That's all.
If you want to make it bi-directional, you'll have to add a OneToMany
on the other side (and don't forget the mappedBy
element since the association is bidirectional):
@Entity
public class Category {
@Id @GeneratedValue
private Long id;
@OneToMany(mappedBy="category")
private Set<Expense> expenses = new HashSet<Expense>();
....
}
And a possible JPQL query would be:
SELECT e FROM Expense e JOIN e.category c WHERE e.username = :username
Update: Hibernate and JDBC are different. With Hibernate, you need to think objects and the above HQL query (which was more an example) will actually return a List<Expense>
. To get a category name, iterate over the results and navigate through the association. For example:
List<Expense> expenses = ... // some code to retrieve a list by username
for (Expense expense : expenses) {
System.out.println(expense.getCategory().getName());
}
References
- 2.2. Mapping with JPA (Java Persistence Annotations)
- 2.2.5.2. Many-to-one
As Bozho suggested,
@ManyToOne(fetch=FetchType.EAGER) // Gonna be eager by default anyway
@JoinColumn(name="CATEGORY_ID")
private Category category;
Plus this in your Category class to make it bidirectional,
@OneToMany(mappedBy="category")
private List<Expense> expense;
You need not do an inner join like that. When you query the expense, the related category will automatically get loaded eagerly, most likely using join.
In your Expense
class have:
@ManyToOne
@JoinColumn(name="CATEGORY_ID")
private Category category
As pointed in the comments, if you need to access all expenses in a given category, i.e. have the one-to-many relationship, you can have:
@OneToMany
private List<Expense> expenses;
I, for example, prefer to use as little @OneToMany
mappings as possible - you'd have to manager eager/lazy loading, at some point limiting the number of results, etc. For them I tend to use HQL queries that fetch the subset of objects (expenses in your case) that I need.
精彩评论