Hibernate – One-to-Many example (Annotation)

In this tutorial, it will reuse the entire infrastructure of the previous “Hibernate one to many relationship example – XML mapping” tutorial, enhance it to support Hibernate / JPA annotation.

Project Structure

Review the new project structure of this tutorial.

one to many annotation folder
Note
Since Hibernate 3.6, annotation codes are merged into the Hibernate core module, so, the previous pom.xml file can be reuse.

1. “One-to-many” table relationship

See the previous one to many table relationship again.

one to many table relationship

2. Hibernate Model Class

Update previous model classes – Stock.java and StockDailyRecord.java, and define the annotation code inside.

File : Stock.java


package com.mkyong.stock;

import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import static javax.persistence.GenerationType.IDENTITY;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;

@Entity
@Table(name = "stock", catalog = "mkyongdb", uniqueConstraints = {
		@UniqueConstraint(columnNames = "STOCK_NAME"),
		@UniqueConstraint(columnNames = "STOCK_CODE") })
public class Stock implements java.io.Serializable {

	private Integer stockId;
	private String stockCode;
	private String stockName;
	private Set<StockDailyRecord> stockDailyRecords = new HashSet<StockDailyRecord>(
			0);

	public Stock() {
	}

	public Stock(String stockCode, String stockName) {
		this.stockCode = stockCode;
		this.stockName = stockName;
	}

	public Stock(String stockCode, String stockName,
			Set<StockDailyRecord> stockDailyRecords) {
		this.stockCode = stockCode;
		this.stockName = stockName;
		this.stockDailyRecords = stockDailyRecords;
	}

	@Id
	@GeneratedValue(strategy = IDENTITY)
	@Column(name = "STOCK_ID", unique = true, nullable = false)
	public Integer getStockId() {
		return this.stockId;
	}

	public void setStockId(Integer stockId) {
		this.stockId = stockId;
	}

	@Column(name = "STOCK_CODE", unique = true, nullable = false, length = 10)
	public String getStockCode() {
		return this.stockCode;
	}

	public void setStockCode(String stockCode) {
		this.stockCode = stockCode;
	}

	@Column(name = "STOCK_NAME", unique = true, nullable = false, length = 20)
	public String getStockName() {
		return this.stockName;
	}

	public void setStockName(String stockName) {
		this.stockName = stockName;
	}

	@OneToMany(fetch = FetchType.LAZY, mappedBy = "stock")
	public Set<StockDailyRecord> getStockDailyRecords() {
		return this.stockDailyRecords;
	}

	public void setStockDailyRecords(Set<StockDailyRecord> stockDailyRecords) {
		this.stockDailyRecords = stockDailyRecords;
	}

}

File : StockDailyRecord.java


package com.mkyong.stock;

import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import static javax.persistence.GenerationType.IDENTITY;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.UniqueConstraint;

@Entity
@Table(name = "stock_daily_record", catalog = "mkyongdb", 
uniqueConstraints = @UniqueConstraint(columnNames = "DATE"))
public class StockDailyRecord implements java.io.Serializable {

	private Integer recordId;
	private Stock stock;
	private Float priceOpen;
	private Float priceClose;
	private Float priceChange;
	private Long volume;
	private Date date;

	public StockDailyRecord() {
	}

	public StockDailyRecord(Stock stock, Date date) {
		this.stock = stock;
		this.date = date;
	}

	public StockDailyRecord(Stock stock, Float priceOpen, Float priceClose,
			Float priceChange, Long volume, Date date) {
		this.stock = stock;
		this.priceOpen = priceOpen;
		this.priceClose = priceClose;
		this.priceChange = priceChange;
		this.volume = volume;
		this.date = date;
	}

	@Id
	@GeneratedValue(strategy = IDENTITY)
	@Column(name = "RECORD_ID", unique = true, nullable = false)
	public Integer getRecordId() {
		return this.recordId;
	}

