简体   繁体   中英

Using @Transactional annotation for hibernate application resulting in error

I am trying to integrate spring with hibernate this morning. I want to use spring transaction manager. But getting the below error. The error has something to do with @Trasactional Annotation. If i remove the annotation,im able to get the bean from the spring container.

Exception in thread "main" java.lang.ClassCastException: com.sun.proxy.$Proxy19 cannot be cast to com.hibernate.dao.EvntDAOImpl
at com.hibernate.action.HibernateAction.main(HibernateAction.java:17)

Im pasting below my source code.

POM.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>hibernate-tutorials</groupId>
<artifactId>hibernate-tutorials</artifactId>
<version>0.0.1-SNAPSHOT</version>
<build>
    <sourceDirectory>src</sourceDirectory>
    <plugins>
        <plugin>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.1</version>
            <configuration>
                <source>1.6</source>
                <target>1.6</target>
            </configuration>
        </plugin>
    </plugins>
</build>
<properties>
    <spring-framework.version>4.0.3.RELEASE</spring-framework.version>
    <hibernate.version>4.3.5.Final</hibernate.version>
     <slf4j.version>1.7.5</slf4j.version>
</properties>
<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring-framework.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-tx</artifactId>
        <version>${spring-framework.version}</version>
    </dependency>

    <!-- Spring ORM support -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-orm</artifactId>
        <version>${spring-framework.version}</version>
    </dependency>

    <!-- Logging with SLF4J & LogBack -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>${slf4j.version}</version>
        <scope>compile</scope>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-entitymanager</artifactId>
        <version>${hibernate.version}</version>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-core</artifactId>
        <version>${hibernate.version}</version>
    </dependency>
    <dependency>
        <groupId>com.oracle</groupId>
        <artifactId>ojdbc14</artifactId>
        <version>10.2.0.2.0</version>
    </dependency>
    <dependency>
        <groupId>commons-dbcp</groupId>
        <artifactId>commons-dbcp</artifactId>
        <version>1.4</version>
    </dependency>
</dependencies>

Hibernate Configuration

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

http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd ">

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
    <property name="url" value="${url}" />
    <property name="username" value="${username}" />
    <property name="password" value="${password}" />
</bean>

<bean id="sessionFactory"
    class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="annotatedClasses">
        <list>
            <value>com.hibernate.model.Evnt</value>
        </list>
    </property>
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
            <prop key="hibernate.show_sql">true</prop>
        </props>
    </property>
</bean>

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

EvntDAOImpl.java

package com.hibernate.dao;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import com.hibernate.model.Evnt;

@Repository(value="evntDAO")
@Transactional
public class EvntDAOImpl implements EvntDAO {

@Autowired
private SessionFactory sessionFactory;

@Override
public void storeEvnt(Evnt evnt) {

    sessionFactory.getCurrentSession().save(evnt);

}

}

HibernateAction.java

package com.hibernate.action;

import java.util.Date;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.hibernate.dao.EvntDAO;
import com.hibernate.dao.EvntDAOImpl;
import com.hibernate.model.Evnt;

public class HibernateAction {

public static void main(String[] args) {
    ApplicationContext context  = new         ClassPathXmlApplicationContext("applicationContext.xml");

    EvntDAOImpl evntDAO = (EvntDAOImpl) context.getBean("evntDAO");
    Evnt evnt = new Evnt();
    evnt.setTitle("first Event");
    evnt.setDate(new Date());
    evntDAO.storeEvnt(evnt);

    }
}

Thanks in advance...

The problem is in the place where you are injecting EventDaoImpl .

Just replace

@Autowired EventDaoImpl eventDaoImpl

with

@Autowired EventDao eventDao

wherever you need Spring to autowire the dao.

Or if you are getting the bean from the applicationContext use:

EvntDAO evntDAO = (EvntDAO) context.getBean("evntDAO");

The problem is caused by the fact that the use of @Transactional annotation on the dao's implementation code means that Spring will create a JDK dynamic proxy for it, which cannot be cast to the implementation class. Here is the complete documentation of Spring's AOP capabilities (where the creation of JDK dynamic proxies and CGLib class proxies is fully explained).

What that essentially means is that because of @Transactional , when you call context.getBean("evntDAO") you don't get back your EventDaoImpl (as one would expect), but you actually get back an object whose class is java.lang.reflect.Proxy which has been created by Spring. That proxy object implements EventDao (and therefor can be cast to it) but it's signature has nothing to do with EventDaoImpl (and hence the ClassCastException since it does not extend EventDaoImpl ). When a method is called on the proxy various things happen before and/or after the call is actually delegated to EventDaoImpl (what happens before/and or after the actual call to EventDaoImpl is controlled by Spring though the implementation of InvocationHandler ).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM