gpt4 book ai didi

java - Spring Controller 中的 JDBCTemplate

转载 作者:行者123 更新时间:2023-11-30 07:28:38 25 4
gpt4 key购买 nike

我需要做一些并非严格意义上的实体列表的报告。更多自由形式的查询,硬编码 SQL,以任意 JSON 形式返回。

我正在尝试为此使用 JdbcTemplate,并使用我在网上找到的代码(例如 here)来构建它。

这一切都在一个名为 ReportViewController 的类中。

我的代码(带有稍后相关的日志记录/调试问题):

private JdbcTemplate jdbcTemplate;
private DataSource dataSource;
private UUID uuid;


public ReportViewController() {
this.uuid = UUID.randomUUID();
}


public void setDataSource(DataSource dataSource) {
System.out.println("Setting data source");
this.dataSource = dataSource;
if (this.dataSource == null) {
System.out.println("failed to set my dataSource properly");
}
System.out.println("uuid: " + this.uuid);
}

@RequestMapping(value = "/report/{reportId}", method = RequestMethod.POST)
@ResponseBody
public String runNewUntypedSearch(@PathVariable Integer reportId, WebRequest request, HttpSession session) {
//View v = View.findView(reportId);

System.out.println("uuid: " + this.uuid);
if (this.dataSource == null) {
System.out.println("lost my dataSource somewhere along the way");
}

this.jdbcTemplate = new JdbcTemplate(this.dataSource);

List<Map<String, Object>> l = null;
try {
l = this.jdbcTemplate.queryForList("select 1 as one");

JSONSerializer s = new JSONSerializer();
return s.serialize(l);

} catch (Exception e) {
System.out.println("querying failed -- " + e.toString());
return "";
}
}

我的问题是,尽管控制台指示它正在调用 setDataSource(),但当我进入 runNewUntypedSearch() 时,这些属性为空。

因此,我怀疑我正在与之交谈的对象存在犯规行为,我让这个 Controller 在其构造函数中创建一个 UUID,并将其作为其日志记录的一部分输出,如您在上文中所见。

控制台输出部分显示:

Setting data source
hash: bc679ef1-fbdc-4ef9-9457-dd79889f973e
...
hash: bbe2b03a-92ff-4517-add8-8d9ff6480cc8
lost my dataSource somewhere along the way

...然后 Spring 以“内部错误”和堆栈跟踪响应浏览器,该堆栈跟踪指示我正在尝试实例化我的 jdbcTemplate 的空指针。

这使我得出结论,无论对象被告知设置其数据源与作为 URL 映射方法挂接的实例不同。服务器运行的“真实”实例尚未调用 getDataSource()

可以吗?为什么这不起作用?

编辑:

web.xml(编辑删除我客户的名字):

<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.4" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">


<display-name>myProjectName</display-name>

<description>Roo generated application</description>


<!-- Enable escaping of form submission contents -->
<context-param>
<param-name>defaultHtmlEscape</param-name>
<param-value>true</param-value>
</context-param>

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:META-INF/spring/applicationContext*.xml</param-value>
</context-param>

<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>



<filter>
<filter-name>HttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>



<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter>
<filter-name>Spring OpenEntityManagerInViewFilter</filter-name>
<filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<filter-mapping>
<filter-name>HttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>



<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>Spring OpenEntityManagerInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<!-- Handles Spring requests -->
<servlet>
<servlet-name>myProjectName</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/webmvc-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>myProjectName</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

<session-config>
<session-timeout>90</session-timeout>
</session-config>

<error-page>
<exception-type>java.lang.Exception</exception-type>
<location>/uncaughtException</location>
</error-page>

<error-page>
<error-code>404</error-code>
<location>/resourceNotFound</location>
</error-page>
</web-app>

applicationContext.xml(编辑以删除客户端名称和 Roo 生成的注释)

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd 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 http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">


<context:property-placeholder location="classpath*:META-INF/spring/*.properties"/>


<context:spring-configured/>


<context:component-scan base-package="com.myProjectName">
<context:exclude-filter expression=".*_Roo_.*" type="regex"/>
<context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
</context:component-scan>


<bean class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" id="dataSource">
<property name="driverClassName" value="${database.driverClassName}"/>
<property name="url" value="${database.url}"/>
<property name="username" value="${database.username}"/>
<property name="password" value="${database.password}"/>
<property name="testOnBorrow" value="true"/>
<property name="testOnReturn" value="true"/>
<property name="testWhileIdle" value="true"/>
<property name="timeBetweenEvictionRunsMillis" value="1800000"/>
<property name="numTestsPerEvictionRun" value="3"/>
<property name="minEvictableIdleTimeMillis" value="1800000"/>
<property name="validationQuery" value="SELECT 1"/>
</bean>
<bean class="org.springframework.orm.jpa.JpaTransactionManager" id="transactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<tx:annotation-driven mode="aspectj" transaction-manager="transactionManager"/>
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory">
<property name="persistenceUnitName" value="persistenceUnit"/>
<property name="dataSource" ref="dataSource"/>
</bean>
<bean class="org.springframework.mail.javamail.JavaMailSenderImpl" id="mailSender">
<property name="host" value="${email.host}"/>
</bean>
<bean class="org.springframework.mail.SimpleMailMessage" id="templateMessage">
<property name="from" value="${email.from}"/>
<property name="subject" value="${email.subject}"/>
</bean>
</beans>

