Tuesday, May 20, 2014

Hibernate – One-To-Many Example


1. “One-to-many” example

This is a one-to-many relationship table design, a STOCK table has many occurrences STOCK_DAILY_RECORD table.
one to many table relationship
See MySQL table scripts
DROP TABLE IF EXISTS `stock`;
CREATE TABLE `stock` (
  `STOCK_ID` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  `STOCK_CODE` VARCHAR(10) NOT NULL,
  `STOCK_NAME` VARCHAR(20) NOT NULL,
  PRIMARY KEY (`STOCK_ID`) USING BTREE,
  UNIQUE KEY `UNI_STOCK_NAME` (`STOCK_NAME`),
  UNIQUE KEY `UNI_STOCK_ID` (`STOCK_CODE`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=34 DEFAULT CHARSET=utf8;
 
 
DROP TABLE IF EXISTS `mkyongdb`.`stock_daily_record`;
CREATE TABLE  `mkyongdb`.`stock_daily_record` (
  `RECORD_ID` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  `PRICE_OPEN` FLOAT(6,2) DEFAULT NULL,
  `PRICE_CLOSE` FLOAT(6,2) DEFAULT NULL,
  `PRICE_CHANGE` FLOAT(6,2) DEFAULT NULL,
  `VOLUME` BIGINT(20) UNSIGNED DEFAULT NULL,
  `DATE` DATE NOT NULL,
  `STOCK_ID` INT(10) UNSIGNED NOT NULL,
  PRIMARY KEY (`RECORD_ID`) USING BTREE,
  UNIQUE KEY `UNI_STOCK_DAILY_DATE` (`DATE`),
  KEY `FK_STOCK_TRANSACTION_STOCK_ID` (`STOCK_ID`),
  CONSTRAINT `FK_STOCK_TRANSACTION_STOCK_ID` FOREIGN KEY (`STOCK_ID`) 
  REFERENCES `stock` (`STOCK_ID`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=36 DEFAULT CHARSET=utf8;
2. create model classes to map for tables

we already have a Stock.java class which was made under package package com.mkyong.common;
 first let's rename it to package com.mkyong.stock;
 so we have better packaging structure
 you have to do few modifications to support the one to many relationship
 
 or else you can make new Stock.java in new package
 
 
 ---------
 
 package com.mkyong.stock;

import static javax.persistence.GenerationType.IDENTITY;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;

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

/**
*/
private static final long serialVersionUID = 7029806795746254329L;
private Integer stockId;
private String stockCode;
private String stockName;

public Stock() {

}

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

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

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

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

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

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

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


-----------------------------------

for StockDailyRecord  create another java class






Errors
----------

1. AppOneToMany.java stockDailyRecords.setStock(stock);  was giving error, mapping to wrong Stock.java
previously on common package.
Reason : StockDailyRecord.java , I have imported import com.mkyong.common.Stock;
so the setter was mapped to com.mkyong.common.Stock;

2. Error in running application 
------------------------------

Hibernate one to many (Annotation)
May 20, 2014 4:11:34 PM org.hibernate.annotations.common.Version
INFO: HCANN000001: Hibernate Commons Annotations {4.0.1.Final}
May 20, 2014 4:11:34 PM org.hibernate.Version logVersion
INFO: HHH000412: Hibernate Core {4.1.4.Final}
May 20, 2014 4:11:34 PM org.hibernate.cfg.Environment
INFO: HHH000206: hibernate.properties not found
May 20, 2014 4:11:34 PM org.hibernate.cfg.Environment buildBytecodeProvider
INFO: HHH000021: Bytecode provider name : javassist
May 20, 2014 4:11:34 PM org.hibernate.cfg.Configuration configure
INFO: HHH000043: Configuring from resource: /hibernate.cfg.xml
May 20, 2014 4:11:34 PM org.hibernate.cfg.Configuration getConfigurationInputStream
INFO: HHH000040: Configuration resource: /hibernate.cfg.xml
May 20, 2014 4:11:34 PM org.hibernate.internal.util.xml.DTDEntityResolver resolveEntity
WARN: HHH000223: Recognized obsolete hibernate namespace http://hibernate.sourceforge.net/. Use namespace http://www.hibernate.org/dtd/ instead. Refer to Hibernate 3.6 Migration Guide!
May 20, 2014 4:11:34 PM org.hibernate.cfg.Configuration doConfigure
INFO: HHH000041: Configured SessionFactory: null
Initial SessionFactory creation failed.org.hibernate.AnnotationException: Use of the same entity name twice: Stock
Exception in thread "main" java.lang.ExceptionInInitializerError
at com.mkyong.util.HibernateUtil.buildSessionFactory(HibernateUtil.java:20)
at com.mkyong.util.HibernateUtil.(HibernateUtil.java:8)
at com.mkyong.AppOneToMany.main(AppOneToMany.java:15)
Caused by: org.hibernate.AnnotationException: Use of the same entity name twice: Stock
at org.hibernate.cfg.annotations.EntityBinder.bindEntity(EntityBinder.java:402)
at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:586)
at org.hibernate.cfg.Configuration$MetadataSourceQueue.processAnnotatedClassesQueue(Configuration.java:3435)
at org.hibernate.cfg.Configuration$MetadataSourceQueue.processMetadata(Configuration.java:3389)
at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1341)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1731)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1782)
at com.mkyong.util.HibernateUtil.buildSessionFactory(HibernateUtil.java:16)
... 2 more
Caused by: org.hibernate.DuplicateMappingException: duplicate import: Stock refers to both com.mkyong.stock.Stock and com.mkyong.common.Stock (try using auto-import="false")
at org.hibernate.cfg.Configuration$MappingsImpl.addImport(Configuration.java:2582)
at org.hibernate.cfg.annotations.EntityBinder.bindEntity(EntityBinder.java:395)
... 9 more

