Hibernate "Column --- cannot be null - java

I'm using Hibernate in combination with phpmyadmin (MySQL).
Recently I found a really weird error.
Whenever I try to insert a new row (.persist) I get the following error:
com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Column 'user_id' cannot be null
The error is really obvious.
But the weird part is, this error came out of nowhere.
I'm ENTIRELY sure the property userId (mapped to 'user_id') isn't null. I tested several times.
This is the mapping part:
(On the #manytoone part).
<property name="userId" update="false" insert="false" column="user_id" type="java.lang.Long" />
The OneToMany part isn't the problem I guess.
So the problem here is, i'm 100% sure the value isn't null, still Hibernate passes it as null to the MySQL. (Getter does work).
UPDATE
#ManyToOne side, which causes the error
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="xx.xx.xx.AlarmEntity" table="alarms">
<meta attribute="class-description">
Hierin staan de object properties van de alarm entiteit.
</meta>
<id name="id" type="java.lang.Long" column="id">
<generator class="native"/>
</id>
<property name="keepsRunning" type="java.lang.Boolean">
<column name="keeps_running" sql-type="int"></column>
</property>
<property name="userId" update="false" insert="false" column="user_id" type="java.lang.Long" />
<many-to-one name="userAlarm" cascade="save-update" fetch="select" column="user_id" class="xx.xx.xx.UserEntity" />
</class>
</hibernate-mapping>

Please check the mapping
UserEntity
private int user_id;
private Set<AlarmEntity> alarm;
AlarmEntity
private int alarm_id;
private String keepsRunning;
As per your requirement , I have provided mapping with annotation please check
User
#Id
#Column(name = "userId")
private Long userId;
// parent to Alarm
#Fetch(value = FetchMode.SELECT)
#OneToMany(cascade = CascadeType.ALL)
#JoinColumn(name = "userId")
#JsonIgnore
private List<Alarm> alarmList ;
Alarm
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "alarmId")
private Long alarmId;
#ManyToOne
#JoinColumn(name = "userId", insertable = true, updatable = true, nullable = true)
private User user;
#Column(name="keepsRunning")
private String keepsRunning;

Providing Annotation Approach one to Many Example which worked for me
In below example Factory can have multiple product ,that means there is one to many mapping between Factory and Product where Product is owning side of this relationship which means Product will maintain foreign key constraint for holding factory id.
Table structure:
CREATE TABLE `factory` (
`id` bigint NOT NULL AUTO_INCREMENT,
`factory_name` varchar(500) DEFAULT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `product` (
`id` bigint NOT NULL AUTO_INCREMENT,
`factory_id` bigint NOT NULL ,
`product_name` varchar(500) DEFAULT NULL,
PRIMARY KEY (`id`)
);
ALTER TABLE product
ADD CONSTRAINT FK_product_factory
FOREIGN KEY (factory_id) REFERENCES factory (id);
Entity Structure:
#Entity
#Table(name = “factory”)
public class Factory {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name=“id”)
private int id;
#Column(name = "factory_name")
private String factoryName;
#OneToMany(mappedBy = “factory”,cascade = CascadeType.ALL,fetch = FetchType.EAGER)
private List<Product> products = new ArrayList<>();
}
#Entity
#Table(name = “product”)
public class Product {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name = "id")
private int id;
#Column(name = “product_name")
private String productName;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name=“factory_id")
private Factory factory;
}
Service Structure:
#Service
public class ProductService {
#Autowired
private ProductRepository productRepository;
#Autowired
private FactoryRepository factoryRepository;
public void saveFactoryAndProduct(){
Factory factory = new Factory();
factory.setFactoryName("F1");
Product product1 = new Product();
product1.setProductName("P1");
factory.getProducts.add(product1);
product.setFactory(factory);
Product product2 = new Product();
product2.setProductName("P2");
factory.getProducts.add(product2);
product1.setFactory(factory);
//Saving factory will also saved linked product1 and product2 data having factory_id as a foreign key from Factory table
factoryRepository.save(factory);
}
}
Note:
Saving Products with Mapped Factory.Here we don't need to save product specifically since Factory is maintaining cascade so when we save factory related products will also save but we just need to setFatory for every product object inorder to maintain foreign key in product.

Related

Jpa Hibernate map key in multi column relationship

