A one-to-one relationships occurs when one entity is related to exactly one occurrence in another entity.
“One-to-one” example
This is a one-to-one relationship table design, a STOCK table contains exactly one record in STOCK_DETAIL table. Both tables have the same Stock_Id as primary key. In STOCK_DETAIL table, Stock_Id is the primary key and also a foreign key to STOCK table. This is one of the common ways to define one-to-one relationship. More detail…
Hibernate implementation
In Hibernate, this “one-to-one” relationship can implemented in two ways :
- Hibernate XML Mapping file
- Hibernate Annotation
1. Hibernate XML mapping file
In XML mapping way, you need two Java classes to hold the table data.
- Stock.java -> STOCK table
- StockDetail.java -> STOCK_DETAIL table
and two XML mapping files to describe the table relationship.
- Stock.hbm.xml -> STOCK table
- StockDetail.hbm.xml -> STOCK_DETAIL table
Stock.java
... public class Stock implements java.io.Serializable { private StockDetail stockDetail; ... public StockDetail getStockDetail() { return this.stockDetail; } public void setStockDetail(StockDetail stockDetail) { this.stockDetail = stockDetail; }
StockDetail.java
... public class StockDetail implements java.io.Serializable { private Stock stock; ... public Stock getStock() { return this.stock; } public void setStock(Stock stock) { this.stock = stock; }
Stock.hbm.xml
... <class name="com.mkyong.common.Stock" table="stock" ...> <id name="stockId" type="java.lang.Integer"> <column name="STOCK_ID" /> <generator class="identity" /> </id> ... <one-to-one name="stockDetail" class="com.mkyong.common.StockDetail" cascade="save-update"></one-to-one> ...
StockDetail.hbm.xml
... <class name="com.mkyong.common.StockDetail" table="stock_detail" ...> <id name="stockId" type="java.lang.Integer"> <column name="STOCK_ID" /> <generator class="foreign"> <param name="property">stock</param> </generator> </id> <one-to-one name="stock" class="com.mkyong.common.Stock" constrained="true"></one-to-one> ...
The main difficulty with one-to-one relationship is ensuring both are assigned the same primary key. In StockDetail.hbm.xml, a special foreign identifier generator is declared, it will know get the primary key value from STOCK table. With constrained=”true”, it ensure the Stock must exists.
2. Hibernate annotation
In annotation way, only two classes are required, all the relationships are declared inside the Java classes.
- Stock.java -> STOCK table
- StockDetail.java -> STOCK_DETAIL table
Stock.java
... @Entity @Table(name = "stock", catalog = "mkyong", uniqueConstraints = { @UniqueConstraint(columnNames = "STOCK_NAME"), @UniqueConstraint(columnNames = "STOCK_CODE") }) public class Stock implements java.io.Serializable { private StockDetail stockDetail; ... @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "STOCK_ID", unique = true, nullable = false) public Integer getStockId() { return this.stockId; } @OneToOne(fetch = FetchType.LAZY, mappedBy = "stock") @Cascade({CascadeType.SAVE_UPDATE}) public StockDetail getStockDetail() { return this.stockDetail; }
StockDetail.java
@Entity @Table(name = "stock_detail", catalog = "mkyong") public class StockDetail implements java.io.Serializable { private Stock stock; ... @GenericGenerator(name = "generator", strategy = "foreign", parameters = @Parameter(name = "property", value = "stock")) @Id @GeneratedValue(generator = "generator") @Column(name = "STOCK_ID", unique = true, nullable = false) public Integer getStockId() { return this.stockId; } @OneToOne(fetch = FetchType.LAZY) @PrimaryKeyJoinColumn public Stock getStock() { return this.stock; }
The code is self-explanatory, all the @annotation are the XML mapping tag substitution.
Test It
Run the example, both annotation and XML mapping file will generate the same output. Hibernate inserts a row into the STOCK table and a row into the STOCK_DETAIL table.
Stock stock = new Stock(); stock.setStockCode("4715"); stock.setStockName("GENM"); StockDetail stockDetail = new StockDetail(); stockDetail.setCompName("GENTING Malaysia"); stockDetail.setCompDesc("Best resort in the world"); stockDetail.setListedDate(new Date()); stock.setStockDetail(stockDetail); stockDetail.setStock(stock); session.save(stock);
Output
Hibernate:
INSERT INTO mkyong.stock
(STOCK_CODE, STOCK_NAME)
VALUES (?, ?)
Hibernate:
INSERT INTO mkyong.stock_detail
(COMP_NAME, COMP_DESC, REMARK, LISTED_DATE, STOCK_ID)
VALUES (?, ?, ?, ?, ?)Download Full Project
In this tutorial, many files and configuration steps are hidden, only the important files are remark. If you are interest to do the hand-on, you can download the full project here.
- Hibernate one-to-one XML mapping example – Full project download.
- Hibernate one-to-one annotation example – Full project download.
These two projects are developed in Eclipse IDE, using Maven as project management tool, and MySQL as database engine. The MySQL table creation scripts are stored in “db” folder.