-------------------
Reason : I have included two entries in the "hibernate.cfg.xml"
  
 
 
  
  If you can see above , I have two entries for Stock.java   and
  
  Error itself gives asuggestion to 
  duplicate import: Stock refers to both com.mkyong.stock.Stock and com.mkyong.common.Stock (try using auto-import="false")
  
  solution 1 :First i try with removing one record, 
  execute
  
  ------------------ i still hvae an error--------------
  
  Hibernate one to many (Annotation)
May 20, 2014 4:18:52 PM org.hibernate.annotations.common.Version
INFO: HCANN000001: Hibernate Commons Annotations {4.0.1.Final}
May 20, 2014 4:18:52 PM org.hibernate.Version logVersion
INFO: HHH000412: Hibernate Core {4.1.4.Final}
May 20, 2014 4:18:52 PM org.hibernate.cfg.Environment
INFO: HHH000206: hibernate.properties not found
May 20, 2014 4:18:52 PM org.hibernate.cfg.Environment buildBytecodeProvider
INFO: HHH000021: Bytecode provider name : javassist
May 20, 2014 4:18:52 PM org.hibernate.cfg.Configuration configure
INFO: HHH000043: Configuring from resource: /hibernate.cfg.xml
May 20, 2014 4:18:52 PM org.hibernate.cfg.Configuration getConfigurationInputStream
INFO: HHH000040: Configuration resource: /hibernate.cfg.xml
May 20, 2014 4:18:52 PM org.hibernate.internal.util.xml.DTDEntityResolver resolveEntity
WARN: HHH000223: Recognized obsolete hibernate namespace http://hibernate.sourceforge.net/. Use namespace http://www.hibernate.org/dtd/ instead. Refer to Hibernate 3.6 Migration Guide!
May 20, 2014 4:18:52 PM org.hibernate.cfg.Configuration doConfigure
INFO: HHH000041: Configured SessionFactory: null
Initial SessionFactory creation failed.org.hibernate.AnnotationException: Use of @OneToMany or @ManyToMany targeting an unmapped class: com.mkyong.stock.Stock.stockDailyRecords[com.mkyong.stock.StockDailyRecord]
Exception in thread "main" java.lang.ExceptionInInitializerError
at com.mkyong.util.HibernateUtil.buildSessionFactory(HibernateUtil.java:20)
at com.mkyong.util.HibernateUtil.(HibernateUtil.java:8)
at com.mkyong.AppOneToMany.main(AppOneToMany.java:15)
Caused by: org.hibernate.AnnotationException: Use of @OneToMany or @ManyToMany targeting an unmapped class: com.mkyong.stock.Stock.stockDailyRecords[com.mkyong.stock.StockDailyRecord]
at org.hibernate.cfg.annotations.CollectionBinder.bindManyToManySecondPass(CollectionBinder.java:1204)
at org.hibernate.cfg.annotations.CollectionBinder.bindStarToManySecondPass(CollectionBinder.java:735)
at org.hibernate.cfg.annotations.CollectionBinder$1.secondPass(CollectionBinder.java:670)
at org.hibernate.cfg.CollectionSecondPass.doSecondPass(CollectionSecondPass.java:66)
at org.hibernate.cfg.Configuration.originalSecondPassCompile(Configuration.java:1591)
at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1366)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1731)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1782)
at com.mkyong.util.HibernateUtil.buildSessionFactory(HibernateUtil.java:16)
... 2 more