	public void setRecordId(Integer recordId) {
		this.recordId = recordId;
	}

	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "STOCK_ID", nullable = false)
	public Stock getStock() {
		return this.stock;
	}

	public void setStock(Stock stock) {
		this.stock = stock;
	}

	@Column(name = "PRICE_OPEN", precision = 6)
	public Float getPriceOpen() {
		return this.priceOpen;
	}

	public void setPriceOpen(Float priceOpen) {
		this.priceOpen = priceOpen;
	}

	@Column(name = "PRICE_CLOSE", precision = 6)
	public Float getPriceClose() {
		return this.priceClose;
	}

	public void setPriceClose(Float priceClose) {
		this.priceClose = priceClose;
	}

	@Column(name = "PRICE_CHANGE", precision = 6)
	public Float getPriceChange() {
		return this.priceChange;
	}

	public void setPriceChange(Float priceChange) {
		this.priceChange = priceChange;
	}

	@Column(name = "VOLUME")
	public Long getVolume() {
		return this.volume;
	}

	public void setVolume(Long volume) {
		this.volume = volume;
	}

	@Temporal(TemporalType.DATE)
	@Column(name = "DATE", unique = true, nullable = false, length = 10)
	public Date getDate() {
		return this.date;
	}

	public void setDate(Date date) {
		this.date = date;
	}

}

3. Hibernate Configuration File

Puts annotated classes Stock.java and StockDailyRecord.java in hibernate.cfg.xml like this :

File : hibernate.cfg.xml


<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
<session-factory>
    <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
    <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/mkyongdb</property>
    <property name="hibernate.connection.username">root</property>
    <property name="hibernate.connection.password">password</property>
    <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
    <property name="show_sql">true</property>
    <mapping class="com.mkyong.stock.Stock" />
    <mapping class="com.mkyong.stock.StockDailyRecord" />
</session-factory>
</hibernate-configuration>

4. Run It

Run it, Hibernate will insert a row into the STOCK table and a row into the STOCK_DAILY_RECORD table.

File : App.java


package com.mkyong;

import java.util.Date;

import org.hibernate.Session;

import com.mkyong.stock.Stock;
import com.mkyong.stock.StockDailyRecord;
import com.mkyong.util.HibernateUtil;

public class App {
	public static void main(String[] args) {
		
        System.out.println("Hibernate one to many (Annotation)");
	Session session = HibernateUtil.getSessionFactory().openSession();

	session.beginTransaction();

	Stock stock = new Stock();
        stock.setStockCode("7052");
        stock.setStockName("PADINI");
        session.save(stock);
        
        StockDailyRecord stockDailyRecords = new StockDailyRecord();
        stockDailyRecords.setPriceOpen(new Float("1.2"));
        stockDailyRecords.setPriceClose(new Float("1.1"));
        stockDailyRecords.setPriceChange(new Float("10.0"));
        stockDailyRecords.setVolume(3000000L);
        stockDailyRecords.setDate(new Date());
        
        stockDailyRecords.setStock(stock);        
        stock.getStockDailyRecords().add(stockDailyRecords);

        session.save(stockDailyRecords);

	session.getTransaction().commit();
	System.out.println("Done");
	}
}

Output


Hibernate one to many (Annotation)
Hibernate: 
    insert 
    into
        mkyongdb.stock
        (STOCK_CODE, STOCK_NAME) 
    values
        (?, ?)
Hibernate: 
    insert 
    into
        mkyongdb.stock_daily_record
        (DATE, PRICE_CHANGE, PRICE_CLOSE, PRICE_OPEN, STOCK_ID, VOLUME) 
    values
        (?, ?, ?, ?, ?, ?)
Done
Download it – Hibernate-one-to-many-annotation.zip (9KB)

Reference

  1. Hibernate Documentation – one to many relationship

About the Author

author image
mkyong
Founder of Mkyong.com, love Java and open source stuff. Follow him on Twitter, or befriend him on Facebook or Google Plus. If you like my tutorials, consider make a donation to these charities.

Comments

avatar
39 Comment threads
12 Thread replies
0 Followers
 
Most reacted comment
Hottest comment thread
40 Comment authors
SalahAla eddineSalman KhanTonyShreevardhan Recent comment authors
newest oldest most voted
Shreevardhan
Guest
Shreevardhan

Here I have a confusion. In App.java you have saved stock table once, the you have added to stockDailyRecords object for mapping and connecting both of them. But why is stockDailyRecords object is being added to stock object before saving
again as below???

stockDailyRecords.setStock(stock);
stock.getStockDailyRecords().add(stockDailyRecords);

session.save(stockDailyRecords);

Ala eddine
Guest
Ala eddine

