2013-02-28 3 views
5

스프링 프레임 워크 응용 프로그램의 선언적 트랜잭션에 대해이 자습서를 구현하려고하고 있지만 작동하지 않습니다. 내가 원하는

http://www.tutorialspoint.com/spring/declarative_management.htm

그래서 나는 단지 CRUD 메소드를 정의 느릅 나무에 StudentDAO 인터페이스를 가지고 : 나는 응용 프로그램의 동작을 테스트하기 위해 MainApp에게 클래스를 실행하려고하면 오류를 얻을

,451,515,
package org.andrea.myexample.myDeclarativeTransactionSpring; 

import java.util.List; 

import javax.sql.DataSource; 

/** Interfaccia che definisce i metodi che implementano le operazioni di CRUD 
* che vogliamo implementare nel nostro DAO: 
*/ 
public interface StudentDAO { 

    /** 
    * Questo metodo viene usato per inizializzare le risorse del database cioè 
    * la connessione al database: 
    */ 
    public void setDataSource(DataSource ds); 

    /** 
    * Questo metodo serve a creare un record nella tabella Student e nella 
    * tabella Marks: 
    */ 
    public void create(String name, Integer age, Integer marks, Integer year); 

    /** 
    * Questo metodo serve ad elencare tutti i record all'interno della tabella 
    * Studend e della tabella Marks 
    */ 
    public List<StudentMarks> listStudents(); 
} 

은 그 때 나는 데이터베이스에이 테이블에 계속 내 엔티티을 rappresent StudentMark 클래스가 : 그럼

package org.andrea.myexample.myDeclarativeTransactionSpring; 

// Rappresenta l'entity: 
public class StudentMarks { 

    // Proprietà: 
    private Integer age; 
    private String name; 
    private Integer id; 
    private Integer marks; 
    private Integer year; 
    private Integer sid; 

    // Metodi Getter & Setter: 
    public void setAge(Integer age) { 
     this.age = age; 
    } 

    public Integer getAge() { 
     return age; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

    public String getName() { 
     return name; 
    } 

    public void setId(Integer id) { 
     this.id = id; 
    } 

    public Integer getId() { 
     return id; 
    } 

    public void setMarks(Integer marks) { 
     this.marks = marks; 
    } 

    public Integer getMarks() { 
     return marks; 
    } 

    public void setYear(Integer year) { 
     this.year = year; 
    } 

    public Integer getYear() { 
     return year; 
    } 

    public void setSid(Integer sid) { 
     this.sid = sid; 
    } 

    public Integer getSid() { 
     return sid; 
    } 
} 

내가 RowMapper의 인터페이스를 구현하는 클래스 StudentMarksMapper 있습니다 :

package org.andrea.myexample.myDeclarativeTransactionSpring; 

import java.sql.ResultSet; 
import java.sql.SQLException; 
import org.springframework.jdbc.core.RowMapper; 


/** Classe che implementa l'interfaccia RowMapper. Si tratta di un'interfaccia 
* usata da JdbcTemplate per mappare le righe di un ResultSet (oggetto che 
* contiene l'insieme delle righe restituite da una query SQL) riga per riga. 
* Le implementazioni di questa interfaccia mappano ogni riga su di un oggetto 
* risultante senza doversi preoccupare della gestione delle eccezioni poichè 
* le SQLException saranno catturate e gestite dalla chiamata a JdbcTemplate. 
*/ 
public class StudentMarksMapper implements RowMapper<StudentMarks> { 

