somebody
somebody

Reputation: 1107

How to use OneToMany?

I want to link 2 entity:

@Entity
@Table(name = "company")
public class Company {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;

@Column(nullable = false, name = "company_name")
private String companyName;

@OneToMany(mappedBy = "company", cascade = CascadeType.ALL)
private List<Department> departments;

public Company(){
    departments = new ArrayList<Department>();
}

// setters and getters
}

and

@Entity
@Table(name = "department")
public class Department {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;

@Column(nullable = false, name = "department_name")
private String departmentName;

@ManyToOne
@JoinColumn(name = "company_id", nullable = false)
private Company company;

public Department(){}

// setters and getters
}

DAO class:

@Service
public class CompanyDAOImpl implements CompanyDAO {

@Autowired
private SessionFactory sessionFactory;

@Override
public void createCompany(Company company) {
    sessionFactory.getCurrentSession().save(company);
}
}

And Service class:

@Service
public class CompanyServiceImpl implements CompanyService {

@Autowired
private CompanyDAO companyDAO;

@Override
@Transactional
public List readCompany() {
    return  companyDAO.readCompany();
}

@Override
@Transactional
public void createCompany(Company company) {
    companyDAO.createCompany(company);
}
}

When I want to write to database:

public class Main {
public static void main(String[] args) {

    ApplicationContext ctx =
            new ClassPathXmlApplicationContext("spring.config.xml");
    CompanyService companyService = (CompanyService) ctx.getBean("companyServiceImpl");
    companyService.readCompany();
    Company company = new Company();
    company.setCompanyName("test1");
    companyService.createCompany(company);
}
}

I have so many exceptions:

Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error 
creating bean with name 'companyDAOImpl': Injection of autowired dependencies failed; nested
exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: 
private org.hibernate.SessionFactory com.itechart.dao.impl.CompanyDAOImpl.sessionFactory; nested
exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with
name 'sessionFactory' defined in class path resource [spring.config.xml]: Invocation of init
method failed; nested exception is java.lang.NoSuchMethodError:
javax.persistence.OneToMany.orphanRemoval()Z

So I have 2 config xml file. Hibernate

<!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
    <mapping class="model.Company" />
    <mapping class="model.Department" />
</session-factory>
</hibernate-configuration>

And Spring:

<?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:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd ">

<context:component-scan base-package="dao.impl" />
<context:component-scan base-package="service.impl" />

<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="configLocation">
        <value>classpath:hibernate.config.xml</value>
    </property>
    <property name="packagesToScan" value="dao.impl"/>
</bean>

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    <property name="url" value="jdbc:mysql://localhost:3306/employee_service" />
    <property name="username" value="root" />
    <property name="password" value="root" />
</bean>

<bean id="transactionManager"   class="org.springframework.orm.hibernate4.HibernateTransactionManager">
    <property name="sessionFactory"  ref="sessionFactory" />
</bean>

<tx:annotation-driven transaction-manager="transactionManager" />

</beans>

What am I doing wrong? How to link 2 entity use hibernate? pom.xml

<?xml version="1.0" encoding="UTF-8"?>

http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0

<groupId>EmployeeService</groupId>
<artifactId>EmployeeService</artifactId>
<version>1.0-SNAPSHOT</version>

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <!-- Define Spring version as a constant -->
    <spring.version>3.2.0.RELEASE</spring.version>
</properties>

<dependencies>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>${spring.version}</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring.version}</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-tx</artifactId>
        <version>${spring.version}</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-orm</artifactId>
        <version>${spring.version}</version>
    </dependency>

    <dependency>
        <groupId>commons-dbcp</groupId>
        <artifactId>commons-dbcp</artifactId>
        <version>1.2.2</version>
    </dependency>

    <dependency>
        <groupId>javax.persistence</groupId>
        <artifactId>persistence-api</artifactId>
        <version>1.0</version>
    </dependency>

    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-core</artifactId>
        <version>4.1.9.Final</version>
    </dependency>

    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.31</version>
    </dependency>
</dependencies>

</project>

Upvotes: 0

Views: 376

Answers (2)

nityan
nityan

Reputation: 316

I've run into this problem before when using Hibernate and Spring, the problem was that when I tried to use ctx.getBean(MyClass.class) or ctx.getBean("myClass") I would get the same error. It was because my DAO class implemented an interface, and that was causing the problem.