It is one to many bidirectionelle ,we can get which stock these details are stored .

Marcel Kobain
Guest
Marcel Kobain

Thanks for this nice article,

A question :

Is it mandatory to write (an why)

stockDailyRecords.setStock(stock);
stock.getStockDailyRecords().add(stockDailyRecords);

>> It is not redundant ?
Why not just add to the stock a list of stockDailyRecords ?

Salman Khan
Guest
Salman Khan

how we can do the reference key and reference value column for one to many relationship in spring and hibernate with status column as well as we make a child table for the parent table. plz help me out, I am trying but all the records of phone and email are coming in single row…
Thanks in advance

Tony
Guest
Tony

Thanks for this :-)

Thieu Anh
Guest
Thieu Anh

-Why i can’t code like that :
@Id
@Column(name = “id”)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
Server show error but if i code :
@Id
@Column(name = “id”)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int getId();
Server run !
– i had tried
“@Id
@Column(name = “id”)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;”
with Hirbernate only one table . It ran . But why not with two table with relation.

Salah
Guest
Salah

you can write like this:
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = “STOCK_ID”, unique = true, nullable = false)
private Integer stockId;

@Column(name = “STOCK_CODE”, unique = true, nullable = false, length = 10)
private String stockCode;

@Column(name = “STOCK_NAME”, unique = true, nullable = false, length = 20)
private String stockName;

@OneToMany(fetch = FetchType.LAZY, mappedBy = “stock”)
private Set stockDailyRecords = new HashSet(0);

Derick Daniel
Guest
Derick Daniel

nice tutorial but explanation for the annotations/coding would be more helpful..!

sebastin
Guest
sebastin

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = “STOCK_ID”, nullable = false)
public Stock getStock() {
return this.stock;
}
i dont understand this line any one can explain me

Agustin
Guest
Agustin

I dont know where put hibernate.cfg.xml. I have my persistence.xml with my “Entitys”

Akshay
Guest
Akshay

The thing is if I retireve the child variable it will come with parent details as well, what I want is just that the parent class should get me the child class details only and not other way round

Raed
Guest
Raed

Hi thanks for the nice Blog but what happen if we try to delete a stock-Object from the DB i think we get an orphan rows from type stock_daily_record ?

thanks

Seetesh Hindlekar
Guest
Seetesh Hindlekar

This doesnt look like a One to Many example but just a simple one to one data being inserted into the tables. You need to change the client code to add many records into the Stock table containing many stockdailyrecords.

Ashkan
Guest
Ashkan

very useful, Thank you.

Gourav
Guest
Gourav

i have download your code on this url http://www.mkyong.com/hibernate/hibernate-one-to-many-relationship-example-annotation/ and import in myeclipse id and run i got this error “The archive: C:/Users/abc/.m2/repository/antlr/antlr/2.7.7/antlr-2.7.7.jar which is referenced by the classpath, does not exist.” I’m begginer on java hybernate

Prateek Ashtikar
Guest
Prateek Ashtikar

It seems that your workstation’s local repository (.m2) don’t have a “antlr-2.7.7.jar” file. Try to add this jar in your class-path or if you’ve maven project, add dependency for the same.

Chirag Chavda
Guest
Chirag Chavda

i was working on my own example for one to many relationship in hibernate annotation but i was having some errors so i thought there must be something wrong with my code but when run your source code it keep showing me same error can help me please!!! ?

giuseppe
Guest
giuseppe

Hi first of all thanks for all your posts and time. I’m a frequent reader but it’s my first time. my question is a kind of “best practise” question. I had to write equals and hash method ie @Override public int hashCode() { return 13 * id.hashCode(); } so when the code down is executed stockDailyRecords.setStock(stock); stock.getStockDailyRecords().add(stockDailyRecords); I receive a null pointer error, because stockDailyRecords is not saved yet and id is null you surely know hash method is used for adding items in set but if I save stockDailyRecords before linking it to stock I receive an other error… Read more »

Yamir
Guest
Yamir

Hello Mkyong,

I trying to use your example but using spring jpa, but I notice that the children is not persisted on the database.

Marcin
Guest
Marcin

Hi,
Your posts are really helpful and good commented.Thanks a lot.

Best Regards
Marcin

Luis
Guest
Luis

Nice post, thanks!

One comment be careful if you want to create this schema using

