Spring 抽象父 class 和子 class 的配置问题

Spring configuration issue with abstract parent class and child class

我正在尝试让以下代码工作。基本上我在 mysql 数据库中有一个名为 alert_settings 的 table。下面是我如何配置它和 classes.

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

    <!-- DriverManagerDataSource : Spring simplest implementation of a DataSource (doesn�??t support database connection pooling)-->

    <bean id="dataSource"  class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName"  value="${jdbc.driverClassName}" />
        <property name="url"              value="${jdbc.url}" />
        <property name="username"         value="${jdbc.username}" />
        <property name="password"         value="${jdbc.password}" />
    </bean>


    <!-- The properties file containing the values for the JDBC datasource-->   
    <context:property-placeholder location="jdbc.properties"/>


    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource" />
    </bean>

    <bean id="abstractBaseClass" abstract="true" class="org.jay.dao.impl.spring.commons.GenericDAO">
      <property name="dataSource" value="dataSource"/>
    </bean>

    <bean id="alertSettingDAO" class="org.jay.dao.impl.spring.AlertSettingDAOImplSpring" parent="abstractBaseClass">     
      <!--Override the value of the abstract based class if necessary-->
      <property name="dataSource" value="dataSource"/>
    </bean>

下面是我的Abstract Generic DAO,Alert设置DAO接口和实际DAO class。

