I have an employee table with employee_id and supervisor_employee_id columns. The supervisor is also a record in the table.
The mapping object looks something like:
The DAO looks something like (extraneus code removed):
The persistence file is:
And the context configuration contains:
The employee objects get loaded fine. But instead of getting a supervisor or direct report object... those objects come back with nulls in all their values - if I use lazy loading, even when I touch the records inside of the transaction. If I try to use eager fetching... I get javax.persistence.EntityNotFoundException: Unable to find packageName.Employee with id NULL even though I verified that the supervisor_employee_id value is NOT null and further, it has the correct value for employee_id in the supervisor's employee record.
What is curious is that I had a virtually identical set of code in another app (the only difference where the database column names)... and that one never had any problems.
Where did I go wrong?
---
Something else that I noticed... the employee_id and supervisor_employee_id columns are nvarchar, not int. This was never a problem in the previous app, but I saw that it is now complaining that an Identity column should be an int. How would I modify the annotations for employeeId so that the column is still treated as the primary key (and supervisor and direct reports map back to it) while still being treated as String/nvarchar?
The mapping object looks something like:
Code:
@Entity
@Table(name="employee")
public class Employee implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name="employee_id")
private String employeeId;
@ManyToOne(/*fetch=FetchType.LAZY*/)
@JoinColumn(name="supervisor_employee_id", nullable=true, insertable=false, updatable=false)
private Employee supervisor;
@OneToMany(mappedBy="supervisor"/*, fetch=FetchType.LAZY*/)
private Set<Employee> employees = new HashSet<Employee>(0); // direct reports
}
Code:
@Repository
public class EmployeeDaoImpl implements EmployeeDao {
@PersistenceContext(unitName="myPersistenceUnit")
private EntityManager em;
@Override
@Transactional
public List<Employee> findEmployeesForName(...snip...) {
TypedQuery<Employee> query = em.createQuery(sql, Employee.class);
emps = query.getResultList();
... code here to touch every supervisor/directReportEmployee for each relevant Employee object returned, so that I can use lazy fetching...
return emps;
}
}
Code:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.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_1_0.xsd">
<!-- SPRING version -->
<persistence-unit name="kronosUnit" transaction-type="RESOURCE_LOCAL">
<class>net.cndc.kronos.db.jpa.KronosEmployee</class>
<class>net.cndc.kronos.db.jpa.KronosCeFacilityRegionXref</class>
</persistence-unit>
</persistence>
Code:
<ctx:annotation-config />
<ctx:component-scan base-package="packageForJpaObjects" />
<ctx:component-scan base-package="packageForDao" />
<bean id="employeeDao" class="packageForDao.EmployeeDaoImpl" />
<bean id="myEntityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceXmlLocation" value="classpath*:persistence-mine.xml"/>
<property name="dataSource" ref="myDataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="databasePlatform" value="org.hibernate.dialect.SQLServerDialect"/>
<property name="showSql" value="false" />
<property name="generateDdl" value="false" />
</bean>
</property>
</bean>
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
<tx:annotation-driven transaction-manager="myTransactionManager" proxy-target-class="false"/>
<bean id="myTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="myEntityManagerFactory" />
</bean>
What is curious is that I had a virtually identical set of code in another app (the only difference where the database column names)... and that one never had any problems.
Where did I go wrong?
---
Something else that I noticed... the employee_id and supervisor_employee_id columns are nvarchar, not int. This was never a problem in the previous app, but I saw that it is now complaining that an Identity column should be an int. How would I modify the annotations for employeeId so that the column is still treated as the primary key (and supervisor and direct reports map back to it) while still being treated as String/nvarchar?