<property name="hibernate.hbm2ddl.auto">update</property>

… you will probably get:

ORA-02261: such unique or primary key already exists in the table

Solution: do not add constraints to your ids, just annotate them like this:

	@Id
	@Column(name = "ID")
	public int getId() {
		return id;
	}

Hope it helps,

Luis

Adeeb
Guest
Adeeb

Hi
Can any one tell me, how will be the mapping if STOCK_ID is changed to STK_ID in stock_daily_record table?
Because i am not sure about the columns used while creating mapping in above code since it is not mentioned in description.
Also with this changes, there will be no logical constraint using FOREIGN key relationship between above two tables.

Thanks

Adrien
Guest
Adrien

Thanks for the example.

You probably want to precise in the title/description that your example is WITHOUT a join table.

You also probably want to precise if you’re doing a Unidirectional mapping or a Bidirectional mapping.

Any chance to provide a similar example but with a join table ?

Adrien
Guest
Adrien
Deepa
Guest
Deepa

Hi, am new to annotations and need to some clarifications on one-to-many relationship which you explained in _http://www.mkyong.com/hibernate/hibernate-one-to-many-relationship-example-annotation/. Consider stock_id and some set_id will be the primary key for “StockDailyRecord” table. In that case how the mappings will be??

Kindly help me the same.

-Deepa

trackback
Parent child relationship hibernate | Jisku.com - Developers Network
Joydeep
Guest
Joydeep

Hi,
In my case of 1-M mapping, whenever i’m adding the association mapping between two pojo in hibernate config file,the following exception is coming..

“Unable to instantiate default tuplizer [org.hibernate.tuple.entity.PojoEntityTuplizer]”

problem goes after removing the mappings informations from config and hbm files.

1. javaassist.jar is already there.
2. all the required setter/getter is present in POJO classes.

can anybody pls suggest me some way.

john
Guest
john

hi Mkyong.
In app.java file where is this

add()

method declare.

stockDailyRecords.setStock(stock);        
        stock.getStockDailyRecords().add(stockDailyRecords);

And i also want to ask can

session.save(stockDailyRecords);

will run query for insertion of both stock and stockDailyRecords?

Risav Karna
Guest
Risav Karna

You don’t need setter methods for id fields as they are generated for you by Hibernate itself. Providing a set method to the client classes may cause conflicts with hibernate and client side programmers.

page one rankings
Guest
page one rankings

I was curious if you ever considered changing the layout of your
site? Its very well written; I love what youve got to say.
But maybe you could a little more in the way of content so people
could connect with it better. Youve got an awful
lot of text for only having 1 or 2 pictures. Maybe you could space it out better?

shyamshyre
Guest
shyamshyre

Hi Mkyong,

Thanks for your Example.

Can you update the Stock Record without StockDetails getting Effected ?.

When i am trying to update Stock, A Record from StockDetail is also getting Deleted.

Please can you help me on this.

adam
Guest
adam

I changed you’re code like this try { Stock stock = new Stock(); stock.setStockCode(“7054”); stock.setStockName(“PADINI”); session.save(stock); StockDailyRecord stockDailyRecords = new StockDailyRecord(); stockDailyRecords.setPriceOpen(new Float(“1.2”)); stockDailyRecords.setPriceClose(new Float(“1.1”)); stockDailyRecords.setPriceChange(new Float(“10.0”)); stockDailyRecords.setVolume(3000000L); stockDailyRecords.setDate(new Date()); stockDailyRecords.setStock(stock); stock.getStockDailyRecords().add(stockDailyRecords); stockDailyRecords = null; session.save(stockDailyRecords); session.getTransaction().commit(); } catch (Exception e) { session.getTransaction().rollback(); } System.out.println(“Done”); I would like to rollback stock relation update if anything goes wrong(see stockDailyRecords = null) on stockDailyRecords updates. But it doesn’t work i expected. do you have any idea about this issue?

Dino
Guest
Dino
Mandar
Guest
Mandar

Plz some one tell me How i use one to many mapping in hibernate for creation of three tables.
1.discussion(discId,queId,ansId)
2.question(queId,question,postdate)
3.answer(ansId,answer,postDate)

Thanks in advance

Plz rply its argent

trackback
Hibernate Composite Keys With Annotations « Jaehoo Weblog