2013-02-28 28 views
5

Tôi đang cố triển khai hướng dẫn này về Giao dịch khai báo trong ứng dụng Khung công tác nhưng không hoạt động vì khi tôi cố gắng để thực hiện MainApp lớp để kiểm tra các hành vi ứng dụng tôi có được một lỗi:

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

Vì vậy, tôi có giao diện StudentDAO trong mà tôi chỉ xác định các phương pháp CRUD mà tôi muốn:

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

Sau đó, tôi có StudentMark lớp rappresent thực thể của tôi để tồn tại trên 2 bảng trên cơ sở dữ liệu:

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

Sau đó, tôi có lớp StudentMarksMapper mà thực hiện RowMapper giao diện:

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

Bên cạnh nó thi s là StudentJDBCTemplate lớp StudentDAO giao diện:

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

Sau đó, đây là MainApp lớp để kiểm tra các ứng dụng:

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 đây là Beans.xml tập tin cấu hình của tôi:

<?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> 

prrob lem là khi tôi cố gắng chạy MainApp lớp của tôi, tôi có được messate lỗi sau:

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) 

Trong thông báo lỗi này cho rằng vấn đề là trên dòng 22 của lớp MainApp ... mà chỉ đơn giản là khi Tôi cố gắng lấy đậu có ID = "studentJDBCTemplate:

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

Vấn đề ở đâu? Làm thế nào tôi có thể giải quyết?

Tnx

Andrea

+3

Tôi không phải là rất mới trên các proxy mùa xuân, nhưng tôi nghĩ rằng proxy sẽ triển khai giao diện 'StudentDAO' thay vì mở rộng' StudentJDBCTemplate'. Vì vậy, khi bạn yêu cầu bean đó, từ 'ApplciationContext', bạn có thể muốn đưa nó vào' StudentDAO'. –

+0

@ nicholas.hauschild - Cảm ơn, nó đã hoạt động. Tôi tự hỏi tại sao nó hoạt động theo cách của nó? 1 cho tip và tôi nghĩ rằng đây sẽ là một câu trả lời –

Trả lời

10

Lựa chọn 1, thay đổi cấu hình của bạn để tiêm giao dịch ở mức giao diện:

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

và lấy đậu như một thể hiện của giao diện mà:

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

Tùy chọn 2, cho biết rằng proxy phải mở rộng các cụm mục tiêu s sử dụng proxy-target-class thuộc tính:

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

Tùy chọn đầu tiên là sạch hơn một, nhưng thẳng thắn mà nói tôi muốn sử dụng @Transactional chú thích chứ không phải khai báo AOP trong XML đậu mùa xuân. Đôi khi nó diffucult để có được sau này chính xác và nếu bạn không có kiểm tra giao dịch cụ thể về các thành phần của bạn, bạn sẽ không nhất thiết phải nhận thấy rằng mọi thứ không chính xác.

+0

ok, bây giờ nó hoạt động ... – AndreaNobili

2

Bạn nên sử dụng các loại giao diện trong biểu aop pointcut tức là phù hợp sau đây: -

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

sử dụng mã dưới đây: -

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

Xuân hỗ trợ AOP qua proxy đó là hai loại Giao diện dựa trên (Proxy thực hiện tất cả các giao diện được thực hiện bởi lớp đích) và lớp dựa trên (đạt được bằng cách phân lớp lớp đích).

2

Tôi có thể thực thi mà không thay đổi <aop:config>, chỉ bằng cách lấy cá thể đậu từ giao diện StudentDAO.

<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"); 
Các vấn đề liên quan