@存储库 public class AlertSettingDAOImplSpring 扩展 GenericDAO 实现 AlertSettingDAO {

private final static String SQL_SELECT = 
    "select user_token, sms_enabled, sms_settle_enabled, sms_load_enabled, sms_unload_enabled, sms_auth_enabled, sms_decline_enabled, sms_chargeback_enabled, sms_promo_enabled, sms_flagged_for_failures, 2way_enabled, email_alert_enabled from alert_setting where user_token = ?";


private final static String SQL_INSERT = 
    "insert into alert_setting ( user_token, sms_enabled, sms_settle_enabled, sms_load_enabled, sms_unload_enabled, sms_auth_enabled, sms_decline_enabled, sms_chargeback_enabled, sms_promo_enabled, sms_flagged_for_failures, 2way_enabled, email_alert_enabled ) values ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )";

private final static String SQL_UPDATE = 
    "update alert_setting set sms_enabled = ?, sms_settle_enabled = ?, sms_load_enabled = ?, sms_unload_enabled = ?, sms_auth_enabled = ?, sms_decline_enabled = ?, sms_chargeback_enabled = ?, sms_promo_enabled = ?, sms_flagged_for_failures = ?, 2way_enabled = ?, email_alert_enabled = ? where user_token = ?";

private final static String SQL_DELETE = 
    "delete from alert_setting where user_token = ?";

private final static String SQL_COUNT_ALL = 
    "select count(*) from alert_setting";

private final static String SQL_COUNT = 
    "select count(*) from alert_setting where user_token = ?";

//----------------------------------------------------------------------
/**
 * DAO constructor
 */
public AlertSettingDAOImplSpring() {
    super();
}

//----------------------------------------------------------------------
/* (non-Javadoc)
 * DAO interface implementation
 */
@Override
public AlertSetting find( String userToken ) {
    Object[] primaryKey = new Object[] { userToken };
    return super.doSelect(primaryKey);      
}
//----------------------------------------------------------------------
/* (non-Javadoc)
 * DAO interface implementation
 */
@Override
public boolean load( AlertSetting alertSetting ) {
    return super.doSelect(alertSetting) ;
}

//----------------------------------------------------------------------
/* (non-Javadoc)
 * DAO interface implementation
 */
@Override
public void insert(AlertSetting alertSetting) {
    super.doInsert(alertSetting);
}   

//----------------------------------------------------------------------
/* (non-Javadoc)
 * DAO interface implementation
 */
@Override
public int update(AlertSetting alertSetting) {
    return super.doUpdate(alertSetting);
}   

//----------------------------------------------------------------------
/* (non-Javadoc)
 * DAO interface implementation
 */
@Override
public int delete( String userToken ) {
    Object[] primaryKey = new Object[] { userToken };
    return super.doDelete(primaryKey);      
}

//----------------------------------------------------------------------
/* (non-Javadoc)
 * DAO interface implementation
 */
@Override
public int delete( AlertSetting alertSetting ) {
    return super.doDelete(alertSetting);
}

//----------------------------------------------------------------------
/* (non-Javadoc)
 * DAO interface implementation
 */
@Override
public boolean exists( String userToken ) {
    Object[] primaryKey = new Object[] { userToken };
    return super.doExists(primaryKey);
}
//----------------------------------------------------------------------
/* (non-Javadoc)
 * DAO interface implementation
 */
@Override
public boolean exists( AlertSetting alertSetting ) {
    return super.doExists(alertSetting);
}

//----------------------------------------------------------------------
/* (non-Javadoc)
 * DAO interface implementation
 */
@Override
public long count() {
    return super.doCountAll();
}

//----------------------------------------------------------------------
// Super class abstract methods implementation
//----------------------------------------------------------------------
@Override
protected String getSqlSelect() {
    return SQL_SELECT ;
}
//----------------------------------------------------------------------
@Override
protected String getSqlInsert() {
    return SQL_INSERT ;
}
//----------------------------------------------------------------------
@Override
protected String getSqlUpdate() {
    return SQL_UPDATE ;
}
//----------------------------------------------------------------------
@Override
protected String getSqlDelete() {
    return SQL_DELETE ;
}
//----------------------------------------------------------------------
@Override
protected String getSqlCount() {
    return SQL_COUNT ;
}
//----------------------------------------------------------------------
@Override
protected String getSqlCountAll() {
    return SQL_COUNT_ALL ;
}
//----------------------------------------------------------------------
@Override
protected Object[] getValuesForInsert(AlertSetting alertSetting)  {
    return new Object[] {
        //--- Returns PRIMARY KEY and DATA ( for SQL "SET x=?, y=?, ..." )
        alertSetting.getUserToken() , // "user_token" : java.lang.String
        alertSetting.getSmsEnabled() , // "sms_enabled" : java.lang.Integer
        alertSetting.getSmsSettleEnabled() , // "sms_settle_enabled" : java.lang.Integer
        alertSetting.getSmsLoadEnabled() , // "sms_load_enabled" : java.lang.Integer
        alertSetting.getSmsUnloadEnabled() , // "sms_unload_enabled" : java.lang.Integer
        alertSetting.getSmsAuthEnabled() , // "sms_auth_enabled" : java.lang.Integer
        alertSetting.getSmsDeclineEnabled() , // "sms_decline_enabled" : java.lang.Integer
        alertSetting.getSmsChargebackEnabled() , // "sms_chargeback_enabled" : java.lang.Integer
        alertSetting.getSmsPromoEnabled() , // "sms_promo_enabled" : java.lang.Integer
        alertSetting.getSmsFlaggedForFailures() , // "sms_flagged_for_failures" : java.lang.Integer
        alertSetting.getTwoWayEnabled() , // "2way_enabled" : java.lang.Integer
        alertSetting.getEmailAlertEnabled()  // "email_alert_enabled" : java.lang.Integer
    };
}
//----------------------------------------------------------------------
@Override
protected Object[] getValuesForUpdate(AlertSetting alertSetting) {
    return new Object[] {       
        //--- Returns DATA first ( for SQL "SET x=?, y=?, ..." )
        alertSetting.getSmsEnabled(), // "sms_enabled" : java.lang.Integer
        alertSetting.getSmsSettleEnabled(), // "sms_settle_enabled" : java.lang.Integer
        alertSetting.getSmsLoadEnabled(), // "sms_load_enabled" : java.lang.Integer
        alertSetting.getSmsUnloadEnabled(), // "sms_unload_enabled" : java.lang.Integer
        alertSetting.getSmsAuthEnabled(), // "sms_auth_enabled" : java.lang.Integer
        alertSetting.getSmsDeclineEnabled(), // "sms_decline_enabled" : java.lang.Integer
        alertSetting.getSmsChargebackEnabled(), // "sms_chargeback_enabled" : java.lang.Integer
        alertSetting.getSmsPromoEnabled(), // "sms_promo_enabled" : java.lang.Integer
        alertSetting.getSmsFlaggedForFailures(), // "sms_flagged_for_failures" : java.lang.Integer
        alertSetting.getTwoWayEnabled(), // "2way_enabled" : java.lang.Integer
        alertSetting.getEmailAlertEnabled(), // "email_alert_enabled" : java.lang.Integer
        //--- Returns PRIMARY KEY at the end ( for SQL "WHERE key=?, ..." )
        alertSetting.getUserToken()  // "user_token" : java.lang.String
    };
}
//----------------------------------------------------------------------
@Override
protected Object[] getValuesForPrimaryKey(AlertSetting alertSetting)  {
    return new Object[] {
        //--- Returns PRIMARY KEY values ( for SQL "WHERE key=?, ..." )
        alertSetting.getUserToken()  // "user_token" : java.lang.String
    };
}
//----------------------------------------------------------------------
@Override
protected RowMapper<AlertSetting> getRowMapper(AlertSetting o)  {
    //--- RowMapper to populate the given bean instance
    return new AlertSettingRowMapper(o) ;
}
//----------------------------------------------------------------------
@Override
protected RowMapper<AlertSetting> getRowMapper()  {
    //--- RowMapper to populate a new bean instance
    return new AlertSettingRowMapper( new AlertSetting() ) ;
}

//----------------------------------------------------------------------
/**
 * Populates the given bean with the data retrieved from the given ResultSet
 * @param rs
 * @param alertSetting
 * @throws SQLException
 */
private void populateBean(ResultSet rs, AlertSetting alertSetting) throws SQLException {

    //--- Set data from ResultSet to Bean attributes
    alertSetting.setUserToken(rs.getString("user_token")); // java.lang.String
    alertSetting.setSmsEnabled(rs.getInt("sms_enabled")); // java.lang.Integer
    if ( rs.wasNull() ) { alertSetting.setSmsEnabled(null); }; // not primitive number => keep null value if any
    alertSetting.setSmsSettleEnabled(rs.getInt("sms_settle_enabled")); // java.lang.Integer
    if ( rs.wasNull() ) { alertSetting.setSmsSettleEnabled(null); }; // not primitive number => keep null value if any
    alertSetting.setSmsLoadEnabled(rs.getInt("sms_load_enabled")); // java.lang.Integer
    if ( rs.wasNull() ) { alertSetting.setSmsLoadEnabled(null); }; // not primitive number => keep null value if any
    alertSetting.setSmsUnloadEnabled(rs.getInt("sms_unload_enabled")); // java.lang.Integer
    if ( rs.wasNull() ) { alertSetting.setSmsUnloadEnabled(null); }; // not primitive number => keep null value if any
    alertSetting.setSmsAuthEnabled(rs.getInt("sms_auth_enabled")); // java.lang.Integer
    if ( rs.wasNull() ) { alertSetting.setSmsAuthEnabled(null); }; // not primitive number => keep null value if any
    alertSetting.setSmsDeclineEnabled(rs.getInt("sms_decline_enabled")); // java.lang.Integer
    if ( rs.wasNull() ) { alertSetting.setSmsDeclineEnabled(null); }; // not primitive number => keep null value if any
    alertSetting.setSmsChargebackEnabled(rs.getInt("sms_chargeback_enabled")); // java.lang.Integer
    if ( rs.wasNull() ) { alertSetting.setSmsChargebackEnabled(null); }; // not primitive number => keep null value if any
    alertSetting.setSmsPromoEnabled(rs.getInt("sms_promo_enabled")); // java.lang.Integer
    if ( rs.wasNull() ) { alertSetting.setSmsPromoEnabled(null); }; // not primitive number => keep null value if any
    alertSetting.setSmsFlaggedForFailures(rs.getInt("sms_flagged_for_failures")); // java.lang.Integer
    if ( rs.wasNull() ) { alertSetting.setSmsFlaggedForFailures(null); }; // not primitive number => keep null value if any
    alertSetting.setTwoWayEnabled(rs.getInt("2way_enabled")); // java.lang.Integer
    if ( rs.wasNull() ) { alertSetting.setTwoWayEnabled(null); }; // not primitive number => keep null value if any
    alertSetting.setEmailAlertEnabled(rs.getInt("email_alert_enabled")); // java.lang.Integer
    if ( rs.wasNull() ) { alertSetting.setEmailAlertEnabled(null); }; // not primitive number => keep null value if any
}

//----------------------------------------------------------------------
/**
 * Specific inner class for 'RowMapper' implementation
 */
private class AlertSettingRowMapper implements RowMapper<AlertSetting> {