This is My DAO class that my other DAO classes inherit from.

Here is my setup using Spring MVC and Hibernate

public abstract class GenericDaoImpl<T, ID extends Serializable> {

private final Class<T> clazz;

@PersistenceContext(unitName = "persistenceUnit")
protected EntityManager entityManager;

protected GenericDaoImpl(Class<T> clazz) {
    this.clazz = clazz;
}

public List<T> all() {
    return entityManager.createQuery("FROM " + clazz.getName() + " a").getResultList();
}

@Transactional
public synchronized void delete(int id) {
    T entity = findById(id);
    entityManager.remove(entityManager.contains(entity) ? entity : entityManager.merge(entity));
}

@Transactional
public synchronized void delete(T entity) {
    entityManager.remove(entityManager.contains(entity) ? entity : entityManager.merge(entity));
}

public T findById(int id) {
    return entityManager.find(clazz, id);
}

@Transactional
public T findSingleResultOrNull(Query query) {
    query.setMaxResults(1);
    List data = query.getResultList();

    if (data.size() == 1) {
        return (T) data.get(0);
    } else {
        return null;
    }
}

@Transactional
public synchronized void save(T entity) {
    entityManager.persist(entityManager.contains(entity) ? entity : entityManager.merge(entity));
}

@Transactional
public synchronized void update(T entity) {
    entityManager.merge(entity);
}

protected EntityManager getEntityManager() {
    return entityManager;
}

protected void setEntityManager(EntityManager entityManager) {
    this.entityManager = entityManager;
}

}

One of my DAO classes

A few things to notice.

  1. My GenericDao I'm inheriting from has 2 parameters for the class
  2. The object my DAO class in managing
  3. The type of the primary key of my object

    @Repository
    public class CompanyDao extends GenericDaoImpl<Company, Integer> {
    
    public CompanyDao () {
        super(Company.class);
    }
    
    /**
     * Finds a Company based on name.
     *
     * @param name The name of the company.
     * @return Returns a list of Companies.
     */
    @Transactional
    public List<Company> findByName(String name) {
        Query query = entityManager.createQuery("FROM Comapny c WHERE c.name = :name");
    
        query.setParameter("name", name);
    
        return query.getResultList();
    }
    

    }

Then I have my object itself

@Entity
@Table(name = "company")
public class Company implements java.io.Serializable {

    @Id
    @Column(name = "id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @Column(name = "name")
    private String name;


// getters and setters for other properties......
}

Then I have my Spring Initializer class

public class SpringUtil {

    private static final ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring_config.xml");

    public static <T extends GenericDaoImpl> T newInstance(Class<T> clazz) {
        return (T) applicationContext.getBean(clazz);
    }
}

Then I have my spring_config.xml

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
    <property name="persistenceUnitName" value="persistenceUnit"/>
</bean>

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>

<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" autowire="byName"/>

<tx:annotation-driven />
<context:component-scan base-package="org.mycompany.system.dao" />

Then my 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="persistenceUnit" transaction-type="RESOURCE_LOCAL">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <properties>
      <property name="hibernate.archive.autodetection" value="class"/>
      <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
      <property name="hibernate.connection.url" value="YOUR_DATABASE_CONNECTION_HERE"/>
      <property name="hibernate.connection.username" value="YOUR_USERNAME_HERE"/>
      <property name="hibernate.connection.password" value="YOUR_PASSWORD_HERE"/>
      <property name="hibernate.show_sql" value="false"/>
      <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
      <property name="hibernate.hbm2ddl.auto" value="update"/>
    </properties>
  </persistence-unit>
</persistence>

Hope this helps

Upvotes: 0

David Levesque
David Levesque

Reputation: 22451

The following error indicates that you probably have a conflict with jar versions:

java.lang.NoSuchMethodError: javax.persistence.OneToMany.orphanRemoval()Z

The orphanRemoval attributes requires JPA 2.x. My guess is that you did not include the JPA 2.x jar in your deployment, or you included it along with an older, conflicting version.

Try adding the JPA 2.x jar to the classpath of your deployed app. For Hibernate, the jar should be called something like hibernate-jpa-2.x-api-1.0.x.Final.jar. Also make sure that no older version is included.

Upvotes: 1

Related Questions