webmvc-config.xml(编辑以删除我客户的名字):

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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 http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">

<!-- The controllers are autodetected POJOs labeled with the @Controller annotation. -->
<context:component-scan base-package="com.myProjectName" use-default-filters="false">
<context:include-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
</context:component-scan>


<!-- Turns on support for mapping requests to Spring MVC @Controller methods
Also registers default Formatters and Validators for use across all @Controllers -->
<mvc:annotation-driven conversion-service="applicationConversionService"/>

<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources -->
<mvc:resources location="/, classpath:/META-INF/web-resources/" mapping="/resources/**"/>

<!-- Allows for mapping the DispatcherServlet to "/" by forwarding static resource requests to the container's default Servlet -->
<mvc:default-servlet-handler/>

<!-- register "global" interceptor beans to apply to all registered HandlerMappings -->
<mvc:interceptors>
<bean class="org.springframework.web.servlet.theme.ThemeChangeInterceptor"/>
<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor" p:paramName="lang"/>
</mvc:interceptors>

<!-- selects a static view for rendering without the need for an explicit controller -->
<mvc:view-controller path="/login"/>
<mvc:view-controller path="/admin" view-name="admin"/>
<mvc:view-controller path="/" view-name="index"/>
<mvc:view-controller path="/uncaughtException"/>
<mvc:view-controller path="/resourceNotFound"/>
<mvc:view-controller path="/dataAccessFailure"/>

<!-- Resolves localized messages*.properties and application.properties files in the application to allow for internationalization.
The messages*.properties files translate Roo generated messages which are part of the admin interface, the application.properties
resource bundle localizes all application specific messages such as entity names and menu items. -->
<bean class="org.springframework.context.support.ReloadableResourceBundleMessageSource" id="messageSource" p:basenames="WEB-INF/i18n/messages,WEB-INF/i18n/application" p:fallbackToSystemLocale="false"/>

<!-- store preferred language configuration in a cookie -->
<bean class="org.springframework.web.servlet.i18n.CookieLocaleResolver" id="localeResolver" p:cookieName="locale"/>

<!-- resolves localized <theme_name>.properties files in the classpath to allow for theme support -->
<bean class="org.springframework.ui.context.support.ResourceBundleThemeSource" id="themeSource"/>

<!-- store preferred theme configuration in a cookie -->
<bean class="org.springframework.web.servlet.theme.CookieThemeResolver" id="themeResolver" p:cookieName="theme" p:defaultThemeName="standard"/>

<!-- This bean resolves specific types of exceptions to corresponding logical - view names for error views.
The default behaviour of DispatcherServlet - is to propagate all exceptions to the servlet container:
this will happen - here with all other types of exceptions. -->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver" p:defaultErrorView="uncaughtException">
<property name="exceptionMappings">
<props>
<prop key=".DataAccessException">dataAccessFailure</prop>
<prop key=".NoSuchRequestHandlingMethodException">resourceNotFound</prop>
<prop key=".TypeMismatchException">resourceNotFound</prop>
<prop key=".MissingServletRequestParameterException">resourceNotFound</prop>
</props>
</property>
</bean>

<!-- allows for integration of file upload functionality -->
<bean class="org.springframework.web.multipart.commons.CommonsMultipartResolver" id="multipartResolver"/>
<bean class="com.mavenmanagement.web.ApplicationConversionServiceFactoryBean" id="applicationConversionService"/>
<bean class="org.springframework.web.servlet.view.UrlBasedViewResolver" id="tilesViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.tiles2.TilesView"/>
</bean>
<bean class="org.springframework.web.servlet.view.tiles2.TilesConfigurer" id="tilesConfigurer">
<property name="definitions">
<list>
<value>/WEB-INF/layouts/layouts.xml</value>
<!-- Scan views directory for Tiles configurations -->
<value>/WEB-INF/views/**/views.xml</value>
</list>
</property>
</bean>
</beans>

我看到注释扫描上的过滤在 applicationContext 级别阻止了 @Controller,并在 webmvc-config 级别启用了它们。所以我认为这并不能解释双重实例化。

最佳答案

@Tomasz Nurkiewicz 和@Inerdial 在问题评论中的提示让我想到了完全不同的方式,这更简单并且工作出色,但我还没有在任何地方看到它的记录。

在 applicationContext.xml 的底部,我正在实例化一个 JdbcTemplate 对象:

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

然后我只是将它@AutoWire 到我需要它的 Controller 中:

@Autowired
private JdbcTemplate jdbcTemplate;

Bob 的你叔叔,我现在可以与 this.jdbcTemplate 中的完全配置的模板对象对话。

为什么这个 Controller 类被实例化两次是因为我从 applicationContext.xml 启动它以尝试配置它的数据源。然后创建了由 @Controller 注释实例化的版本,但没有配置。这就是问题所在。

我还听从了评论中的其他建议,将此查询函数移动到模型类型类中,并从我的 View Controller 中调用它。是的,显然 View Controller 中的数据库交互是可憎的。

关于java - Spring Controller 中的 JDBCTemplate,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9036853/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com