    /** Implementazione del metodo dell'interfaccia RowMapper che mappa una 
    * specifica riga della tabella su di un oggetto Student 
    * 
    * @param Un oggetto ResultSet contenente l'insieme di tutte le righe 
    *   restituite dalla query 
    * 
    * @param L'indice che indentifica una specifica riga 
    * 
    * @return Un nuovo oggetto Student rappresentante la riga selezionata 
    *   all'interno dell'oggetto ResultSet 
    * 
    * @see org.springframework.jdbc.core.RowMapper#mapRow(java.sql.ResultSet, int) 
    */ 
    public StudentMarks mapRow(ResultSet rs, int rowNum) throws SQLException { 

     StudentMarks studentMarks = new StudentMarks(); 

     studentMarks.setId(rs.getInt("id")); 
     studentMarks.setName(rs.getString("name")); 
     studentMarks.setAge(rs.getInt("age")); 
     studentMarks.setSid(rs.getInt("sid")); 
     studentMarks.setMarks(rs.getInt("marks")); 
     studentMarks.setYear(rs.getInt("year")); 

     return studentMarks; 
    } 
} 

다음으로

package org.andrea.myexample.myDeclarativeTransactionSpring; 

import java.util.List; 
import javax.sql.DataSource; 
import org.springframework.dao.DataAccessException; 
import org.springframework.jdbc.core.JdbcTemplate; 

/** 
* Classe che fornisce l'implementazione per il nostro DAO le cui funzionalità 
* di CRUD sono state definite tramite l'interfaccia StudentDAO 
*/ 
public class StudentJDBCTemplate implements StudentDAO { 

    // Utility per l'accesso alla sorgente dati 
    private JdbcTemplate jdbcTemplateObject; 

    /** 
    * Metodo Setter per l'Injection della dipendenza relativa alla sorgente 
    * dati. Tale metodo inoltre costruisce anche l'oggetto istanza di 
    * JdbcTemplate usato per interagire con i dati nel database. 
    * 
    * @param la sorgente dati 
    */ 
    public void setDataSource(DataSource dataSource) { 
     this.jdbcTemplateObject = new JdbcTemplate(dataSource); 
    } 

    /** 
    * Metodo relativo all'operazione di CREATE che inserisce un nuovo record 
    * all'interno della tabella Student ed un correlato nuovo record nella 
    * tabella Marks. 
    */ 
    public void create(String name, Integer age, Integer marks, Integer year) { 

     try { 
      // Query che inserisce nome ed età nella tabella Student: 
      String SQL1 = "insert into Student (name, age) values (?, ?)"; 
      // Esegue la query passandogli anche i valori effettivi da inserire: 
      jdbcTemplateObject.update(SQL1, name, age); 

      // Seleziona l'ultimo studente inserito nella tabella Marks: 
      String SQL2 = "select max(id) from Student"; 
      // Esegue la query e mette il risultato (l'ID) in sid: 
      int sid = jdbcTemplateObject.queryForInt(SQL2); 

      /** 
      * Query che inserisce un nuovo record nella tabella Marks. Il 
      * record rappresenta il voto per l'ultimo studente inserito nella 
      * tabella Student: 
      */ 
      String SQL3 = "insert into Marks(sid, marks, year) " 
        + "values (?, ?, ?)"; 
      // Esegue la query passandogli anche i valori effettivi da inserire: 
      jdbcTemplateObject.update(SQL3, sid, marks, year); 

      System.out.println("Created Name = " + name + ", Age = " + age); 

      // SIMULA UNA RuntimeExceptio: 
      throw new RuntimeException("Simulazione di una condizione d'errore"); 
     } catch (DataAccessException e) {  // GESTIONE DELL'ECCEZIONE 
      System.out.println("Errore nella creazione dei record, esegue rollback"); 
      throw e; 
     } 
    } 