I would like to map a Java Map, where all key values are stored in the same table.
Something similar to https://en.wikibooks.org/wiki/Java_Persistence/Relationships#Example_of_a_map_key_column_relationship_database
but with the key being an object and not a simple type.
Say I have an Entity "User"
#Entity
public class User{
#Id
private String userId;
#OneToMany
#MapKeyClass(CalenderWeek.class)
private Map<CalenderWeek, WorkedTime> workedTimeMap;
The key CalendarWeek would be something like this
#Embeddable
public class CalenderWeek {
int year;
Month month; // Month is the enum java.time.Month
The WorkedTime would be something like
#Embeddable
public class WorkedTime {
private long workedHours;
The corresponding worked time table should be like this
worked_time
user_id | year | month | worked_hours
---------|------|-------| ---
1 | 2017 | 11 | 42
Is it possible to get that
or do I have to do it as described here
https://en.wikibooks.org/wiki/Java_Persistence/Relationships#Example_of_a_map_key_class_embedded_relationship_annotation
i.e., with three tables.
In general if you want to have a Map u simply use #ElementCollection annotation and if you want to override some of the column or associations from the Embeddables then you use #AttributeOverride / #AssociationOverride:
#ElementCollection
#AttributeOverrides({
#AttributeOverride(name="key.year",
column=#Column(name="YEAR1")),
#AttributeOverride(name="value.workedHours",
column=#Column(name="WORKED_H"))
})
private Map<CalenderWeek, WorkedTime> workedTimeMap;
Depending whether you want to override the key or value attribute, you add those prefixes respectively for persistence provider to be able to recodgnize the difference.
The answer of Maciej Kowalski was very useful and correct. Thank you.
I just want to complete here the answer and extend it a little as I used xml configuration at the end.
The Annotated version ended like that
#Entity
public class UserWorklogAggregate {
#Id
private String userId;
#ElementCollection
#CollectionTable(
name = "worked_time",
joinColumns = #JoinColumn(name = "user_id")
)
#AttributeOverrides({
#AttributeOverride(name = "key.year", column = #Column(name = "year")),
#AttributeOverride(name = "key.week", column = #Column(name = "week")),
#AttributeOverride(name = "value.workedDuration", column = #Column(name = "worked_duration"))
})
private final Map<CalenderWeek, WorkedTime> workedTimeMap = new HashMap<>();
and the xml version
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping default-access="field" default-cascade="all">
<class name="org.whatever.UserWorklogAggregate" table="user_worklog_aggregate">
<id name="userId" length="10" column="user_id" />
<map name="workedTimeMap" table="worked_time" >
<key column="user_id" />
<composite-map-key class="org.whatever.CalenderWeek">
<key-property name="year" column="year"/>
<key-property name="week" column="week"/>
</composite-map-key>
<composite-element class="org.whatever.WorkedTime" >
<property name="workedDuration" column="worked_duration"/>
</composite-element>
</map>
</class>
I assume you want to store working hours of a user per month+year.
Looking at your result table I would recommend not using Embeddable. You could try this approach:
#Entity
public class User{
#Id
private String id;
#OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
private List<WorkedTime> workedTime;
plus the back reference:
#Entity
public class WorkedTime {
#Id
private long id;
#ManyToOne
#JoinColumn(name = "user_id", nullable = false)
private User user;
private int year;
private Month month;
private long workedHours;
This would result in having only two tables.

Bidirectional #OneToMany relation with JPA annotations doesn't seem to work

This is in reference to this answer.
Entities-
// Many to One
#Entity
#Table
public class Address {
#Id
#GeneratedValue
#Column
private int addressIdentity;
#Column
private int houseNo;
#Column
private char streetNo;
#Column
private int pincode;
#Column
private String city;
#Column
private String state;
#Column
private String country;
#ManyToOne
#JoinTable(name="PersonAddress",
joinColumns=#JoinColumn(name="addressId", insertable = false, updatable = false),
inverseJoinColumns=#JoinColumn(name="personId", insertable = false, updatable = false)
)
private Person person;
// getters and setters
One to Many
#Entity
#Table
public class Person {
#Id
#GeneratedValue
#Column
private int personId;
#Column
private String name;
#Column
private String designation;
#OneToMany
#JoinTable(name = "PersonAddress",
joinColumns = #JoinColumn(name = "personId"),
inverseJoinColumns = #JoinColumn(name = "addressId"))
private Set<Address> addSet = new HashSet<Address>();
// getters and setters
Hibernate configuration file-
<hibernate-configuration>
<session-factory name="">
<property name="hibernate.connection.driver_class">org.postgresql.Driver</property>
<property name="hibernate.connection.password">hello</property>
<property name="hibernate.connection.url">jdbc:postgresql://localhost:5432/xyz</property>
<property name="hibernate.connection.username">postgres</property>
<property name="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</property>
<property name="show_sql">true</property>
<property name="hbm2ddl.auto">create</property>
<mapping class="ManyToOne_OneToManyMappingWithJoinTable.Person" />
<mapping class="ManyToOne_OneToManyMappingWithJoinTable.Address" />
</session-factory>
</hibernate-configuration>
the persistence logic-
SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
Session session = sessionFactory.openSession();
session.beginTransaction();
Person person1 = new Person();
person1.setName("Shahnaz Parveen");
person1.setDesignation("HouseWife");
Address address1 = new Address();
address1.setHouseNo(18);
address1.setStreetNo('E');
address1.setPincode(250002);
address1.setCity("Meerut");
address1.setState("UP");
address1.setCountry("INDIA");
address1.setPerson(person1);
Address address2 = new Address();
address2.setHouseNo(84);
address2.setStreetNo('1');
address2.setPincode(250002);
address2.setCity("Meerut");
address2.setState("UP");
address2.setCountry("INDIA");
address1.setPerson(person1);
person1.getAddSet().add(address1);
person1.getAddSet().add(address2);
session.save(address1);
session.save(address2);
session.save(person1);
session.getTransaction().commit();
session.close();
I am getting -
Jan 07, 2017 9:47:35 PM org.hibernate.action.internal.UnresolvedEntityInsertActions logCannotResolveNonNullableTransientDependencies
WARN: HHH000437: Attempting to save one or more entities that have a non-nullable association with an unsaved transient entity. The unsaved transient entity must be saved in an operation prior to saving these dependent entities.
Unsaved transient entity: ([ManyToOne_OneToManyMappingWithJoinTable.Person#0])
Dependent entities: ([[ManyToOne_OneToManyMappingWithJoinTable.Address#1]])
Non-nullable association(s): ([ManyToOne_OneToManyMappingWithJoinTable.Address.person])
Exception in thread "main" org.hibernate.TransientPropertyValueException: Not-null property references a transient value - transient instance must be saved beforeQuery current operation : ManyToOne_OneToManyMappingWithJoinTable.Address.person -> ManyToOne_OneToManyMappingWithJoinTable.Person
at org.hibernate.action.internal.UnresolvedEntityInsertActions.checkNoUnresolvedActionsAfterOperation(UnresolvedEntityInsertActions.java:122)
at org.hibernate.engine.spi.ActionQueue.checkNoUnresolvedActionsAfterOperation(ActionQueue.java:418)
at org.hibernate.internal.SessionImpl.checkNoUnresolvedActionsAfterOperation(SessionImpl.java:621)
at org.hibernate.internal.SessionImpl.fireSave(SessionImpl.java:684)
at org.hibernate.internal.SessionImpl.save(SessionImpl.java:674)
at org.hibernate.internal.SessionImpl.save(SessionImpl.java:669)
at ManyToOne_OneToManyMappingWithJoinTable.ManyToOne_OneToManyMappingWithJoinTableImpl.main(ManyToOne_OneToManyMappingWithJoinTableImpl.java:40)
It works perfect with hbms.
Please suggest.
Thanks Vlad and Neil, it works but there is a problem described below-
This is the structure which gets created with HBMs. Hence the same must be with Annotations.
CREATE TABLE person_address
(
addressid integer NOT NULL,
personid integer NOT NULL,
CONSTRAINT person_address_pkey PRIMARY KEY (addressid , personid ),
CONSTRAINT fkkpp6mysmnyiywx3q33yxr1gbe FOREIGN KEY (personid )
REFERENCES person (person_id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT fkrpk0jx2y558su288tx9kd5cs6 FOREIGN KEY (addressid )
REFERENCES address (address_id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)
the moment I do -
#OneToMany(cascade = CascadeType.ALL, mappedBy = "person")
private Set<Address> addSet = new HashSet<Address>();
the join table structure is-
CREATE TABLE personaddress
(
personid integer,
addressid integer NOT NULL,
CONSTRAINT personaddress_pkey PRIMARY KEY (addressid),
CONSTRAINT fkfd5pm843bldj10y5kxwo37xge FOREIGN KEY (addressid)
REFERENCES address (addressidentity) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT fkjuwlthwsi53bpf902nnl6snxh FOREIGN KEY (personid)
REFERENCES person (personid) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)
You see that the primary key is NOT a combination of addressid and personid as in HBMs. Please suggest.
You need to add a cascade on the one-to-many side:
#OneToMany(cascade = CascadeType.ALL)
Then, change the #ManyToOne side to:
#ManyToOne
#JoinTable(name="PersonAddress",
joinColumns=#JoinColumn(name="addressId"),
inverseJoinColumns=#JoinColumn(name="personId")
)
private Person person;
and the #OneToMany side to:
#OneToMany(cascade = CascadeType.ALL, mappedBy = "person")
private Set<Address> addSet = new HashSet<Address>();
To address the composite-key requirement as indicated by the question update, try mapping the join table (e.g. personaddress) as an entity, and use composite identifiers.

One object from two tables

I have two tables and want to map them to one object with Hibernate.
The reason for both tables is in the past and I wont change the frontend, which access data like this.
I have Table Event (Event_ID, Preview, img) and Event_Details (ID, Event_ID, content).
I prepare one class in Java:
public class Event {
private int event_ID;
private String preview;
private String img;
private String content;
//Getter and Setter
}
and following XML mapping file:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 16.03.2016 20:33:10 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping>
<class name="de.data.events.Event" table="ev1_event">
<id name="id" type="int">
<column name="Event_ID" />
<generator class="assigned" />
</id>
<property name="preview" type="java.lang.String">
<column name="ev1_preview" />
</property>
<property name="img" type="java.lang.String">
<column name="ev1_img" />
</property>
</class>
<class name="de.data.events.Event" table="pb1_event">
<id name="id" type="int">
<column name="id" />
<generator class="assigned" />
</id>
//some properties
</class>
The part, where I have to join table1 to table2 is missing. But I didn´t found a way to fix my problem.
First, you'd have your Hibernate entities. Yours are Event and EventDetail, but for fun, let's go with Person and Address in this example. The key here is that you need a one-to-one or many-to-one relationship between your tables. Otherwise, your resultset will come out weird (more on that later).
#Entity
#Table(name = "PERSON")
public class Person {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "PERSON_ID")
public Integer id;
#Column(name = "NAME")
public String name;
#Column(name = "HOME_ADDRESS_ID")
public Integer homeAddressId;
#Column(name = "TEMP_ADDRESS_ID")
public Integer tempAddressId;
// . . . other fields,getters,setters
}
#Entity
#Table(name = "ADDRESS")
public class Address {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "ADDRESS_ID")
public Integer id;
#Column(name = "STREET")
public String street;
#Column(name = "CITY")
public String city;
// . . . other fields,getters,setters
}
Then you'd have your target FlatObject POJO with the a constructor that will build it appropriately:
public class FlatObject {
public final String name;
public final String homeStreet;
public final String homeCity;
public final String tempStreet;
public final String tempCity;
public FlatEntity(String name, String homeStreet, String homeCity, String tempStreet, String tempCity) {
this.name = name;
this.homeStreet = homeStreet;
this.homeCity = homeCity;
this.tempStreet = tempStreet;
this.tempCity = tempCity;
}
// . . . other fields,getters
}
Finally, you'd leverage those objects with a Hibernate HQL SELECT where you join Person and Address and use their fields to construct a new FlatEntity:
SELECT new FlatEntity(p.name, ha.homeStreet, ha.homeCity, ta.tempStreet, ta.tempCity)
FROM
Person p, Address ha, Address ta
WHERE
p.homeAddressId = ha.id
and p.tempAddressId = ta.id
As you can see, the HQL statment will join Person to Address twice: once for the home address and once for the temp address.
The same will hold true in your case. So in your case, if you're joining Event e, EventDetail ed WHERE e.id = ed.eventId, just be sure there's only one detail row per Event. Otherwise you'll get multiple rows when you have more than one details or you'll drop rows (because of the inner join) when an event has no details.

One to one relationship select query fetches data once first time only

I'm trying to apply one to one relationship between two entities
first entity:
Video and OrganzationVideo every OrganizationVideo has one video entity
So I did the following
first organization_video table
CREATE TABLE `organization_video` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
video table
CREATE TABLE `video` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`title` varchar(100) DEFAULT NULL,
// rest of table contents
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
then I added constraint in organization_video table
CONSTRAINT `FK_organization_video` FOREIGN KEY (`id`) REFERENCES `video` (`id`)
Then generated entities
Video.java
#Entity
#Table(name = "video")
public class Video extends Persistable<Long> {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "id")
private Long id;
#OneToOne(cascade = CascadeType.ALL, mappedBy = "video")
private OrganizationVideo organizationVideo;
\\ rest of video contetns
}
OrganizationVideo.java
#Entity
#Table(name = "organization_video")
public class OrganizationVideo extends Persistable<Long> {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "id")
private Long id;
#JoinColumn(name = "id", referencedColumnName = "id")
#OneToOne(optional = false)
private Video video;
\\ rest of organziation video contents
}
persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="Default_Persistence_Unit" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<non-jta-data-source>jdbc/defaultDataSource</non-jta-data-source>
<properties>
<property name="hibernate.transaction.auto_close_session" value="false"/>
<property name="hibernate.max_fetch_depth" value="0"/>
<property name="hibernate.connection.release_mode" value="auto"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
<property name="hibernate.cglib.use_reflection_optimizer" value="true"/>
</properties>
</persistence-unit>
</persistence>
everything worked perfectly when persisting objects
the issue is with the fetching query
StringBuilder queryStr = new StringBuilder("select v from Video v where v.organizationVideo is null");
Query query = getEntityManager().createQuery(queryStr.toString());
return query.getResultList();
The weird behavior is that this query fetches data once then doesn't fetch any data tried to use #PrimaryKeyJoinColumn and changed id generation type with no luck but indeed there is something wrong it's strange to see data once first time when I tried to remove is null from query it fetches data but with null value assigned to OrganizationVideo then why the query doesn't work except at first time.
You will have to check the SQL that is generated for the query, but I'm guessing that since the ID is the foreign key and it is autogenerated, inserting entities causes problems with your query. Try fixing your model first:
Either the OrganizationVideo ID needs to be set by the video relationship (if using JPA 2.0):
#Entity
#Table(name = "organization_video")
public class OrganizationVideo extends Persistable<Long> {
#Id
#JoinColumn(name = "id", referencedColumnName = "id")
#OneToOne(optional = false)
private Video video;
\\ rest of organziation video contents
}
That, or you make one of the ID mappings within OrganizationVideo insertable=false, updatable=false. if you do this, then you must set the other fields with in OrganizationVideo within the application yourself, and only after the Video instance has an ID value assigned. Since you are using identity, this means you would have to persist the vidoe, flush, and then use that value within the OrganizationVideo before it can be persisted.
It would be easier for your model if you could just add a foreign key to the OrganizationVideo table and use that to reference the Video ID.

Repeated column in mapping for entity (should be mapped with insert="false" update="false") [duplicate]

There is a mapping exception for a particular entity.
Cant figure out from where the problem is arising.
I checked all the mappings 3 times from start to end.
Still i am getting a Mapping Exception.
Email to employee is mapped only once.
but still it is reporting the error repeated mapping
Error is:
Caused by: org.hibernate.MappingException: Repeated column in mapping for entity: com.cluster.entity.Email column: EMPLOYEE_ID (should be mapped with insert="false" update="false")
at org.hibernate.mapping.PersistentClass.checkColumnDuplication(PersistentClass.java:680)
at org.hibernate.mapping.PersistentClass.checkPropertyColumnDuplication(PersistentClass.java:702)
at org.hibernate.mapping.PersistentClass.checkColumnDuplication(PersistentClass.java:724)
at org.hibernate.mapping.PersistentClass.validate(PersistentClass.java:477)
at org.hibernate.mapping.RootClass.validate(RootClass.java:268)
at org.hibernate.cfg.Configuration.validate(Configuration.java:1287)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1729)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1775)
at com.cluster.util.HibernateUtil.<clinit>(HibernateUtil.java:16)
... 1 more
Email Pojo
package com.cluster.entity;
public class Email {
private int intEmailID;
private String strEmailName;
//many to one
private EmailType emailType;
//many to one
private Employee employee;
public int getIntEmailID() {
return intEmailID;
}
public void setIntEmailID(int intEmailID) {
this.intEmailID = intEmailID;
}
public String getStrEmailName() {
return strEmailName;
}
public void setStrEmailName(String strEmailName) {
this.strEmailName = strEmailName;
}
public EmailType getEmailType() {
return emailType;
}
public void setEmailType(EmailType emailType) {
this.emailType = emailType;
}
public Employee getEmployee() {
return employee;
}
public void setEmployee(Employee employee) {
this.employee = employee;
}
}
email.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
'-//Hibernate/Hibernate Mapping DTD 3.0//EN'
'http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd'>
<hibernate-mapping package="com.cluster.entity" >
<class name="Email" table="EMAIL">
<id name="intEmailID" column="EMAIL_ID">
<generator class="sequence">
<param name="sequence">EMAIL_ID_SEQ</param>
</generator>
</id>
<property name="strEmailName" column = "EMAIL_NAME"/>
<many-to-one name="employee" column="EMPLOYEE_ID" not-null = "true" class = "Employee"/>
<many-to-one name="emailType" column="EMAIL_TYPE_ID" not-null = "true" class = "EmailType"/>
</class>
</hibernate-mapping>
Related Script
CREATE TABLE EMPLOYEE
(
EMPLOYEE_ID NUMBER NOT NULL,
FIRSTNAME VARCHAR2(20 BYTE) NOT NULL,
LASTNAME VARCHAR2(20 BYTE) NOT NULL,
DATE_OF_BIRTH VARCHAR2(20 BYTE) NOT NULL,
SALARY VARCHAR2(10 BYTE) NOT NULL,
DEPARTMENT_ID NUMBER NOT NULL
);
CREATE TABLE EMAIL
(
EMAIL_ID NUMBER NOT NULL,
EMAIL_NAME VARCHAR2(40 BYTE) NOT NULL,
EMPLOYEE_ID NUMBER NOT NULL,
EMAIL_TYPE_ID NUMBER NOT NULL
);
CREATE TABLE EMAIL_TYPE
(
EMAIL_TYPE_ID NUMBER NOT NULL,
EMAIL_TYPE_NAME VARCHAR2(40 BYTE) NOT NULL
);
ALTER TABLE EMPLOYEE ADD
(
CONSTRAINT PK_EMPLOYEE_ID
PRIMARY KEY (EMPLOYEE_ID)
);
ALTER TABLE EMAIL_TYPE ADD
(
CONSTRAINT PK_EMAIL_TYPE_ID
PRIMARY KEY (EMAIL_TYPE_ID)
);
ALTER TABLE EMAIL ADD
(
CONSTRAINT PK_EMAIL_ID
PRIMARY KEY (EMAIL_ID)
);
ALTER TABLE EMAIL ADD
(
CONSTRAINT FK_EMAIL_EMPLOYEE_ID
FOREIGN KEY (EMPLOYEE_ID)
REFERENCES EMPLOYEE (EMPLOYEE_ID)
);
ALTER TABLE EMAIL ADD
(
CONSTRAINT FK_EMAIL_EMAIL_TYPE_ID
FOREIGN KEY (EMAIL_TYPE_ID)
REFERENCES EMAIL_TYPE (EMAIL_TYPE_ID)
);
Email to employee is mapped only once.
but still it is reporting the error repeated mapping
have you set the collection in Employee as inverse?
<bag name="emails" inverse="true">
<key column="EMPLOYEE_ID" not-null="true">
...
</bag>
For those who are using annotations to solve this, the classes should look like this:
#Entity
public class Email {
#Id
#GeneratedValue(strategy=GenerationType.SEQUENCE)
private int intEmailID;
#Column(insertable = false, updatable = false)
private int employeeId;
#ManyToOne
private EmailType emailType;
#ManyToOne
#JoinColumn(name="employeeId")
private Employee employee;
// Getters and Setter
}
#Entity
public class Employee {
#Id
private int id;
#OneToMany(cascade = {CascadeType.ALL}, mappedBy="employeeId")
#PrimaryKeyJoinColumn
private List<Email> emailList;
public void setEmailList(List<Email> emailList) {
this.emailList = emailList
}
public List<Email> getEmailList() {
return emailList;
}
// Rest of getters and setters
}
I think you have mapped Employee to Email using oneToMany relation. If yes its nothing wrong but you have to make sure you can insert and update only in one direction
should be mapped with insert="false" update="false" in Employee

Categories

Resources