Trying to create a one to one on a table with a composite key.
I'm unable to get it to work and getting this error:
Error creating bean with name 'sessionFactory' defined in class path resource [applicationContext-dao.xml]: Invocation of init method failed; nested exception is org.hibernate.MappingException: broken column mapping for: compensation.id of: com.ciwise.model.Focus
Compensation.java:
package com.ciwise.model;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.Table;
#Entity
#Table(name = "commissions")
public class Compensation implements Serializable {
private static final long serialVersionUID = 1L;
/**
* Composite key
*/
private CompensationPK compensationPK;
/**
* This year monthly net sales
*/
private double tYMonthlyNetSales;
/**
* Last year monthly net sales
*/
private double lYMonthlyNetSales;
/**
* This year YTD net sales
*/
private double tYYTDNetSales;
private Focus focus;
/**
* Getters and Setters
*/
#OneToOne( mappedBy = "compensation", fetch = FetchType.EAGER)
#JoinColumn(name = "FOCUS_ID")
public Focus getFocus() {
return focus;
}
public void setFocus(Focus focus) {
this.focus = focus;
}
#EmbeddedId
public CompensationPK getCompensationPK() {
return compensationPK;
}
public void setCompensationPK(CompensationPK compensationPK) {
this.compensationPK = compensationPK;
}
#Column(name = "TY_MONTHLY_NET_SALES")
public double gettYMonthlyNetSales() {
return tYMonthlyNetSales;
}
public void settYMonthlyNetSales(double tYMonthlyNetSales) {
this.tYMonthlyNetSales = tYMonthlyNetSales;
}
#Column(name = "LY_MONTHLY_NET_SALES")
public double getlYMonthlyNetSales() {
return lYMonthlyNetSales;
}
public void setlYMonthlyNetSales(double lYMonthlyNetSales) {
this.lYMonthlyNetSales = lYMonthlyNetSales;
}
#Column(name = "TY_YTD_NET_SALES")
public double gettYYTDNetSales() {
return tYYTDNetSales;
}
public void settYYTDNetSales(double tYYTDNetSales) {
this.tYYTDNetSales = tYYTDNetSales;
}
}
CompensationPK.java
package com.ciwise.model;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Embeddable;
#Embeddable
public class CompensationPK implements Serializable {
private String divisionId;
private String repId;
private int focusId;
private int repTypeId;
private int commissionYear;
private int commissionMonth;
#Column(name = "DIVISION_ID")
public String getDivisionId() {
return divisionId;
}
#Column(name = "REP_ID")
public String getRepId() {
return repId;
}
#Column(name = "FOCUS_ID")
public int getFocusId() {
return focusId;
}
#Column(name = "REPTYPE_ID")
public int getRepTypeId() {
return repTypeId;
}
#Column(name = "COMMISSION_YEAR")
public int getCommissionYear() {
return commissionYear;
}
#Column(name = "COMMISSION_MONTH")
public int getCommissionMonth() {
return commissionMonth;
}
public void setDivisionId(String divisionId) {
this.divisionId = divisionId;
}
public void setRepId(String repId) {
this.repId = repId;
}
public void setFocusId(int focusId) {
this.focusId = focusId;
}
public void setRepTypeId(int repTypeId) {
this.repTypeId = repTypeId;
}
public void setCommissionYear(int commissionYear) {
this.commissionYear = commissionYear;
}
public void setCommissionMonth(int commissionMonth) {
this.commissionMonth = commissionMonth;
}
#Override
public boolean equals(Object o) {
return false;
}
#Override
public int hashCode() {
return 0;
}
}
Focus.java:
package com.ciwise.model;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name = "CT_FOCUS")
public class Focus implements Serializable {
private int focusId;
private String focusDesc;
private String focusYN;
private Compensation compensation;
#OneToOne
#PrimaryKeyJoinColumn
public Compensation getCompensation() {
return compensation;
}
public void setCompensation(Compensation compensation) {
this.compensation = compensation;
}
public Focus() {
};
#Id
#Column(name = "FOCUS_ID")
public int getFocusId() {
return focusId;
}
public void setFocusId(int focusId) {
this.focusId = focusId;
}
#Column(name = "FOCUS_DESC", length = 16)
public String getFocusDesc() {
return focusDesc;
}
public void setFocusDesc(String focusDesc) {
this.focusDesc = focusDesc;
}
#Column(name = "FOCUS_YN", length = 1)
public String getFocusYN() {
return focusYN;
}
public void setFocusYN(String focusYN) {
this.focusYN = focusYN;
}
}
Since you used an embeddable type (CompositionPK) as your primary key for Composition entity, you should annotate the corresponding primary key field in your Composition entity with #EmbeddedId.
#EmbeddedId
private CompensationPK compensationPK;
On the Focus entity, you need not specify a #PrimaryKeyJoinColumn on the one-to-one mapping. It will just use the default join column names for the foreign keys.
So this code should be fine without the #PrimaryKeyJoinColumn:
#OneToOne
public Compensation getCompensation() {
return compensation;
}
This is a sample Hibernate generated schema based on your mappings (target DB is MySQL):
Hibernate:
create table CT_FOCUS (
FOCUS_ID integer not null,
FOCUS_DESC varchar(16),
FOCUS_YN varchar(1),
compensation_COMMISSION_MONTH integer,
compensation_COMMISSION_YEAR integer,
compensation_DIVISION_ID varchar(255),
compensation_FOCUS_ID integer,
compensation_REP_ID varchar(255),
compensation_REPTYPE_ID integer,
primary key (FOCUS_ID)
)
Hibernate:
create table commissions (
COMMISSION_MONTH integer not null,
COMMISSION_YEAR integer not null,
DIVISION_ID varchar(255) not null,
FOCUS_ID integer not null,
REP_ID varchar(255) not null,
REPTYPE_ID integer not null,
LY_MONTHLY_NET_SALES double precision,
TY_MONTHLY_NET_SALES double precision,
TY_YTD_NET_SALES double precision,
primary key (COMMISSION_MONTH, COMMISSION_YEAR, DIVISION_ID, FOCUS_ID, REP_ID, REPTYPE_ID)
)
Hibernate:
alter table CT_FOCUS
add constraint FK_d6d2c9n91dlw59uiuqswfueg5
foreign key (compensation_COMMISSION_MONTH, compensation_COMMISSION_YEAR, compensation_DIVISION_ID, compensation_FOCUS_ID, compensation_REP_ID, compensation_REPTYPE_ID)
references commissions (COMMISSION_MONTH, COMMISSION_YEAR, DIVISION_ID, FOCUS_ID, REP_ID, REPTYPE_ID)
#PrimaryKeyJoinColumn can be used on a #OneToOne mapping, if you want the primary keys of Focus entity to be referencing the primary keys of Commission entity. However, you already have defined a primary key for your Focus entity, which the focusId annotated by #Id. So there's no need to specify a #PrimaryKeyJoinColumn.
Related
I am using Oracle database and have to define a UUID column. I followed other posts and created the table using regex pattern for primary key:
CREATE TABLE TEST_UUID (
ID_UUID VARCHAR(255)
DEFAULT REGEXP_REPLACE(RAWTOHEX(SYS_GUID()), '([A-F0-9]{8})([A-F0-9]{4})([A-F0-9]{4})([A-F0-9]{4})([A-F0-9]{12})', '\1-\2-\3-\4-\5'),
NAME VARCHAR2(40) NOT NULL
);
In my entity class I have to define the ID_UUID column of type UUID (cannot define it as String). The entity class looks like this:
import java.util.UUID;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name = "test_uuid")
public class TestUuid {
#Id
#Column(name = "id_uuid")
#GeneratedValue(strategy = GenerationType.AUTO)
private UUID idUuid;
#Column(name = "name")
private String name;
/**
* #return the idUuid
*/
public UUID getIdUuid() {
return idUuid;
}
/**
* #param idUuid the idUuid to set
*/
public void setIdUuid(UUID idUuid) {
this.idUuid = idUuid;
}
/**
* #return the name
*/
public String getName() {
return name;
}
/**
* #param name the name to set
*/
public void setName(String name) {
this.name = name;
}
}
When I retrieve the table values I don't get the same value for ID_UUID whats stored in the database because of UUID data type (if I change it to a String I am able to pull the correct value). My limitation is to use the UUID type as I am migrating from Postgre to Oracle database and cannot change my entity class. Is it possible to retrieve the correct value using UUID data type?
You need to define custom type that stores and retrieves UUID type as VARCHAR.
See Hibernate UUID type implementation.
https://github.com/hibernate/hibernate-orm/blob/main/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/UUIDJavaType.java
In case if you have Hibernate 5 or higher you can use it.
Create own user type
public class UUIDType extends AbstractSingleColumnStandardBasicType<UUID> {
public static final UUIDType INSTANCE = new UUIDType();
public static final String NAME = "UUIDType";
public UUIDType() {
super(VarcharTypeDescriptor.INSTANCE, UUIDTypeDescriptor.INSTANCE);
}
#Override
public String getName() {
return NAME;
}
}
Implement a UUIDTypeDescriptor for storing and retrieving UUID as VARCHAR
public class UUIDTypeDescriptor extends AbstractTypeDescriptor<UUID> {
public static final UUIDTypeDescriptor INSTANCE = new UUIDTypeDescriptor();
public UUIDTypeDescriptor() {
super(UUID.class, ImmutableMutabilityPlan.INSTANCE);
}
#Override
public String toString(UUID uuid) {
return uuid.toString();
}
#Override
public UUID fromString(String s) {
return UUID.fromString(s);
}
#Override
public <T> T unwrap(UUID uuid, Class<T> type, WrapperOptions wrapperOptions) {
if (uuid == null) return null;
if (String.class.isAssignableFrom(type)) {
return (T) uuid.toString();
}
throw unknownUnwrap(type);
}
#Override
public <T> UUID wrap(T value, WrapperOptions wrapperOptions) {
if (value == null)
return null;
if(value instanceof String) {
return UUID.fromString((String) value);
}
throw unknownWrap(value.getClass());
}
}
Apply custom type to your entity
Specific for entity:
#TypeDef(name = UUIDType.NAME,
typeClass = UUIDType.class,
defaultForType = UUID.class)
#Entity
#Table(name = "test_uuid")
public class TestUUID {
}
or on package lavel in package-info.java file:
#TypeDef(
name = UUIDType.NAME,
typeClass = UUIDType.class,
defaultForType = UUID.class
)
package com.model;
I have a table GROCERY which has following structure:
CREATE TABLE grocery
(
gro_id NUMBER,
gro_name VARCHAR(32),
gro_dep_name VARCHAR(32),
gro_price NUMBER(16, 2),
gro_max_discount NUMBER(16, 2),
CONSTRAINT gro_pk PRIMARY KEY (gro_id, gro_dep_name)
)
My problem is that, when I am trying to fetch the data from the table (saved in my oracle data base) , I am getting the following error :
org.hibernate.id.IdentifierGenerationException: null id generated
for:class com.domain.Grocery
I have generated following entity classes according to the structure of the table :
Grocery.java
package com.domain;
import java.math.BigDecimal;
import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.Column;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Table;
/**
* Grocery generated by hbm2java
*/
#SuppressWarnings("serial")
#Entity
#Table(name = "GROCERY", schema = "TPRDBA")
public class Grocery implements java.io.Serializable {
#EmbeddedId
private GroceryId id;
private String groName;
private BigDecimal groPrice;
private BigDecimal groMaxDiscount;
public Grocery() {
}
public Grocery(GroceryId id) {
this.id = id;
}
public Grocery(GroceryId id, String groName, BigDecimal groPrice, BigDecimal groMaxDiscount) {
this.id = id;
this.groName = groName;
this.groPrice = groPrice;
this.groMaxDiscount = groMaxDiscount;
}
#EmbeddedId
#AttributeOverrides({
#AttributeOverride(name = "groId", column = #Column(name = "GRO_ID", nullable = false, precision = 22, scale = 0)),
#AttributeOverride(name = "groDepName", column = #Column(name = "GRO_DEP_NAME", nullable = false, length = 32)) })
public GroceryId getId() {
return this.id;
}
public void setId(GroceryId id) {
this.id = id;
}
#Column(name = "GRO_NAME", length = 32)
public String getGroName() {
return this.groName;
}
public void setGroName(String groName) {
this.groName = groName;
}
#Column(name = "GRO_PRICE", precision = 16)
public BigDecimal getGroPrice() {
return this.groPrice;
}
public void setGroPrice(BigDecimal groPrice) {
this.groPrice = groPrice;
}
#Column(name = "GRO_MAX_DISCOUNT", precision = 16)
public BigDecimal getGroMaxDiscount() {
return this.groMaxDiscount;
}
public void setGroMaxDiscount(BigDecimal groMaxDiscount) {
this.groMaxDiscount = groMaxDiscount;
}
}
GroceryId.java
package com.domain;
// Generated Nov 12, 2018 11:42:16 AM by Hibernate Tools 4.3.1.Final
import java.math.BigDecimal;
import javax.persistence.Column;
import javax.persistence.Embeddable;
/**
* GroceryId generated by hbm2java
*/
#SuppressWarnings("serial")
#Embeddable
public class GroceryId implements java.io.Serializable {
private BigDecimal groId;
private String groDepName;
public GroceryId() {
}
public GroceryId(BigDecimal groId, String groDepName) {
this.groId = groId;
this.groDepName = groDepName;
}
#Column(name = "GRO_ID", nullable = false, precision = 22, scale = 0)
public BigDecimal getGroId() {
return this.groId;
}
public void setGroId(BigDecimal groId) {
this.groId = groId;
}
#Column(name = "GRO_DEP_NAME", nullable = false, length = 32)
public String getGroDepName() {
return this.groDepName;
}
public void setGroDepName(String groDepName) {
this.groDepName = groDepName;
}
public boolean equals(Object other) {
if ((this == other))
return true;
if ((other == null))
return false;
if (!(other instanceof GroceryId))
return false;
GroceryId castOther = (GroceryId) other;
return ((this.getGroId() == castOther.getGroId()) || (this.getGroId() != null && castOther.getGroId() != null
&& this.getGroId().equals(castOther.getGroId())))
&& ((this.getGroDepName() == castOther.getGroDepName())
|| (this.getGroDepName() != null && castOther.getGroDepName() != null
&& this.getGroDepName().equals(castOther.getGroDepName())));
}
public int hashCode() {
int result = 17;
result = 37 * result + (getGroId() == null ? 0 : this.getGroId().hashCode());
result = 37 * result + (getGroDepName() == null ? 0 : this.getGroDepName().hashCode());
return result;
}
}
I have followed this example.
Please help me out, I am not able to figure out what is wrong in it.
Following is my service to take the data from database, which has GroceryRepository which extends CrudRepository :
#Service
public class GroceryService {
#Autowired
GroceryRepository groceryRepository;
public List<Grocery> getAllGrocery()
{
List<Grocery> groceries = new ArrayList<>();
groceryRepository.findAll().forEach(groceries::add);
return groceries;
}
public void addGrocery(Grocery grocery)
{
groceryRepository.save(grocery);
}
}
Missed #EmbeddedId annotation in Grocery.java. Update your code as below.
#EmbeddedId
private GroceryId id;
Just use #EmbeddedId.There must be only one EmbeddedId annotation and no Id annotation when the EmbeddedId annotation is used.
#EmbeddedId
private GroceryId id;
My project based on spring boot,Thymeleaf,mysql,html and Jquery.I tried to make a #oneToMany Relation with unidirectional in maintable,but it produces only error like
2017-10-23 16:17:49.908 ERROR 18724 --- [ main] o.s.boot.SpringApplication : Application startup failed
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'entityManagerFactory' defined in class path
resource
[org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]:
Invocation of init method failed; nested exception is
org.hibernate.AnnotationException: **Unable to map collection
com.vfraternity.process.entity.EntPropertyMaster.blockListPropSub** at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1702)
~[spring-beans-5.0.0.RC4.jar:5.0.0.RC4] at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:583)
~[spring-beans-5.0.0.RC4.jar:5.0.0.RC4] at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:502)
~[spring-beans-5.0.0.RC4.jar:5.0.0.RC4] at
org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:312)
~[spring-beans-5.0.0.RC4.jar:5.0.0.RC4] at
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
~[spring-beans-5.0.0.RC4.jar:5.0.0.RC4] at
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:310)
~[spring-beans-5.0.0.RC4.jar:5.0.0.RC4] at
org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
~[spring-beans-5.0.0.RC4.jar:5.0.0.RC4] at
org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1083)
~[spring-context-5.0.0.RC4.jar:5.0.0.RC4] at
org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:858)
~[spring-context-5.0.0.RC4.jar:5.0.0.RC4] at
org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:549)
~[spring-context-5.0.0.RC4.jar:5.0.0.RC4] at
org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:122)
~[spring-boot-2.0.0.M4.jar:2.0.0.M4] at
org.springframework.boot.SpringApplication.refresh(SpringApplication.java:750)
[spring-boot-2.0.0.M4.jar:2.0.0.M4] at
org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:386)
[spring-boot-2.0.0.M4.jar:2.0.0.M4] at
org.springframework.boot.SpringApplication.run(SpringApplication.java:327)
[spring-boot-2.0.0.M4.jar:2.0.0.M4] at
org.springframework.boot.SpringApplication.run(SpringApplication.java:1245)
[spring-boot-2.0.0.M4.jar:2.0.0.M4] at
org.springframework.boot.SpringApplication.run(SpringApplication.java:1233)
[spring-boot-2.0.0.M4.jar:2.0.0.M4] at
com.vfraternity.VfSpringBootMain.main(VfSpringBootMain.java:12)
[classes/:na] Caused by: org.hibernate.AnnotationException: Unable to
map collection
com.vfraternity.process.entity.EntPropertyMaster.blockListPropSub at
org.hibernate.cfg.annotations.CollectionBinder.bindCollectionSecondPass(CollectionBinder.java:1604)
~[hibernate-core-5.2.10.Final.jar:5.2.10.Final] at
org.hibernate.cfg.annotations.CollectionBinder.bindOneToManySecondPass(CollectionBinder.java:871)
~[hibernate-core-5.2.10.Final.jar:5.2.10.Final] at
org.hibernate.cfg.annotations.CollectionBinder.bindStarToManySecondPass(CollectionBinder.java:786)
~[hibernate-core-5.2.10.Final.jar:5.2.10.Final] at
org.hibernate.cfg.annotations.CollectionBinder$1.secondPass(CollectionBinder.java:725)
~[hibernate-core-5.2.10.Final.jar:5.2.10.Final] at
org.hibernate.cfg.CollectionSecondPass.doSecondPass(CollectionSecondPass.java:54)
~[hibernate-core-5.2.10.Final.jar:5.2.10.Final] at
org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processSecondPasses(InFlightMetadataCollectorImpl.java:1621)
~[hibernate-core-5.2.10.Final.jar:5.2.10.Final] at
org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processSecondPasses(InFlightMetadataCollectorImpl.java:1589)
~[hibernate-core-5.2.10.Final.jar:5.2.10.Final] at
org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:278)
~[hibernate-core-5.2.10.Final.jar:5.2.10.Final] at
org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:858)
~[hibernate-core-5.2.10.Final.jar:5.2.10.Final] at
org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:885)
~[hibernate-core-5.2.10.Final.jar:5.2.10.Final] at
org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:57)
~[spring-orm-5.0.0.RC4.jar:5.0.0.RC4] at
org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:358)
~[spring-orm-5.0.0.RC4.jar:5.0.0.RC4] at
org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:384)
~[spring-orm-5.0.0.RC4.jar:5.0.0.RC4] at
org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:373)
~[spring-orm-5.0.0.RC4.jar:5.0.0.RC4] at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods AbstractAutowireCapableBeanFactory.java:1761)
~[spring-beans-5.0.0.RC4.jar:5.0.0.RC4] at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1698)
~[spring-beans-5.0.0.RC4.jar:5.0.0.RC4] ... 16 common frames omitted
Caused by: org.hibernate.cfg.RecoverableException: Unable to find
column with logical name: propertysubpk in
org.hibernate.mapping.Table(property_master) and its related
supertables and secondary tables at
org.hibernate.cfg.Ejb3JoinColumn.checkReferencedColumnsType(Ejb3JoinColumn.java:831)
~[hibernate-core-5.2.10.Final.jar:5.2.10.Final] at
org.hibernate.cfg.BinderHelper.createSyntheticPropertyReference(BinderHelper.java:243)
~[hibernate-core-5.2.10.Final.jar:5.2.10.Final] at
org.hibernate.cfg.annotations.CollectionBinder.bindCollectionSecondPass(CollectionBinder.java:1594)
~[hibernate-core-5.2.10.Final.jar:5.2.10.Final] ... 31 common frames
omitted Caused by: org.hibernate.MappingException: Unable to find
column with logical name: propertysubpk in
org.hibernate.mapping.Table(property_master) and its related
supertables and secondary tables at
org.hibernate.cfg.Ejb3JoinColumn.checkReferencedColumnsType(Ejb3JoinColumn.java:826)
~[hibernate-core-5.2.10.Final.jar:5.2.10.Final] ... 33 common frames
omitted
I tried to achive unidirectional using
#OneToMany(cascade=CascadeType.ALL)
#JoinColumn(name="propertysubfkid", referencedColumnName="propertysubpk")
private List<EntPropertySub> blockListPropSub = newArrayList<EntPropertySub>();
But it produces only error...
Here is my complete codes..
**EntPropertyMaster**
package com.vfraternity.process.entity;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Version;
import javax.validation.constraints.NotNull;
#Entity
#Table(name="Property_Master")
public class EntPropertyMaster implements Serializable{
/**
*
*/
private static final long serialVersionUID = 6162594257264775391L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="propertyid")
private int property_id;
#NotNull
private String property_name;
#NotNull
private String address1;
#NotNull
#Column(columnDefinition="varchar(15) default'None'")
private String address2;
#NotNull
private String city;
#NotNull
private String state;
#NotNull
private String country;
#NotNull
private int zipcode;
#OneToMany(cascade=CascadeType.ALL)
#JoinColumn(name="propertysubfkid", referencedColumnName="propertysubpk")
private List<EntPropertySub> blockListPropSub = new ArrayList<EntPropertySub>();
#Version
private int version;
private Boolean is_active;
private String created_by;
private Date created_ts;
private String modified_by;
private Date modified_ts;
private String approved_by;
private Date approved_ts;
public EntPropertyMaster() {
}
//Getter Setter
public int getProperty_id() {
return property_id;
}
public void setProperty_id(int property_id) {
this.property_id = property_id;
}
public String getProperty_name() {
return property_name;
}
public void setProperty_name(String property_name) {
this.property_name = property_name;
}
public String getAddress1() {
return address1;
}
public void setAddress1(String address1) {
this.address1 = address1;
}
public String getAddress2() {
return address2;
}
public void setAddress2(String address2) {
this.address2 = address2;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public int getVersion() {
return version;
}
public void setVersion(int version) {
this.version = version;
}
public Boolean getIs_active() {
return is_active;
}
public void setIs_active(Boolean is_active) {
this.is_active = is_active;
}
public String getCreated_by() {
return created_by;
}
public void setCreated_by(String created_by) {
this.created_by = created_by;
}
public Date getCreated_ts() {
return created_ts;
}
public void setCreated_ts(Date created_ts) {
this.created_ts = created_ts;
}
public String getModified_by() {
return modified_by;
}
public void setModified_by(String modified_by) {
this.modified_by = modified_by;
}
public Date getModified_ts() {
return modified_ts;
}
public void setModified_ts(Date modified_ts) {
this.modified_ts = modified_ts;
}
public String getApproved_by() {
return approved_by;
}
public void setApproved_by(String approved_by) {
this.approved_by = approved_by;
}
public Date getApproved_ts() {
return approved_ts;
}
public void setApproved_ts(Date approved_ts) {
this.approved_ts = approved_ts;
}
public int getZipcode() {
return zipcode;
}
public void setZipcode(int zipcode) {
this.zipcode = zipcode;
}
public List<EntPropertySub> getBlockListPropSub() {
return blockListPropSub;
}
public void setBlockListPropSub(List<EntPropertySub> blockListPropSub) {
this.blockListPropSub = blockListPropSub;
}
}
/////////////////////////////////////////////////////////////
EntPropertySub
package com.vfraternity.process.entity;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.persistence.Version;
import javax.validation.constraints.NotNull;
#Entity
#Table(name="propertysub")
public class EntPropertySub implements Serializable
{
/**
*
*/
private static final long serialVersionUID = 810618405796553525L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="propertysubpk")
private int propertySub_pk;
#NotNull
private String blockname;
#NotNull
private int floors;
#NotNull
private String flatstart;
private String flatend;
#Version
private int version;
private Boolean is_active;
private String created_by;
private Date created_ts;
private String modified_by;
private Date modified_ts;
private String approved_by;
private Date approved_ts;
public EntPropertySub() {
}
//Getter Setter
public int getPropertySub_pk() {
return propertySub_pk;
}
public void setPropertySub_pk(int propertySub_pk) {
this.propertySub_pk = propertySub_pk;
}
public String getBlockname() {
return blockname;
}
public void setBlockname(String blockname) {
this.blockname = blockname;
}
public int getFloors() {
return floors;
}
public void setFloors(int floors) {
this.floors = floors;
}
public String getFlatstart() {
return flatstart;
}
public void setFlatstart(String flatstart) {
this.flatstart = flatstart;
}
public String getFlatend() {
return flatend;
}
public void setFlatend(String flatend) {
this.flatend = flatend;
}
public int getVersion() {
return version;
}
public void setVersion(int version) {
this.version = version;
}
public Boolean getIs_active() {
return is_active;
}
public void setIs_active(Boolean is_active) {
this.is_active = is_active;
}
public String getCreated_by() {
return created_by;
}
public void setCreated_by(String created_by) {
this.created_by = created_by;
}
public Date getCreated_ts() {
return created_ts;
}
public void setCreated_ts(Date created_ts) {
this.created_ts = created_ts;
}
public String getModified_by() {
return modified_by;
}
public void setModified_by(String modified_by) {
this.modified_by = modified_by;
}
public Date getModified_ts() {
return modified_ts;
}
public void setModified_ts(Date modified_ts) {
this.modified_ts = modified_ts;
}
public String getApproved_by() {
return approved_by;
}
public void setApproved_by(String approved_by) {
this.approved_by = approved_by;
}
public Date getApproved_ts() {
return approved_ts;
}
public void setApproved_ts(Date approved_ts) {
this.approved_ts = approved_ts;
}
}
Please help me to solve this..Thanks in advance
The cause of the error is:
Unable to find column with logical name: propertysubpk in org.hibernate.mapping.Table(property_master)
The reason is that you have the referencedColumnName attribute wrong. It is supposed to be:
JPA 2.1 11.1.25: The name of the column referenced
by this foreign key column. When
used with entity relationship mappings
other than the cases described below, the
referenced column is in the table of the target
entity. When used with a unidirectional
OneToMany foreign key mapping, the referenced
column is in the table of the
source entity. When used inside a Join-
Table annotation, the referenced key column
is in the entity table of the owning
entity, or inverse entity if the join is part of
the inverse join definition. When used in a
collection table mapping, the referenced
column is in the table of the entity containing
the collection.
To explain: a #JoinColumn creates a column in the many side of the relation (the EntPropertySub here) with the given name that references the PK of the parent entity, unless referencedColumnName is specified. In the latter case the FK in the "many" table references the column given in referencedColumnName. In your case you want to reference the PK of EntPropertyMaster, so referencedColumnName is redundant. Simply use:
#OneToMany(cascade=CascadeType.ALL)
#JoinColumn(name="propertysubfkid")
private List<EntPropertySub> blockListPropSub = newArrayList<EntPropertySub>();
Try this: make sure how the foreign key in the table EntPopertySub called
#OneToMany(cascade=CascadeType.ALL)
#JoinColumn(name="propertyid")
private List<EntPropertySub> blockListPropSub = new ArrayList<EntPropertySub>();
It's not possible to create a physical column on the master table because you have a OneToMany relation. OneToMany means that Master has many Sub Table references.
Let's explain the Problem:
If you would have a column in the master table you need to would add a list of references in one cell.
For Example
------------------
| sub-fk |
|1, 2, 3, 4| <-- and this is against the database normalization
But this is not necessary:
Hibernate will automatically select all the referenced sub-columns for you (intern hibernate joins to the columns)
If you use the entitymanager to select the master data, the sub-data is included in the List blockListPropSub attribute
When you use the #JoinColumn on a #OneToMany relationship, the name attribute will point to the relating tables column, that is EntPropertySub entity and the referencedColumnName should be pointing to the column of the entity in which the #OneToMany annotation is present, that is EntPropertyMaster.
So basically you have it other way round and it should be in my opinion:
#OneToMany(cascade=CascadeType.ALL)
#JoinColumn(name="propertysubpk", referencedColumnName="propertysubfkid")
private List<EntPropertySub> blockListPropSub = newArrayList<EntPropertySub>();
The error clearly shows mapping missing in your schema relation.
You need to map EntPropertyMaster in EntPropertySub.
#OneToMany(cascade=CascadeType.ALL, mappedBy="entPropertyMaster")
private List<EntPropertySub> blockListPropSub = newArrayList<EntPropertySub>();
Provide EntPropertyMaster mapping in relation entity too.i.e.
#ManyToOne
#JoinColumn(name="entPropertyMasterId",referencedColumnName="id")
private EntPropertyMaster entPropertyMaster;
Relationships in JPA are always unidirectional, unless you associate
the parent with the child in both directions. Cascading REMOVE
operations from the parent to the child will require a relation from
the parent to the child (not just the opposite).
Finnaly i got a answer..
i made a changes in master entity "EntPropertyMaster"
"#OneToMany(cascade=CascadeType.ALL)"
"#JoinColumn(name="propertyidfk")"
private List<EntPropertySub> blockListPropSub = new ArrayList<EntPropertySub>();
It will create column in child table,but i wrote this code in parent Entity...
Please Note we need to give unique name for column creation,Then only it creates a column in child table.... not a primarykey column name
of child /parent table..
I have created an object which maps two tables in my database, the Dictionary table and the Token table. The object (class) that represents the join between these two tables is called DictionaryToken.
Here is the class:
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.apache.log4j.Logger;
#Entity
#Table(name="dictionary", catalog="emscribedxcode")
public class DictionaryToken {
private static Logger LOG = Logger.getLogger(DictionaryToken.class);
private Long _seq;
private String _code;
private String _acute;
private String _gender;
private String _codeType;
private String _papplydate;
private String _capplydate;
private Long _tokenLength;
private List <TokenDictionary> _token;
private int _type;
private String _system;
private String _physicalsystem;
/*
* type of 0 is a straight line insert type of 1 is a language dictionary
* entyr type of 2 is a multiple token entry
*/
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "seq")
public Long getSeq() {
return _seq;
}
public void setSeq(Long seq_) {
_seq = seq_;
}
#Column(name = "code")
public String getCode() {
return _code;
}
public void setCode(String code_) {
_code = code_;
}
#Column(name = "acute")
public String getAcute() {
return _acute;
}
public void setAcute(String acute_) {
_acute = acute_;
}
#Column(name = "gender")
public String getGender() {
return _gender;
}
public void setGender(String gender_) {
_gender = gender_;
}
#Column(name = "codetype")
public String getCodeType() {
return _codeType;
}
public void setCodeType(String codeType_) {
_codeType = codeType_;
}
#Column(name = "papplydate")
public String getPapplydate() {
return _papplydate;
}
public void setPapplydate(String papplydate_) {
_papplydate = papplydate_;
}
#Column(name = "capplydate")
public String getCapplydate() {
return _capplydate;
}
public void setCapplydate(String capplydate_) {
_capplydate = capplydate_;
}
#Column(name = "token_length")
public Long getTokenLength() {
return _tokenLength;
}
public void setTokenLength(Long tokenLength_) {
_tokenLength = tokenLength_;
}
#OneToMany (mappedBy = "dictionarytoken", targetEntity = TokenDictionary.class, cascade = CascadeType.ALL, fetch = FetchType.EAGER)
public List<TokenDictionary> get_token() {
return _token;
}
public void set_token(List<TokenDictionary> _token) {
this._token = _token;
}
public void addToToken(TokenDictionary token){
this._token.add(token);
}
#Column(name = "type")
public int getType() {
return _type;
}
public void setType(int _type) {
this._type = _type;
}
#Column(name = "physicalsystem")
public String get_physicalsystem() {
return _physicalsystem;
}
public void set_physicalsystem(String _physicalsystem) {
this._physicalsystem = _physicalsystem;
}
#Column(name = "codingsystem")
public String get_system() {
return _system;
}
public void set_system(String _system) {
this._system = _system;
}
}
Here is my problem. I can perform queries using a service with this object with no problems UNLESS I add a criteria. Here is the method which retrieves the entries
public List<DictionaryToken> getDictionaryTokenEntries(String system) {
Session session = null;
List<DictionaryToken> dictonaries = new ArrayList<DictionaryToken>();
try {
session = HibernateUtils.beginTransaction("emscribedxcode");
session.createCriteria(Dictionary.class).addOrder(Order.desc("codeType"))
Criteria criteria = session.createCriteria(DictionaryToken.class);
/*******THIS IS THE PROBLEM STATEMENT*************************/
if (system != null) {
criteria.add(Restrictions.eq("codingsystem", system));
}
/****************************************************************/
// dictonaries = criteria.list();
Order order = Order.asc("seq");
criteria.addOrder(order);
dictonaries = criteria.list();
System.out.println("Dictionaryentries = " + dictonaries.size());
// System.out.println("Dictionaries entries EVICT start...");
// for(Dictionary dic : dictonaries){
// session.evict(dic);
// }
// System.out.println("Dictionaries entries EVICT end");
} catch (HibernateException e_) {
e_.printStackTrace();
NTEVENT_LOG.error("Error while getting List of Dictionary entries");
} finally {
if (session != null && session.isOpen()) {
try {
HibernateUtils.closeSessions();
} catch (HibernateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return dictonaries;
}
When I add the criteria, I get the following error:
org.hibernate.QueryException: could not resolve property: coding system of : com.artificialmed.domain.dictionary.model.DictionaryToken
I know that it has something to do with the nature of the object which is really a join between my dictionary class and the underlying table and my token class and table.
The field codingsystem is a field in my dictionary class. I think I am suppose to use aliases but I don't know how to do this under the current circumstances. Any help would be greatly appreciated.
Elliott
This was a newbie problem. Hibernate requires the getters and setters of the models that reflect the tables to be of a specific format. The getter MUST BE get+ where name is the fieldname in the underlying table. The setter MUST BE set+ where name is the fieldname of the underlying table. And yes the first letter of Name must capitalized.
So I reverse engineered some tables from my db and when I try to save my object to the db I get the following error:
Initial SessionFactory creation failed.org.hibernate.AnnotationException: A Foreign key refering com.mycode.Block from com.mycode.Account has the wrong number of column. should be 2
Exception in thread "main" java.lang.ExceptionInInitializerError
The Domain objects Are Block which contains a number of Account Objects:
#OneToMany(fetch = FetchType.LAZY, mappedBy = "Block")
public Set<EAccount> getAccounts() {
return this.Accounts;
}
Account has a Composite key of Id and Role. This has been setup in a seperate Class:
#Embeddable
public class BlockAccountId implements java.io.Serializable {
private long blockOid;
private String accountRole;
public BlockAccountId() {
}
public BlockAccountId(long blockOid, String accountRole) {
this.blockOid = blockOid;
this.accountRole = accountRole;
}
#Column(name = "BLOCK_OID", nullable = false)
public long getBlockOid() {
return this.blockOid;
}
public void setBlockOid(long blockOid) {
this.blockOid = blockOid;
}
#Column(name = "ACCOUNT_ROLE", nullable = false, length = 10)
public String getAccountRole() {
return this.accountRole;
}
public void setAccountRole(String accountRole) {
this.accountRole = accountRole;
}
So I want to know. How can I Link the tables Block and account on blockOid but still ensure the account table has both blockOid and accountRole as a composite key.
Any examples would be greatly appreciated!
N.B this is a Block (One) to Account (Many) relationship.
Thanks
The easiest is to place your association directly in the embedded id component.
Hibernate reference documentation
Section 5.1.2.1.1. id as a property using a component type ()
Example (Only write the important getter() and setter())
#Entity
public class Block {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="BLOCK_OID")
long blockOid;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "id.block", cascade=CascadeType.ALL)
Set<Account> accounts = new HashSet<Account>();
}
#Entity
public class Account {
#EmbeddedId BlockAccountId id;
public Account()
{
this.id = new BlockAccountId();
}
public void setBlock(Block pBlock) {
this.id.setBlock(pBlock);
}
public Block getBlock() {
return this.id.getBlock();
}
public String getAccountRole() {
return this.id.getAccountRole();
}
public void setAccountRole(String accountRole) {
this.id.setAccountRole(accountRole);
}
}
#Embeddable
public class BlockAccountId implements java.io.Serializable {
#ManyToOne(optional = false)
private Block block;
#Column(name = "ACCOUNT_ROLE", nullable = false, length = 10)
private String accountRole;
public BlockAccountId() {
}
//Implement equals and hashcode
}
The corresponding database table are :
CREATE TABLE block (
BLOCK_OID bigint(20) NOT NULL auto_increment,
PRIMARY KEY (`BLOCK_OID`)
)
CREATE TABLE account (
ACCOUNT_ROLE varchar(10) NOT NULL,
block_BLOCK_OID bigint(20) NOT NULL,
PRIMARY KEY (`ACCOUNT_ROLE`,`block_BLOCK_OID`),
KEY `FK_block_OID` (`block_BLOCK_OID`),
CONSTRAINT `FK_block_OID` FOREIGN KEY (`block_BLOCK_OID`) REFERENCES `block` (`BLOCK_OID`)
)
based on hibernate documentation here's the link
based on it you can do the following :
#Entity
public class Account {
#EmbeddedId BlockAccountId id;
#MapsId(value = "blockOid")
#ManyToOne
private Block block;
public Account()
{
this.id = new BlockAccountId();
}
public void setBlock(Block pBlock) {
this.block = pBlock;
}
public Block getBlock() {
return this.block;
}
public String getAccountRole() {
return this.id.getAccountRole();
}
public void setAccountRole(String accountRole) {
this.id.setAccountRole(accountRole);
}
}