使用Spring JDBC的PreparedStatementCreator的正确方法是什么?

2023-12-19

据我了解,Java中PreparedStatement的使用是我们可以多次使用它。 但是我在使用Spring JDBC的PreparedStatementCreator时有些困惑。

例如考虑以下代码,

public class SpringTest {

    JdbcTemplate jdbcTemplate; 
    PreparedStatementCreator preparedStatementCreator; 
    ResultSetExtractor<String> resultSetExtractor;

    public SpringTest() throws SQLException {

        jdbcTemplate = new JdbcTemplate(OracleUtil.getDataSource());

        preparedStatementCreator = new PreparedStatementCreator() {
            String query = "select NAME from TABLE1  where ID=?";
            public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
                return connection.prepareStatement(query);
            }
        };

        resultSetExtractor  = new ResultSetExtractor<String>() {
            public String extractData(ResultSet resultSet) throws SQLException,
            DataAccessException {
                if (resultSet.next()) {
                    return resultSet.getString(1);
                }
                return null;
            }
        };
    }
    public String getNameFromId(int id){
        return jdbcTemplate.query(preparedStatementCreator, new Table1Setter(id), resultSetExtractor);
    }

    private static class Table1Setter implements PreparedStatementSetter{

        private int id;
        public Table1Setter(int id) {
            this.id =id;
        }
        @Override
        public void setValues(PreparedStatement preparedStatement) throws SQLException {
            preparedStatement.setInt(1, id);
        }
    }
    public static void main(String[] args) {
        try {
            SpringTest  springTest = new SpringTest();

            for(int i=0;i<10;i++){
                System.out.println(springTest.getNameFromId(i));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

根据这段代码,当我调用 springTest.getNameFromId(int id) 方法时,它从给定的 id 返回名称,这里我使用PreparedStatementCreator 来创建PreparedStatement,使用PreparedStatementSetter 来设置输入参数,并从 ResultSetExtractor 获得结果。 但性能非常慢。

在调试并研究了PreparedStatementCreator和JdbcTemplate内部发生的情况之后,我知道PreparedStatementCreator每次都会创建新的PreparedStatement......!

每次我调用方法 jdbcTemplate.query(preparedStatementCreator,preparedStatementSetter,resultSetExtractor) 时,它都会创建新的PreparedStatement,这会降低性能。

这是使用PreparedStatementCreator的正确方法吗?因为在这段代码中我无法重用PreparedStatement。如果这是使用PreparedStatementCreator的正确方法,那么如何获得PreparedStatement的可重用性的好处呢?


准备好的语句通常由底层连接池缓存,因此您无需担心每次都创建新的语句。

所以我认为你的实际用法是正确的。

JdbcTemplate 在执行后关闭语句,因此如果您确实想重用相同的准备好的语句,您可以代理该语句并拦截语句创建者中的 close 方法

例如(未测试,仅作为示例):

public abstract class ReusablePreparedStatementCreator implements PreparedStatementCreator {

    private PreparedStatement statement;

    public PreparedStatement createPreparedStatement(Connection conn) throws SQLException {
        if (statement != null)
            return statement;

        PreparedStatement ps = doPreparedStatement(conn);

        ProxyFactory pf = new ProxyFactory(ps);
        MethodInterceptor closeMethodInterceptor = new MethodInterceptor() {

            @Override
            public Object invoke(MethodInvocation invocation) throws Throwable {
                return null;  // don't close statement
            }
        };

        NameMatchMethodPointcutAdvisor closeAdvisor = new NameMatchMethodPointcutAdvisor();
        closeAdvisor.setMappedName("close");
        closeAdvisor.setAdvice(closeMethodInterceptor);
        pf.addAdvisor(closeAdvisor);

        statement = (PreparedStatement) pf.getProxy();

        return statement;       
    }

    public abstract PreparedStatement doPreparedStatement(Connection conn) throws SQLException;

    public void close() {
        try {
            PreparedStatement ps = (PreparedStatement) ((Advised) statement).getTargetSource().getTarget();
            ps.close();
        } catch (Exception e) {
            // handle exception
        }
    }

}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用Spring JDBC的PreparedStatementCreator的正确方法是什么? 的相关文章

随机推荐

  • 防止 HTML 源代码窃取 [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 最近我为一个人做了一些网页设计工作 我继续向他展示了我的开发服务器上他的新网站的链接 向他展示了进展 临近完成时 他断绝了与我的所有联
  • 使用 Java 查找并替换文本文件中的单词

    我正在尝试使用 Java 查找并替换文本文件中的某些单词 我的代码在一定程度上有效 但是我得到的输出是错误的 我需要用用户输入替换文本文件中一行中的多个单词 但是 当我运行代码时 该行会为我尝试替换的每个单词复制一次 例如 如果我想替换以下
  • Java Web 服务向 .net 客户端返回 null 对象

    任何人都可以弄清楚我的问题是 我正在从 Net 客户端调用 Java Web 服务 Axis 1 4 的 webmethod 该方法返回一个 Map 对象 如果我从 Axis 客户端调用它 效果很好 但在我的 C 代码中 它始终为 null
  • 如何在javascript中检查图像是否是损坏的图像

    我从 Twitter 获取个人资料图像并将图像 URL 存储在我的数据库中 某些网址给出了损坏的图像 其中网址以图像扩展名结尾 任何人都可以帮助我检查图像是有效图像还是损坏的图像 如果存在损坏的图像 我需要显示默认图像 var image
  • NSSearchPathForDirectoriesInDomains 和持久数据的问题

    根据建议 我们使用以下代码来检索用户文档的路径 NSArray paths NSSearchPathForDirectoriesInDomains NSDocumentDirectory NSUserDomainMask YES NSStr
  • 如何在页面对象模式中使用 WebDriver / Selenium 2 加载组件?

    我很难适应 WebDriver 页面对象模式 请分享您使用页面对象模式和可加载组件的经验和方法 由于 PageObject 通常代表一个组件或一项功能 因此我首先想到应该使用它在 load 中实际执行一些操作 并查看它是否执行 isLoad
  • Java:通用函数X->Y接口

    我需要一个像这样的界面 interface Function
  • 如何在不打开摄像机的情况下录制视频?

    如何在不打开任何相机的情况下录制视频 我的要求是 当一个人遇到问题时 他的视频会被记录下来 但不是通过打开摄像头 它应该在后台工作 Thanks Use AV基础框架 http developer apple com library ios
  • 按特定字形划分字体子集

    我有一个 14MB 的 TTF 其中大部分是简体中文字符 我想通过创建一个仅包含 HTML 页面中特定字符的子集来减小大小 因此 理想情况下 我想向 Linux 程序传递一段文本 并让它根据包含的字符重新创建字体 E g magic fon
  • 为什么按值返回列表初始化对象时不调用复制构造函数?

    据我了解 当从函数按值返回对象时 会调用它们的复制构造函数 如果类具有已删除的复制构造函数 则按值返回将失败 struct X X const X delete X f return X error call to deleted cons
  • 有人看到我的港口号的正则有什么问题吗?

    我为端口号做了一条正则 在您说这是一个坏主意之前 它都会陷入更大的url正则义务 这比听起来要难得多 我的同事说这真的很糟糕 不会抓住一切 我不同意 我相信这个东西可以捕获从 0 到 65535 的所有内容没有其他的 我正在寻找对此的确认
  • 确保“重新启动”任务在其之前自动运行:测试

    是否有可能获得re start 又名重新启动 任务在运行 IntegrationTest 目标之前自动运行 it test 我以为这样就可以了 test lt lt test in IntegrationTest dependsOn reS
  • 如何在android中实现均衡器

    我必须在 android 中实现均衡器 我还发现源代码在这里 http kevinboone net android simple eq html 但我不知道 NumberOfBands 和 BandLevelRange 它们是什么 以及如
  • 临时更改 perl 系统调用中的默认 shell

    情况是这样的 在 Perl 中 我运行这个 my stat system cd somewhere source somescript bash do something else 对于我的所有用户 除了一名用户 来说 这都不是问题 但对于
  • .NET Framework 的目标版本与启动条件不匹配

    我有一个在 VS 2010 中构建的 C 项目 它通过 COM 引用 C 项目 这也是解决方案的一部分 上周五 我成功构建了一个版本 更改了一行代码 又进行了另一个构建 然后我开始收到有关 NET 的错误 项目中 NET Framework
  • 子例程中的默认参数值

    我不知道如何设置子例程的默认参数 这是我的考虑 sub hello print Hello world 如果您只需要一个参数 那么这很有效 如何为多个参数设置默认值 我本来打算这样做 sub hello my say 0 Hello my
  • 如何在 Java 中从内存中“清零”AES SecretKeySpec 密钥

    我正在使用 Java AES 加密 SecretKeySpec byte key String algorithm 生成一个Key对象 加密某些内容后 我想从内存中删除密钥 我可以删除对密钥的所有引用 但这并不能保证密钥不会浮动在内存中的某
  • 模型中默认范围内的参数

    我正在使用 Devise 来验证用户身份 我需要在所有表中显示 隐藏基于 global location id 列的数据 当前global location id的值将来自current user global location id 我尝
  • 使用 Azure BrokeredMessage 在不知道类型的情况下获取正文

    当您在 Azure 服务总线中使用中转消息时 可以通过调用 GetBody 检索消息正文 代码很简单 var msg subscription Receive MyPayload payload msg GetBody
  • 使用Spring JDBC的PreparedStatementCreator的正确方法是什么?

    据我了解 Java中PreparedStatement的使用是我们可以多次使用它 但是我在使用Spring JDBC的PreparedStatementCreator时有些困惑 例如考虑以下代码 public class SpringTes