views:

96

answers:

3

Hi, 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 to 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.

+2  A: 

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.

Bozho
I think making it bidirectional is a good idea. What say you? You just need to add one more suggestion here regarding the `Category` class.
Adeel Ansari
+3  A: 

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

Pascal Thivent
Thanks! I tried the things you have told. I updated the result and some doubts in my question. i hope you will answer for them.
NooBDevelopeR
I also want to tell you that the links you provided is very helpful for me. I just red the Many-To-One part alone. After seeing the link, it reminded me about the time period i wasted in searching of Many-To-One in the internet.
NooBDevelopeR
@MaRaVan You're welcome. Glad it helped.
Pascal Thivent
@pascal: ya it helped, But, you never replied for my updates in my question. I have a huge list in there. I am still strucking in them, you know.
NooBDevelopeR
@MaRaVan Maybe I also have a huge list in there. Maybe I don't have *your* database and can't debug it for you. Maybe I didn't understand that the "problem" wasn't solved. For me, the original problem *is* solved.
Pascal Thivent
@Pascal: Hey, don't take it bad. Actually what i am trying is, i have got a object, its one of property is in another table. If you see the Query generated by hibernate means, you can fully understand my problem. After `on` expens0_.category_catId=category1_.catId, see its checking with the same values from the same table. I did the things you suggested. Create Category category; and its setters getters. Annotated with @ManyToOne. Then, still why its checking with same values of same entity. I am a beginner, i cant figure it out. Give me a hand!!!
NooBDevelopeR
@MaRaVan I did, I was updating my answer.
Pascal Thivent
@Pascal: Well, i am fully responsible for my questions. But if the questions were funny or insane or meaningless, i dont care. Because, i am not doing this for purpose. I don't know, how actually express the thing. I am a beginner. I will laugh on me, after i got enough knowledge and reading the same questions in future. On the time me too will feel like funny or insane or meaningless.
NooBDevelopeR
@MaRaVan I'm not following you, I don't know what you're talking about. But just in case a clarification is required, my previous comment was an answer to *"Give me a hand!"*.
Pascal Thivent
@Pascal: Again, you took it badly... I am sorry for that. Actually, i what i am trying to say is, "i thought you were not answering for my update, because of my question is meaningless". Professionals often do like that. I do not blame them, because that is their nature. Me too will also do like that, in future(i ll became professional in what i do). I am just explaining myself. "But if the questions were funny or insane or meaningless, i dont care" means, i am dont actually know the question is meaningless, because i am noob now. Again sorry, if those words irritates you. Sorry man!!! Cool.
NooBDevelopeR
@MaRaVan I didn't take anything badly, don't worry. And I usually let people know if I understood their question or any follow-up, or not, especially if I started answering. Just be patient :)
Pascal Thivent
@Pascal: Feels like Cooooool :) Ya sure, i ll be patient...
NooBDevelopeR
@MaRaVan By the way, does the last update answer pending questions?
Pascal Thivent
NooBDevelopeR
+2  A: 

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.

Adeel Ansari
+1 good points.
Pascal Thivent
@Pascal Thivent: Thanks, Pascal. But you always come with a detailed, well formed and much more helpful answer. :)
Adeel Ansari