    private final AlertSetting bean ;


    AlertSettingRowMapper(AlertSetting bean) {
        this.bean = bean ;
    }

    @Override
    public AlertSetting mapRow(ResultSet rs, int rowNum) throws SQLException {
        populateBean(rs, this.bean);
        return this.bean;
    }
}

}

这是我的主要class

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

    Resource resource=new ClassPathResource("spring-context.xml");  
    BeanFactory factory=new XmlBeanFactory(resource);  
    AlertSettingDAOImplSpring a = (AlertSettingDAOImplSpring) factory.getBean("alertSettingDAO");
    System.out.println(a.find("Anil").toString());
}  
}  

Error creating bean with name 'alertSettingDAO' defined in class path resource [spring-context.xml]: Error setting property values; nested exception is org.springframework.beans.NotWritablePropertyException: Invalid property 'dataSource' of bean class [org.jay.dao.impl.spring.AlertSettingDAOImplSpring]: Bean property 'dataSource' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?

我哪里错了?正确的做法是什么?

错误很明显,您的 类 中没有 DataSource 的 getter 和 setter。

您的 Spring 配置也是错误的,您使用的是 value="dataSource" 并且 spring 期望那些 类 具有 属性 的字符串的 getter 和 setter数据源。您必须将它们更改为使用 ref="dataSource",如下所示:

<bean id="abstractBaseClass" abstract="true" class="org.jay.dao.impl.spring.commons.GenericDAO">
  <property name="dataSource" ref="dataSource"/>
</bean>

<bean id="alertSettingDAO" class="org.jay.dao.impl.spring.AlertSettingDAOImplSpring" parent="abstractBaseClass">     
  <!--Override the value of the abstract based class if necessary-->
  <property name="dataSource" ref="dataSource"/>
</bean>

同时删除@Resource 注释

private DataSource dataSource;

并确保在您尝试为其注入对象引用的 类 中创建了 getter 和 setter。

如果您不希望 getter 和 setter 从 Spring 配置中删除 <property name="dataSource"... 声明并改为使用 @Autowired:

@Autowired
private DataSource dataSource;