    /** 
    * Metodo relativo all'operazione di READ che recupera la lista degli 
    * studenti e dei relativi voti 
    * 
    * @return La lista di oggetti che rappresentano uno studente ed i suoi voti 
    *   correlati 
    */ 
    public List<StudentMarks> listStudents() { 

     /** 
     * Query che estrae la lista di tutti i record nella tabella Student e 
     * che per ogni record in tale tabella estrae i relativi record 
     * correlati nella tabella Marks 
     */ 
     String SQL = "select * from Student, Marks where Student.id=Marks.sid"; 

     /** 
     * Ottengo la lista degli oggetti StudentMarks, corrispondenti ognuno ad 
     * un record della tabella Student con i correlati vori rappresentati 
     * dai record della tabella Marks, invocando il metodo query 
     * sull'oggetto JdbcTemplate passandogli i seguenti parametri. 
     * 
     * @param La query per creare il preparated statement 
     * @param Un oggetto che implementa RowMapper che viene usato per 
     *  mappare una singola riga della tabella su di un oggetto Java 
     */ 
     List<StudentMarks> studentMarks = jdbcTemplateObject.query(SQL, 
                new StudentMarksMapper()); 
     return studentMarks; 
    } 
} 

그런 다음이 응용 프로그램 테스트 할 MainApp 클래스 :들 StudentJDBCTemplate 클래스 그 StudentDAO 인터페이스입니다

package org.andrea.myexample.myDeclarativeTransactionSpring; 

import java.util.List; 
import org.springframework.context.ApplicationContext; 
import org.springframework.context.support.ClassPathXmlApplicationContext; 

// Classe principale: 
public class MainApp { 

    public static void main(String[] args) { 

     /** 
     * Crea il contesto in base alle impostazioni dell'applicazione definite 
     * nel file Beans.xml 
     */ 
     ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml"); 

     /** 
     * Recupera un bean avente id="studentJDBCTemplate" nel file di 
     * configurazione Beans.xml 
     */ 
     StudentJDBCTemplate studentJDBCTemplate = (StudentJDBCTemplate) context.getBean("studentJDBCTemplate"); 

     System.out.println("------Creazione dei record--------"); 
     // Creo i record nelle tabelle Studend e Marks: 
     studentJDBCTemplate.create("Zara", 11, 99, 2010); 
     studentJDBCTemplate.create("Nuha", 20, 97, 2010); 
     studentJDBCTemplate.create("Ayan", 25, 100, 2011); 

     System.out.println("------Elenca tutti i record--------"); 
     // Recupera la lista degli studenti con i voti ad essi associati: 
     List<StudentMarks> studentMarks = studentJDBCTemplate.listStudents(); 

     for (StudentMarks record : studentMarks) {  // e li stampa 
      System.out.print("ID : " + record.getId()); 
      System.out.print(", Name : " + record.getName()); 
      System.out.print(", Marks : " + record.getMarks()); 
      System.out.print(", Year : " + record.getYear()); 
      System.out.println(", Age : " + record.getAge()); 
     } 
    } 
} 

이 Finnally이 내 beans.xml 환경 구성 파일입니다

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

    <!-- Initializazione della sorgente dati: --> 
    <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/SpringTestDb" /> 
     <property name="username" value="root" /> 
     <property name="password" value="aprile12" /> 
    </bean> 

    <tx:advice id="txAdvice" transaction-manager="transactionManager"> 
     <tx:attributes> 
      <tx:method name="create" /> 
     </tx:attributes> 
    </tx:advice> 

    <aop:config> 
     <aop:pointcut id="createOperation" 
      expression="execution(* org.andrea.myexample.myDeclarativeTransactionSpring.StudentJDBCTemplate.create(..))" /> 
     <aop:advisor advice-ref="txAdvice" pointcut-ref="createOperation" /> 
    </aop:config> 

    <!-- Inizializzazione del Transaction Manager: --> 
    <bean id="transactionManager" 
     class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 
     <property name="dataSource" ref="dataSource" /> 
    </bean> 