-----------------------
Reason to happen this error
http://stackoverflow.com/questions/4956855/hibernate-problem-use-of-onetomany-or-manytomany-targeting-an-unmapped-clas
Your annotations look fine. Here are the things to check:

make sure the annotation is javax.persistence.Entity, and not org.hibernate.annotations.Entity. The former makes the entity detectable. The latter is just an addition.

if you are manually listing your entities (in persistence.xml, in hibernate.cfg.xml, or when configuring your session factory), then make sure you have also listed the ScopeTopic entity

make sure you don't have multiple ScopeTopic classes in different packages, and you've imported the wrong one.


So I deleted all the classes Stock.java which was previously put inside to com.mkyong.common; package
I have been using it's references and I deleted all the references from App2.java and StockDetail.java classes

and it's runs fine
----------------

output will be 

---------------

Hibernate: insert into mkyong.stock (STOCK_CODE, STOCK_NAME) values (?, ?)
Hibernate: insert into mkyong.stock_daily_record (DATE, PRICE_CHANGE, PRICE_CLOSE, PRICE_OPEN, STOCK_ID, VOLUME) values (?, ?, ?, ?, ?, ?)
Done

-----------

if you need full detail output

-------------------------------------------------------------

Hibernate one to many (Annotation)
May 20, 2014 4:55:34 PM org.hibernate.annotations.common.Version
INFO: HCANN000001: Hibernate Commons Annotations {4.0.1.Final}
May 20, 2014 4:55:34 PM org.hibernate.Version logVersion
INFO: HHH000412: Hibernate Core {4.1.4.Final}
May 20, 2014 4:55:34 PM org.hibernate.cfg.Environment
INFO: HHH000206: hibernate.properties not found
May 20, 2014 4:55:34 PM org.hibernate.cfg.Environment buildBytecodeProvider
INFO: HHH000021: Bytecode provider name : javassist
May 20, 2014 4:55:34 PM org.hibernate.cfg.Configuration configure
INFO: HHH000043: Configuring from resource: /hibernate.cfg.xml
May 20, 2014 4:55:34 PM org.hibernate.cfg.Configuration getConfigurationInputStream
INFO: HHH000040: Configuration resource: /hibernate.cfg.xml
May 20, 2014 4:55:34 PM org.hibernate.internal.util.xml.DTDEntityResolver resolveEntity
WARN: HHH000223: Recognized obsolete hibernate namespace http://hibernate.sourceforge.net/. Use namespace http://www.hibernate.org/dtd/ instead. Refer to Hibernate 3.6 Migration Guide!
May 20, 2014 4:55:34 PM org.hibernate.cfg.Configuration doConfigure
INFO: HHH000041: Configured SessionFactory: null
May 20, 2014 4:55:35 PM org.hibernate.service.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
INFO: HHH000402: Using Hibernate built-in connection pool (not for production use!)
May 20, 2014 4:55:35 PM org.hibernate.service.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
INFO: HHH000115: Hibernate connection pool size: 20
May 20, 2014 4:55:35 PM org.hibernate.service.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
INFO: HHH000006: Autocommit mode: false
May 20, 2014 4:55:35 PM org.hibernate.service.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
INFO: HHH000401: using driver [com.mysql.jdbc.Driver] at URL [jdbc:mysql://localhost:3306/mkyong]
May 20, 2014 4:55:35 PM org.hibernate.service.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
INFO: HHH000046: Connection properties: {user=root, password=****}
May 20, 2014 4:55:35 PM org.hibernate.dialect.Dialect
INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQLDialect
May 20, 2014 4:55:35 PM org.hibernate.engine.jdbc.internal.LobCreatorBuilder useContextualLobCreation
INFO: HHH000423: Disabling contextual LOB creation as JDBC driver reported JDBC version [3] less than 4
May 20, 2014 4:55:35 PM org.hibernate.engine.transaction.internal.TransactionFactoryInitiator initiateService
INFO: HHH000399: Using default transaction strategy (direct JDBC transactions)
May 20, 2014 4:55:35 PM org.hibernate.hql.internal.ast.ASTQueryTranslatorFactory
INFO: HHH000397: Using ASTQueryTranslatorFactory
Hibernate: insert into mkyong.stock (STOCK_CODE, STOCK_NAME) values (?, ?)
Hibernate: insert into mkyong.stock_daily_record (DATE, PRICE_CHANGE, PRICE_CLOSE, PRICE_OPEN, STOCK_ID, VOLUME) values (?, ?, ?, ?, ?, ?)
Done








------------------------------------------------











No comments:

Post a Comment