2013-02-28 39 views
5

私はSpring FrameworkアプリケーションのDeclarative Transactionについてこのチュートリアルを実装しようとしていますが、私は、アプリケーションの動作をテストするためにMainAppにクラスを実行しようとすると、私はエラーを取得:

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

だから、私は唯一の私が欲しいCRUDメソッドを定義ウィッヒでStudentDAOインタフェースを持っています その後、私はRowMapperのインタフェースを実装するクラスStudentMarksMapperを持って

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; 
    } 
} 

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(); 
} 

は、それから私は、データベース上の2台の上に固執する私のエンティティをrappresent StudentMarkクラスを持っています

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; 
    } 
} 

thi

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にクラスです:

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の設定ファイルです:

sがStudentDAOインタフェースがあること StudentJDBCTemplateクラスです
<?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 LEMは、私は私のMainAppにクラスを実行しようとすると、私は次のようなエラーmessate得ることをされています。問題は、MainAppにクラスのライン22上にあると言うこのエラーメッセージで

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) 

を...それは単にときです

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

問題がある:私はID = "studentJDBCTemplateを持つBeanを取得しようか?どうすれば解決できますか?

TNX

アンドレア

+3

私はSpringプロキシでは新鮮ではありませんが、プロキシは '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は、プロキシがターゲットクラスを拡張する必要があることを示しますproxy-target-class属性を使用して、S:

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

最初のオプションはきれいですが、率直に言って、私は、SpringのBean XML内@Transactional注釈ではなく、AOP宣言を使用することを好むだろう。後者が正しくなるようにするのは難しい場合があります。コンポーネントに特定のトランザクション性テストがない場合、は必ずしも正しくないことに気付くわけではありません。

+0

今、それは働く... – AndreaNobili

2

あなたは、行を次のようにすなわちAOPポイントカット式のインターフェイスタイプを使用する必要があります: - :

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

春は2型であるプロキシ経由でAOPをサポートしています -

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

は、以下のコードを使用しますインタフェースベース(プロキシはターゲットクラスによって実装されたすべてのインタフェースを実装します)とクラスベース(ターゲットクラスをサブクラス化して実現)

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"); 
関連する問題