Spring JPA Hibernate Oracle #OneToOne with Shared Primary Key fails on insert - foreign key violation - spring

I have 2 Entities that I am trying to set up using a #OneToOne relationship.
I am using Oracle 11g as the database and User Table has a generated ID via a sequence. This Id from the user table is the Primary Key and Foreign key in the UserProfile table.
So basically a User is mapped to 1 and only 1 User Profile and a User Profile maps back to only 1 User.
I have seeded data in my database and I can read User Object with a User Profile without problem. But when I try to insert a new User Object with a New UserProfile object in a transaction it fails with a Foreign Key Violation in my UserProfile table.
It seems to be a common problem out there with a #OneToOne with Shared primary key, but I can't see to find a answer that works. Can someone point me in the right direction?
I can see that the Id in USerProfile gets set correctly, just on the commit to the database it throws the violation. It almost seems like the UserProfile is being committed to the database before User. Is there a way to persist the User first without have to persist these objects separately?
Here are my entities:
package com.company.ca.domain;
import java.io.Serializable;
import java.util.Date;
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.OneToOne;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
#Entity
#Table(name="USERS")
#SequenceGenerator(name="USERS_SEQ", sequenceName="USERS_SEQ", allocationSize=1)
public class Users implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator="USERS_SEQ")
private Long id;
#Column(name="USERNAME", unique=true)
private String email;
private String password;
#Column(name="CREATED_DATE", insertable=false, updatable=false)
private Date createdDate;
#Column(name="CREATED_BY")
private String createdBy;
#Column(name="LAST_UPDATED_DATE")
private Date lastUpdatedDate;
#Column(name="LAST_UPDATED_BY")
private String lastUpdatedBy;
private int enabled;
#OneToOne(cascade = CascadeType.ALL, mappedBy="user")
#PrimaryKeyJoinColumn(name="ID", referencedColumnName="USER_ID")
private UsersProfile usersProfile;
public Users() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getEnabled() {
return enabled;
}
public void setEnabled(int enabled) {
this.enabled = enabled;
}
public Date getCreatedDate() {
return createdDate;
}
public void setCreatedDate(Date createdDate) {
this.createdDate = createdDate;
}
public String getCreatedBy() {
return createdBy;
}
public void setCreatedBy(String createdBy) {
this.createdBy = createdBy;
}
public Date getLastUpdatedDate() {
return lastUpdatedDate;
}
public void setLastUpdatedDate(Date lastUpdatedDate) {
this.lastUpdatedDate = lastUpdatedDate;
}
public String getLastUpdatedBy() {
return lastUpdatedBy;
}
public void setLastUpdatedBy(String lastUpdatedBy) {
this.lastUpdatedBy = lastUpdatedBy;
}
public UsersProfile getUsersProfile() {
return usersProfile;
}
public void setUsersProfile(UsersProfile usersProfile) {
this.usersProfile = usersProfile;
}
}
package com.company.ca.domain;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;
#Entity
#Table(name="USERS_PROFILE")
#org.hibernate.annotations.GenericGenerator(name="user-primarykey", strategy="foreign",
parameters={#org.hibernate.annotations.Parameter(name="property", value="user")
})
public class UsersProfile implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(generator = "user-primarykey")
#Column(name = "USER_ID")
private Long userId;
#OneToOne
#PrimaryKeyJoinColumn(name="USER_ID", referencedColumnName="ID")
private Users user;
#Column(name="FIRST_NAME")
private String firstName;
#Column(name="LAST_NAME")
private String lastName;
#Column(name="PHONE_NUMBER")
private String phoneNumber;
#Column(name="CREATED_DATE", insertable=false, updatable=false)
private Date createdDate;
#Column(name="CREATED_BY")
private String createdBy;
#Column(name="LAST_UPDATED_DATE")
private Date lastUpdatedDate;
#Column(name="LAST_UPDATED_BY")
private String lastUpdatedBy;
public UsersProfile() {
super();
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public Users getUser() {
return user;
}
public void setUser(Users user) {
this.user = user;
}
public Date getCreatedDate() {
return createdDate;
}
public void setCreatedDate(Date createdDate) {
this.createdDate = createdDate;
}
public String getCreatedBy() {
return createdBy;
}
public void setCreatedBy(String createdBy) {
this.createdBy = createdBy;
}
public Date getLastUpdatedDate() {
return lastUpdatedDate;
}
public void setLastUpdatedDate(Date lastUpdatedDate) {
this.lastUpdatedDate = lastUpdatedDate;
}
public String getLastUpdatedBy() {
return lastUpdatedBy;
}
public void setLastUpdatedBy(String lastUpdatedBy) {
this.lastUpdatedBy = lastUpdatedBy;
}
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
}
Here is my DAO and JUnit:
package com.company.ca.persistence;
import org.springframework.data.repository.CrudRepository;
import com.company.ca.domain.Users;
public interface UserDAO extends CrudRepository<Users, Long> {
}
package com.company.ca.persistence.test;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.transaction.TransactionConfiguration;
import com.company.ca.domain.Users;
import com.company.ca.domain.UsersProfile;
import com.company.ca.persistence.UserDAO;
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration
(
locations = {
"classpath*:/spring-persistence.xml"
}
)
#TransactionConfiguration(defaultRollback=false)
#Service
public class UserDAOImplTest extends AbstractTransactionalJUnit4SpringContextTests {
protected final Log logger = LogFactory.getLog(getClass());
#Autowired
UserDAO userDAO;
#Test
public void testFindUser() {
Users testUser = userDAO.findOne(new Long(2));
Assert.assertNotNull("User Object should not be null", testUser);
Assert.assertNotNull("User Profile should not be null", testUser.getUsersProfile());
}
#Test
//#Transactional(propagation=Propagation.MANDATORY)
public void testCreateUser() {
String email = "test.user2#testCompany.com";
String firstName = "Test 2";
String lastName = "User";
String phoneNumber = "1234567890";
String createdBy = "IT_SYSTEM#system.com";
String password = "password";
// now lets create the user
Users user = new Users();
user.setCreatedBy(createdBy);
user.setPassword(password);
user.setEmail(email);
user.setEnabled(0);
UsersProfile userProfile = new UsersProfile();
userProfile.setCreatedBy(createdBy);
userProfile.setFirstName(firstName);
userProfile.setLastName(lastName);
userProfile.setPhoneNumber(phoneNumber);
userProfile.setUser(user);
user.setUsersProfile(userProfile);
userDAO.save(user);
Assert.assertNotNull("UserId was not returned...", user.getId());
Assert.assertEquals("Expected email not set correctly", email,
user.getEmail());
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/jdbc
http://www.springframework.org/schema/jdbc/spring-jdbc-3.1.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
<context:annotation-config />
<context:property-placeholder location="classpath*:/persistence.properties" />
<jpa:repositories base-package="com.company.ca.persistence"/>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${database.driver}" />
<property name="url" value="${database.url}" />
<property name="username" value="${database.username}" />
<property name="password" value="${database.password}" />
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="com.company.ca.domain" />
<property name="persistenceProviderClass" value="org.hibernate.ejb.HibernatePersistence" />
<property name="loadTimeWeaver">
<bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" />
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
<prop key="hibernate.max_fetch_depth">5</prop>
<prop key="hibernate.jdbc.fetch_size">50</prop>
<prop key="hibernate.jdbc.batch_size">10</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
And here is my output:
10:28:13,400 DEBUG SQL:104 - select USERS_SEQ.nextval from dual
Hibernate: select USERS_SEQ.nextval from dual
10:28:13,500 DEBUG SQL:104 - insert into USERS (CREATED_BY, USERNAME, enabled, LAST_UPDATED_BY, LAST_UPDATED_DATE, password, id) values (?, ?, ?, ?, ?, ?, ?)
Hibernate: insert into USERS (CREATED_BY, USERNAME, enabled, LAST_UPDATED_BY, LAST_UPDATED_DATE, password, id) values (?, ?, ?, ?, ?, ?, ?)
10:28:13,501 TRACE BasicBinder:83 - binding parameter [1] as [VARCHAR] - VRS_SYSTEM#audatex.com
10:28:13,501 TRACE BasicBinder:83 - binding parameter [2] as [VARCHAR] - colin.moore3#audatex.com
10:28:13,502 TRACE BasicBinder:83 - binding parameter [3] as [INTEGER] - 0
10:28:13,502 TRACE BasicBinder:71 - binding parameter [4] as [VARCHAR] - <null>
10:28:13,504 TRACE BasicBinder:71 - binding parameter [5] as [TIMESTAMP] - <null>
10:28:13,505 TRACE BasicBinder:83 - binding parameter [6] as [VARCHAR] - test
10:28:13,505 TRACE BasicBinder:83 - binding parameter [7] as [BIGINT] - 117
10:28:13,577 DEBUG SQL:104 - insert into USERS_PROFILE (CREATED_BY, FIRST_NAME, LAST_NAME, LAST_UPDATED_BY, LAST_UPDATED_DATE, PHONE_NUMBER, USER_ID) values (?, ?, ?, ?, ?, ?, ?)
Hibernate: insert into USERS_PROFILE (CREATED_BY, FIRST_NAME, LAST_NAME, LAST_UPDATED_BY, LAST_UPDATED_DATE, PHONE_NUMBER, USER_ID) values (?, ?, ?, ?, ?, ?, ?)
10:28:13,579 TRACE BasicBinder:83 - binding parameter [1] as [VARCHAR] - VRS_SYSTEM#audatex.com
10:28:13,579 TRACE BasicBinder:83 - binding parameter [2] as [VARCHAR] - Colin
10:28:13,579 TRACE BasicBinder:83 - binding parameter [3] as [VARCHAR] - Moore
10:28:13,580 TRACE BasicBinder:71 - binding parameter [4] as [VARCHAR] - <null>
10:28:13,580 TRACE BasicBinder:71 - binding parameter [5] as [TIMESTAMP] - <null>
10:28:13,580 TRACE BasicBinder:83 - binding parameter [6] as [VARCHAR] - 4164983787
10:28:13,581 TRACE BasicBinder:83 - binding parameter [7] as [BIGINT] - 117
10:28:13,715 WARN SqlExceptionHelper:143 - SQL Error: 2291, SQLState: 23000
10:28:13,716 ERROR SqlExceptionHelper:144 - ORA-02291: integrity constraint (SYSTEM.FK_USER_ID) violated - parent key not found
10:28:13,716 WARN SqlExceptionHelper:143 - SQL Error: 2291, SQLState: 23000
10:28:13,716 ERROR SqlExceptionHelper:144 - ORA-02291: integrity constraint (SYSTEM.FK_USER_ID) violated - parent key not found
10:28:13,719 ERROR BatchingBatch:119 - HHH000315: Exception executing batch [ORA-02291: integrity constraint (SYSTEM.FK_USER_ID) violated - parent key not found

Your mapping is wrong. In a bidirectional asociation, one side is the owner of the association, and tells how the association is mapped. The other side is the inverse side, and just says "look at the other side for the mapping" using the mappedBy attribute.
See the documentation for an exemple:
#Entity
class UserProfile {
#Id Integer id;
#MapsId #OneToOne
#JoinColumn(name = "user_id")
User user;
}
#Entity
class Person {
#Id #GeneratedValue
Integer id;
#OneToOne(mappedBy = "user")
private UserProfile profile;
}

Related

Spring Boot -Hibernate 5 simple application initializing in 3 minutes

I am using Spring boot with Hibernate to connect with Oracle database. The application works fine but when I run the application with Dddl.auto flag set to update it takes 3 minutes just to initialize the entity manager. here are my model classes and cfg.xml.
Hibernate.cfg.xml
<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE hibernate-configuration SYSTEM
"classpath://org/hibernate/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">oracle.jdbc.OracleDriver</property>
<property name="hibernate.connection.url">jdbc:oracle:thin:#hhhh.cpckubosallr.ap-south-1.rds.amazonaws.com:1610:gghg</property>
<property name="hibernate.connection.username">DEMO</property>
<property name="hibernate.connection.password">ggggg#78GHTd</property>
<property name="hibernate.dialect">org.hibernate.dialect.Oracle12cDialect</property>
<property name="show_sql">true</property>
<property name="hibernate.connection.pool_size">5</property>
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
<property name="hbm2ddl.auto">update</property>
<mapping class ="student.mappings.model.Student" />
<mapping class ="student.mappings.model.Vehicle" />
<mapping class ="student.mappings.model.Subject" />
</session-factory>
</hibernate-configuration>
Model classes:
#Entity
#Table(name="STUDENT", schema="JAVACODE")
public class Student
{
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
#Column(name="name")
private String name;
#OneToOne(cascade=CascadeType.ALL)
#JoinColumn(name="vehicle_id")
private Vehicle vehicle;
#Override
public String toString() {
return "Student [id=" + id + ", name=" + name + ", vehicle=" + vehicle + ", subject=" + subject + "]";
}
public Vehicle getVehicle()
{
return vehicle;
}
public void setVehicle(Vehicle vehicle)
{
this.vehicle = vehicle;
}
#OneToMany(cascade=CascadeType.ALL)
#JoinColumn(name="subject_id")
private List<Subject> subject;
public List<Subject> getSubject()
{
return subject;
}
public void setSubject(List<Subject> subject)
{
this.subject = subject;
}
public Student(Long id, String name, Vehicle vehicle, List<Subject> subject)
{
super();
this.id = id;
this.name = name;
this.vehicle = vehicle;
this.subject = subject;
}
public Long getId()
{
return id;
}
public void setId(Long id)
{
this.id = id;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public Student()
{
super();
}
public Student(Long id, String name)
{
super();
this.id = id;
this.name = name;
}
public Student(Long id, String name, Vehicle vehicle) {
super();
this.id = id;
this.name = name;
this.vehicle = vehicle;
}
}
Application.java:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.PropertySource;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
#SpringBootApplication
#ComponentScan("student.mappings")
#EntityScan("student.mappings")
#PropertySource(value= {"classpath:application.properties"})
public class StudentMappingsTemplateClient
{
public static void main(String[] args) {
SpringApplication.run(StudentMappingsTemplateClient.class, args);
}
}

Is it really mandatory to give bean an id

I thought naming a bean with id is not mandatory before i get stuck here.
dispatcher-servlet.xml
<mvc:annotation-driven />
<context:annotation-config />
<context:component-scan
base-package="com.springMVC.*"></context:component-scan>
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/Views/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename">
<value>/WEB-INF/messagekeys</value>
</property>
</bean>
messagekeys.properties
NotEmpty.user1.name = UserName cannot be empty
Size.user1.name = Name should have a length between 6 and 16
Pattern.user1.name = Name should not contain numeric value
Min.user1.age = Age cannot be less than 12
Max.user1.age = Age cannot be more than 60
NotNull.user1.age = Please enter your age
NotEmpty.user1.email = email cannot be left blank
Email.user1.email = email is not valid
NotEmpty.user1.country = Enter valid country
User.java
package com.springMVC.model;
import javax.validation.constraints.Email;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
#Component
#Scope("request")
public class User {
#NotEmpty
#Size(min=6,max=16)
#Pattern(regexp = "[^0-9]+")
private String name;
#Min(value=12)
#Max(value=60)
#NotNull
private Integer age;
#NotEmpty
#Email
private String email;
#NotEmpty
private String country;
public void setName(String name) {
this.name = name;
}
public void setAge(Integer age) {
this.age = age;
}
public void setEmail(String email) {
this.email = email;
}
public void setCountry(String country) {
this.country = country;
}
public String getName() {
return name;
}
public Integer getAge() {
return age;
}
public String getEmail() {
return email;
}
public String getCountry() {
return country;
}
}
When i use the bean InternalResourceViewResolver without bean id, it works fine.
But when i use the bean ReloadableResourceBundleMessageSource without bean id, it doesn't render error messages from messages.properties
When i give ReloadableResourceBundleMessageSource bean an id, it works perfect.
So, my question is Is naming a bean with an id mandatory?
Thanks in advance :)
Yes for message resource
When an ApplicationContext is loaded, it automatically searches for a MessageSource bean defined in the context. The bean must have the name messageSource. If such a bean is found, all calls to the preceding methods are delegated to the message source. If no message source is found, the ApplicationContext attempts to find a parent containing a bean with the same name. If it does, it uses that bean as the MessageSource. If the ApplicationContext cannot find any source for messages, an empty DelegatingMessageSource is instantiated in order to be able to accept calls to the methods defined above.
check here documentation

Hibernate relationship code

Getting following error while executing the Hibernate program for a relationship:
Exception in thread "main" org.hibernate.MappingException: Could not determine type for: com.Employee.Department.Department, at table: Employee, for columns: [org.hibernate.mapping.Column(dept)]
The code is shown in below:
Employee.java: Contains the 1-M relationship
package com.Employee.Employee;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import com.Employee.Department.Department;
#Entity
#Table(name = "Employee_1toMany")
public class Employee {
#Id
#GeneratedValue
#Column(name = "EId")
private int emp_id;
#Column(name = "EName")
private String name;
private Department dept;
public int getEmp_id() {
return emp_id;
}
public void setEmp_id(int emp_id) {
this.emp_id = emp_id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#ManyToOne
#JoinColumn(name = "DepartmentID")
public Department getDept() {
return dept;
}
public void setDept(Department dept) {
this.dept = dept;
}
}
Department.java: Contains M to 1 relationship
package com.Employee.Department;
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.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import com.Employee.Employee.Employee;
#Entity
#Table(name = "Department_1toMany")
public class Department {
#Id
#GeneratedValue
#Column(name = "DId")
private int Dept_id;
#Column(name = "DName")
private String Dept_name;
private List<Employee> emp;
public int getDept_id() {
return Dept_id;
}
public void setDept_id(int dept_id) {
Dept_id = dept_id;
}
public String getDept_name() {
return Dept_name;
}
public void setDept_name(String dept_name) {
Dept_name = dept_name;
}
#OneToMany(targetEntity = Employee.class, mappedBy = "dept", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
public List<Employee> getEmp() {
return emp;
}
public void setEmp(List<Employee> emp) {
this.emp = emp;
}
}
MainClass.java:
package com.Employee.MainClass;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import com.Employee.Department.Department;
import com.Employee.Employee.Employee;
public class MainApp {
public static void main(String[] args) {
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Department dept = new Department();
dept.setDept_name("Modern College");
Employee emp1 = new Employee();
emp1.setName("Rakesh");
Employee emp2 = new Employee();
emp2.setName("Sagar");
emp1.setDept(dept);
emp2.setDept(dept);
session.save(dept);
session.save(emp1);
session.save(emp2);
tx.commit();
}
}
hibernate.cfg.xml: This is the configuration class
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration SYSTEM "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.username">root</property>
<property name="hibernate.connection.password">root</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost/EMP_PRACTISE</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
<property name="hibernate.hbm2ddl.auto">create</property>
<property name="hibernate.show_sql">true</property>
<mapping class="com.Employee.Department.Department"></mapping>
<mapping class="com.Employee.Employee.Employee"></mapping>
</session-factory>
</hibernate-configuration>
Exception in detail:
Exception in thread "main" org.hibernate.MappingException: Could not determine type for: com.Employee.Department.Department, at table: Employee, for columns: [org.hibernate.mapping.Column(dept)]
at org.hibernate.mapping.SimpleValue.getType(SimpleValue.java:455)
at org.hibernate.mapping.SimpleValue.isValid(SimpleValue.java:422)
at org.hibernate.mapping.Property.isValid(Property.java:226)
at org.hibernate.mapping.PersistentClass.validate(PersistentClass.java:597)
at org.hibernate.mapping.RootClass.validate(RootClass.java:265)
at org.hibernate.boot.internal.MetadataImpl.validate(MetadataImpl.java:329)
at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:451)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:710)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:726)
at com.Employee.MainClass.MainApp.main(MainApp.java:13)
I believe you cannot mix fields and getter methods annotations. Place them to corresponding fields.
Employee.java
#ManyToOne
#JoinColumn(name = "DepartmentID")
private Department dept;
// mapping annotation on the field
public Department getDept() {
return dept;
}
Department.java
#OneToMany(targetEntity = Employee.class, mappedBy = "dept", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private List<Employee> emp;
// mapping annotation on the field
public List<Employee> getEmp() {
return emp;
}

How to set Entity with Foreign key parent to children using with springs, gradle, appengine, jpa, datanucleaus.

I have two entities: Country (parent) is the hardcoded entity, another one is a Place entity. It is a child entity (states, districts, mandal, villages).
Code below presents the child class.
import javax.jdo.annotations.Index;
import javax.jdo.annotations.Persistent;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
#Entity
public class Places {
#Id
#GeneratedValue
private Long id;
#Index
private String place_Name;
private String placeType;
#Persistent
#ManyToOne
private Country country;
public Country getCountry() {
return country;
}
public String getPlace_Name() {
return place_Name;
}
public void setPlace_Name(String place_Name) {
this.place_Name = place_Name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public void setCountry(Country countryByName) {
this.country = countryByName;
}
public String getPlaceType() {
return placeType;
}
public void setPlaceType(String placeType) {
this.placeType = placeType;
}
}
Code below is parent entity (code).
package com.geeklabs.rss.domain;
import javax.jdo.annotations.Index;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
#Entity
public class Country {
#Id
#GeneratedValue
private Long id;
#Index
private String countryName;
private String countryCode;
public String getCountryName() {
return countryName;
}
public void setCountryName(String countryName) {
this.countryName = countryName;
}
public String getCountryCode() {
return countryCode;
}
public void setCountryCode(String countryCode) {
this.countryCode = countryCode;
}
public long getId() {
return id;
}
}
Below xml file is my persistence.xml
<?xml version="1.0" encoding="UTF-8" ?>
<persistence xmlns="http://java.sun.com/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_1_0.xsd" version="1.0">
<persistence-unit name="rss" transaction-type="RESOURCE_LOCAL">
<provider>org.datanucleus.api.jpa.PersistenceProviderImpl</provider>
<class>com.geeklabs.rss.domain.Country</class>
<class>com.geeklabs.rss.domain.Places</class>
<properties>
<property name="datanucleus.ConnectionURL" value="appengine"/>
<property name="datanucleus.NontransactionalRead" value="true"/>
<property name="datanucleus.NontransactionalWrite" value="true"/>
</properties>
</persistence-unit>
</persistence>
Using classes above I'm trying to assign parent id to child but I got exceptions.
How to assign the foreign key from parent to child using appengine, jpa, datanucleus, spring?

OPEN JPA find() could not retrieve the value of the entity from my Database

There is a weird scenario that I had encountered in my User log in program.
Insert the record.. Userid password etc.
Insert the record using merge();
Then close the IDE (Netbeans)
Open IDE Netbeans then start servers, start database connection.
Open the log in browser.
log in using the inserted record.
My program could not detect the record on the table.
When debugging, after the find() it would not populate my entity.. Maybe there is still another step to populate the entity?
LoginAction
package lotmovement.action;
import com.opensymphony.xwork2.ActionSupport;
import lotmovement.business.crud.RecordExistUserProfile;
import org.apache.commons.lang3.StringUtils;
public class LoginAction extends ActionSupport{
private String userName;
private RecordExistUserProfile recordExistUserProfile;
private String password;
#Override
public void validate(){
if(StringUtils.isEmpty(getUserName())){
addFieldError("userName","Username must not be blanks.");
}
else{
if(!recordExistUserProfile.checkrecordexist(getUserName())){
addFieldError("userName","Username don't exist.");
}
}
if(StringUtils.isEmpty(getPassword())){
addFieldError("password","Password must not be blanks.");
}
else{
if(!recordExistUserProfile.CheckPasswordCorrect(getUserName(), getPassword())){
addFieldError("userName","Password not correct");
}
}
}
public String execute(){
return SUCCESS;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public RecordExistUserProfile getRecordExistUserProfile() {
return recordExistUserProfile;
}
public void setRecordExistUserProfile(RecordExistUserProfile recordExistUserProfile) {
this.recordExistUserProfile = recordExistUserProfile;
}
}
Validator Program
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package lotmovement.business.crud;
import lotmovement.business.entity.UserProfile;
/**
*
* #author god-gavedmework
*/
public class RecordExistUserProfile {
private EntityStart entityStart;
private UserProfile userProfile;
public boolean checkrecordexist(String userId) {
entityStart.StartDbaseConnection();
entityStart.em.find(UserProfile.class, userId);
if (userId.equals(userProfile.getUserId())) {
return true;
} else {
return false;
}
}
public boolean CheckPasswordCorrect(String userId, String password) {
entityStart.StartDbaseConnection();
entityStart.em.find(UserProfile.class, userId);
if (password.equals(userProfile.getPassword())) {
return true;
} else {
return false; ---> It will step here.
}
}
public UserProfile getUserProfile() {
return userProfile;
}
public void setUserProfile(UserProfile userProfile) {
this.userProfile = userProfile;
}
public EntityStart getEntityStart() {
return entityStart;
}
public void setEntityStart(EntityStart entityStart) {
this.entityStart = entityStart;
}
}
Entity
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package lotmovement.business.entity;
import java.io.Serializable;
import javax.persistence.*;
/**
*
* #author god-gavedmework
*/
#Entity(name = "USERPROFILE") //Name of the entity
public class UserProfile implements Serializable{
#Id //signifies the primary key
#Column(name = "USER_ID", nullable = false,length = 20)
private String userId;
#Column(name = "PASSWORD", nullable = false,length = 20)
private String password;
#Column(name = "FIRST_NAME", nullable = false,length = 20)
private String firstName;
#Column(name = "LAST_NAME", nullable = false,length = 50)
private String lastName;
#Column(name = "SECURITY_LEVEL", nullable = false,length = 4)
private int securityLevel;
#Version
#Column(name = "LAST_UPDATED_TIME")
private java.sql.Timestamp updatedTime;
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public int getSecurityLevel() {
return securityLevel;
}
public void setSecurityLevel(int securityLevel) {
this.securityLevel = securityLevel;
}
public java.sql.Timestamp getUpdatedTime() {
return updatedTime;
}
public void setUpdatedTime(java.sql.Timestamp updatedTime) {
this.updatedTime = updatedTime;
}
}
*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package lotmovement.business.crud;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import lotmovement.business.entity.UserProfile;
import org.apache.openjpa.persistence.OpenJPAEntityManager;
import org.apache.openjpa.persistence.OpenJPAPersistence;
public class EntityStart {
EntityManagerFactory factory;
EntityManager em;
public void StartDbaseConnection()
{
factory = Persistence.createEntityManagerFactory("LotMovementPU");
em = factory.createEntityManager();
}
public void StartPopulateTransaction(Object entity){
EntityTransaction userTransaction = em.getTransaction();
userTransaction.begin();
em.merge(entity);
userTransaction.commit();
em.close();
}
public void CloseDbaseConnection(){
factory.close();
}
}
Using Trace as adviced, This is the log of the SQL
SELECT t0.LAST_UPDATED_TIME, t0.FIRST_NAME, t0.LAST_NAME, t0.PASSWORD, t0.SECURITY_LEVEL FROM USERPROFILE t0 WHERE t0.USER_ID = ? [params=(String) tok]
This is the record:
USER_ID FIRST_NAME LAST_NAME PASSWORD SECURITY_LEVEL LAST_UPDATED_TIME
tok 1 1 1 1 2012-12-13 08:46:48.802
Added Persistence.XML
<persistence version="2.0" xmlns="http://java.sun.com/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_0.xsd">
<persistence-unit name="LotMovementPU" transaction-type="RESOURCE_LOCAL">
<provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
<non-jta-data-source/>
<class>lotmovement.business.entity.UserProfile</class>
<properties>
<property name="openjpa.ConnectionURL" value="jdbc:derby://localhost:1527/LotMovementDBase"/>
<property name="openjpa.ConnectionDriverName" value="org.apache.derby.jdbc.ClientDriver"/>
<property name="openjpa.ConnectionUserName" value="toksis"/>
<property name="openjpa.ConnectionPassword" value="bitoytoksis"/>
<property name="openjpa.Log" value="SQL=TRACE"/>
<property name="openjpa.ConnectionFactoryProperties" value="PrintParameters=true" />
</properties>
</persistence-unit>
</persistence>
I discovered the root cause of the problem. It is on how I instantiate the class in Spring Plugin.
When I change the find() statement to below, it will now work.
UserProfile up = entityStart.em.find(UserProfile.class, "tok");
But how can i initialize this one using Spring? codes below dont work?
private UserProfile userProfile;
...... some codes here.
entityStart.em.find(UserProfile.class, userId);
..... getter setter
The Root cause of the problem.
entityStart.em.find(UserProfile.class, userId); --> it should be
userProfile = entityStart.em.find(UserProfile.class, userId);

Resources