web-dev-qa-db-fra.com

en utilisant Spring JdbcTemplate - injection de source de données vs jdbcTemplate

Selon Spring documentation , les étapes pour utiliser Spring JdbcTemplate sont les suivantes:

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

        <!-- Scans within the base package of the application for @Components to configure as beans -->
        <context:component-scan base-package="org.springframework.docs.test" />

        <bean id="dataSource" class="org.Apache.commons.dbcp.BasicDataSource" destroy-method="close">
            <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>

        <context:property-placeholder location="jdbc.properties"/>

    </beans>

Et alors,

    @Repository
    public class JdbcCorporateEventDao implements CorporateEventDao {

        private JdbcTemplate jdbcTemplate;

        @Autowired
        public void setDataSource(DataSource dataSource) {
            this.jdbcTemplate = new JdbcTemplate(dataSource);
        }

        // JDBC-backed implementations of the methods on the CorporateEventDao follow...
    }

Fondamentalement, le JdbcTemplate est créé à l'intérieur de la classe Component à l'aide du setter pour la source de données.

Y a-t-il quelque chose de mal à le faire de cette façon à la place pour qu'il y ait exactement UNE instance de jdbcTemplate dans l'application?

<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"
    p:dataSource-ref="dataSource" 
/>

Et puis injecter le jdbcTemplate lui-même directement dans le composant

@Repository
public class JdbcCorporateEventDao implements CorporateEventDao {
    @Resource("jdbcTemplate")
    private JdbcTemplate jdbcTemplate;


    // JDBC-backed implementations of the methods on the CorporateEventDao follow...
}

Y a-t-il une raison pour laquelle le jdbcTemplate lui-même ne doit pas être injecté directement dans la classe de composants?

SGB

35
SGB

Tu peux faire ce que tu veux. Le javadoc de JdbcTemplate le dit même clairement:

Peut être utilisé dans une implémentation de service via une instanciation directe avec une référence DataSource, ou être préparé dans un contexte d'application et donné aux services comme référence de bean.

30
JB Nizet

Dans le fichier spring-context.xml, ajoutez ce qui suit et

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

et directement vous pouvez utiliser jdbcTemplate par câblage automatique comme

  @Autowired JdbcTemplate jdbcTemplate;

exemple:

this.jdbcTemplate.query("select * from ******",new RowMapper());
27
Odaiah

Vous pouvez aussi le faire comme

@Configuration
@Import({PersistenceConfig.class})
@ComponentScan(basePackageClasses = { 
    ServiceMarker.class,
    RepositoryMarker.class }
)
public class AppConfig {

    /**
     * To resolve ${} in @Values, you must register a static PropertySourcesPlaceholderConfigurer in either XML or 
     * annotation configuration file.
     */
    @Bean
    public static PropertySourcesPlaceholderConfigurer propertyConfigInDev() {
        return new PropertySourcesPlaceholderConfigurer();
    }
}

PersistenceConfig

@Configuration
@PropertySource(value = { "classpath:database/jdbc.properties" })
@EnableTransactionManagement
public class PersistenceConfig {

    @Autowired
    private Environment env;

 /**
  * The @Bean annotation is used to declare a Spring bean and the DI requirements. The @Bean annotation is equivalent to
 *  the <bean> tag, the method name is equivalent to the id attribute within the <bean> tag.
  * 
  * <bean id="mySqlDataSource" class="org.Apache.commons.dbcp2.BasicDataSource" destroy-method="close" 
        p:driverClassName="${jdbc.mysql.driverClassName}" 
        p:url="${jdbc.mysql.url}"   
        p:username="${jdbc.mysql.username}" 
        p:password="${jdbc.mysql.password}" />
  * 
  * @return
  */
     @Bean(destroyMethod = "close")
     public DataSource mySqlDataSource() {
         BasicDataSource dataSource = new BasicDataSource();
         dataSource.setDriverClassName(env.getProperty("jdbc.mysql.driverClassName"));
         dataSource.setUrl(env.getProperty("jdbc.mysql.url"));
         dataSource.setUsername(env.getProperty("jdbc.mysql.username"));
         dataSource.setPassword(env.getProperty("jdbc.mysql.password"));
         return dataSource;
     }

     @Bean(destroyMethod = "close")
     public DataSource ls360DataSource() {
         BasicDataSource dataSource = new BasicDataSource();
         dataSource.setDriverClassName(env.getProperty("jdbc.ls360.driverClassName"));
         dataSource.setUrl(env.getProperty("jdbc.ls360.url"));
         dataSource.setUsername(env.getProperty("jdbc.ls360.username"));
         dataSource.setPassword(env.getProperty("jdbc.ls360.password"));
         return dataSource;
     } 
}

MySqlDaoImpl

@Repository
public class MySqlDaoImpl implements MySqlDao{

    private static final Logger logger = LogManager.getLogger();

    @Inject
    private DataSource mySqlDataSource;
    private JdbcTemplate mySqlJdbcTemplate;

    @PostConstruct
    public void afterPropertiesSet() throws Exception {
        if (mySqlDataSource == null) {
            throw new BeanCreationException("Must set mySqlDataSource on " + this.getClass().getName());
        }
        this.mySqlJdbcTemplate = new JdbcTemplate(mySqlDataSource);
    }

    @Override
    public void callStoredProcedure(String storedProcedureName, Map<String, Object> inParamMap) throws Exception {

        SimpleJdbcCall simpleJdbcCall = new SimpleJdbcCall(mySqlJdbcTemplate).withProcedureName(storedProcedureName);
        SqlParameterSource in = new MapSqlParameterSource(inParamMap);

        logger.info("Calling stored Procedure: " + storedProcedureName);
        Map<String, Object> simpleJdbcCallResult = simpleJdbcCall.execute(in);
        logger.info("Stored Procedure Result: " + simpleJdbcCallResult);
    }
}

Principale

public static void main(String[] args ) {
    try (GenericApplicationContext springContext = new AnnotationConfigApplicationContext(AppConfig.class)) {
        MySQLDao mySqlDao = springContext.getBean(MySQLDaoImpl.class);
        try {
            Map<String, Object> inParamMap = new HashMap<String, Object>();
            inParamMap.put("iCourseId", 1);
            mySqlCourseRenewalDao.callStoredProcedure("usp_processCourseRenewal", inParamMap);
        } catch (Exception e) {
            logger.error("Exception occurs", e);
        }
    } catch (Exception e) {
        logger.error("Exception occurs in loading Spring context: ", e);
    }
}

Merci

6
Basit