    <!-- Definizione del bean che rappresenta il DAO studentJDBCTemplate: --> 
    <bean id="studentJDBCTemplate" class="org.andrea.myexample.myDeclarativeTransactionSpring.StudentJDBCTemplate"> 
     <property name="dataSource" ref="dataSource" /> 
    </bean> 

</beans> 

the prrob 이 오류 메시지

INFO: Loaded JDBC driver: com.mysql.jdbc.Driver 
Exception in thread "main" java.lang.ClassCastException: com.sun.proxy.$Proxy0 cannot be cast to org.andrea.myexample.myDeclarativeTransactionSpring.StudentJDBCTemplate 
    at org.andrea.myexample.myDeclarativeTransactionSpring.MainApp.main(MainApp.java:22) 

즉 단순히 언제 문제가 MainApp 클래스 ... 라인 (22)에 말 : 렘 나는 다음과 같은 오류 messate를 얻기 내 MainApp 클래스를 실행하려고 할 때이다 ID = "studentJDBCTemplate 인 빈을 얻으려고합니다 :

StudentJDBCTemplate studentJDBCTemplate = (StudentJDBCTemplate) context.getBean("studentJDBCTemplate"); 

어디에서 문제가 발생합니까? 어떻게 해결할 수 있습니까?

TNX

안드레아

+3

나는 스프링 프록시가별로 신선하지 않지만, 'StudentJDBCTemplate'을 확장하는 대신 프록시가 'StudentDAO' 인터페이스를 구현할 것이라고 생각한다. 그래서 당신이'ApplciationContext'에서 그 bean을 요청할 때, 당신은 아마 그것을 대신'StudentDAO'로 캐스팅하고 싶을 것입니다. –

+0

@ nicholas.hauschild - 고마워, 효과가 있었다. 나는 왜 그것이 어떻게 작동하는지 궁금해? +1 팁과 나는 이것이 대답이되어야한다고 생각한다. –

답변

10

옵션 1, 인터페이스 수준에서 거래를 주입하는 구성을 변경

<aop:config> 
    <aop:pointcut id="createOperation" 
     expression="execution(* org.andrea.myexample.myDeclarativeTransactionSpring.StudentDAO.create(..))" /> 
    <aop:advisor advice-ref="txAdvice" pointcut-ref="createOperation" /> 
</aop:config> 

그 인터페이스의 인스턴스로 콩을 구하십시오

StudentDAO studentDao = (StudentDAO) context.getBean("studentJDBCTemplate"); 

옵션 2는 프록시가 대상 클러스터를 확장해야 함을 나타냅니다.

<aop:config proxy-target-class="true"> 
    ... 
</aop:config> 

첫 번째 옵션은 청소기 하나이지만, 솔직히 나는 봄 콩 XML 내에서 @Transactional 주석이 아닌 AOP 선언을 사용하는 것을 선호 것 : proxy-target-class 속성을 사용하여이야. 후자를 올바르게 처리하는 것이 어려우며 구성 요소에 대한 특정 거래 성 테스트가없는 경우 은 정확하지 않은 것을 알리지 않습니다..

+0

좋아, 이제는 ... – AndreaNobili

2

당신은 다음과 같은 라인 즉, AOP의 pointcut 표현의 인터페이스 유형 사용해야합니다 -

expression="execution(* org.andrea.myexample.myDeclarativeTransactionSpring.StudentJDBCTemplate.create(..))" /> 

는 아래의 코드를 사용합니다 : -

expression="execution(* org.andrea.myexample.myDeclarativeTransactionSpring.StudentDAO.create(..))" /> 

봄 두 유형 인 프록시를 통해 AOP를 지원합니다 인터페이스 기반 (Proxy는 대상 클래스에 의해 구현 된 모든 인터페이스를 구현 함) 및 클래스 기반 (대상 클래스를 서브 클래 싱하여 구현 됨)

2

<aop:config>을 변경하지 않고도 StudentDAO 인터페이스에서 bean 인스턴스를 가져 와서 실행할 수있었습니다.

<aop:config> 
     <aop:pointcut id="createOperation" 
     expression="execution(* com.tutorialspoint.StudentJDBCTemplate.create(..))"/> 
     <aop:advisor advice-ref="txAdvice" pointcut-ref="createOperation"/> 
</aop:config> 

StudentDAO studentJDBCTemplate = (StudentDAO)context.getBean("studentJDBCTemplate");