Mysql Ebean调用存储过程并将结果集转换为模型

Mysql Ebean调用存储过程并将结果集转换为模型,mysql,stored-procedures,playframework-2.0,resultset,ebean,Mysql,Stored Procedures,Playframework 2.0,Resultset,Ebean,我在报表模块中工作,为此我创建了不同的存储过程。我使用in参数创建过程,然后创建一个类来映射行(resultSet) 我认为这是提高性能和清晰度的最佳方法。(你怎么看?) 我正在使用play框架和ebean orm(2.7.7) 我正在调用存储过程并获取结果集,但是我想使用ebean自动将行转换为model。。。另一种选择是将行单元格转换为属性,但我试图避免它 这是当前的方法 这是调用存储过程的最佳方式吗? Transaction tx = Ebean.beginTransaction(

我在报表模块中工作,为此我创建了不同的存储过程。我使用in参数创建过程,然后创建一个类来映射行(resultSet) 我认为这是提高性能和清晰度的最佳方法。(你怎么看?

我正在使用play框架和ebean orm(2.7.7)

我正在调用存储过程并获取结果集,但是我想使用ebean自动将行转换为model。。。另一种选择是将行单元格转换为属性,但我试图避免它

这是当前的方法
这是调用存储过程的最佳方式吗?

    Transaction tx = Ebean.beginTransaction();
    String sql = "{CALL report(?, ?, ?, ?, ?, ?)}";

    CallableStatement callableStatement = null;

    try {

        Connection dbConnection = tx.getConnection();

        callableStatement = dbConnection.prepareCall(sql);

        callableStatement.setInt(1, 3);
        callableStatement.setInt(2, 5);
        callableStatement.setInt(3, 2013);
        callableStatement.setInt(4, 1);
        callableStatement.setInt(5, 2014);
        callableStatement.setInt(6, 5);

        ResultSet rs = callableStatement.executeQuery(sql);


        while (rs.next()) {
            //HOW TO CONVER row -> model ?
        }

        Ebean.commitTransaction();

    } catch (SQLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
我已放弃RawSQL和查询,因为收到错误
运行时异常:分析sql时出错,在:xxxxx中找不到SELECT关键字

我还找到了其他选择。。。使用CallableSql

 String sql = "{call sp_order_mod(?,?)}";

 CallableSql cs = Ebean.createCallableSql(sql);

 cs.setParameter(1, "turbo");
 cs.registerOut(2, Types.INTEGER);

 Ebean.execute(cs);

 // read the out parameter
 Integer returnValue = (Integer) cs.getObject(2);

但是在这种情况下,我需要返回一个ResultSet,而不仅仅是参数

目前,在Ebean中对存储过程的支持并不针对您正在尝试做的事情。因此,您不会从使用CallableSql或RawSql中获得太多乐趣

>>一个映射行的类(resultSet)我认为这是解决性能和清晰度问题的最佳方法

是的,我能理解你的动机

>>如何将结果集转换为模型

目前没有好的解决办法。最好的解决方案是增强RawSql,以便可以在其上设置ResultSet。RawSql所做的一件事是提供resultSet列到模型属性的映射,而这正是Ebean内部需要的。增强/代码更改将能够在RawSql对象上设置resultSet。。。并让Ebean在内部跳过resultSet(preparedStatement、binding参数和executeQuery()的创建)。就Ebean内部而言,这都是在CQuery.prepareBindExecuteQueryWithOption()方法中完成的。也就是说,如果RawSql已经提供了一个resultSet,那么跳过这些内容

这样做而不仅仅滚动您自己的行->模型映射代码的最大好处是,生成的bean仍然具有延迟加载/部分对象知识等。它们的行为与Ebean作为it查询机制的一部分构建的任何其他bean完全相同

也就是说,我个人要离开一周。。。所以在那之前你不会收到我的回复。如果您想亲自进入其中,则需要修改CQuery.prepareBindExecuteQueryWithOption()内部代码

如果你一直在关注ebean谷歌小组,你会知道,但以防万一,你还没有注意到,Play中的Model和Finder对象就在上周被合并到ebean中。这有助于两个项目。。。减少了混乱等。github master中的Ebean源代码是4.0.4,4.x中的字节码增强是不同的,我不相信在游戏中支持

我现在基本上要离线一个星期,所以我会在那之后回顾这件事


干杯,Rob。

目前,Ebean中对存储过程的支持并不针对您要做的事情。因此,您不会从使用CallableSql或RawSql中获得太多乐趣

>>一个映射行的类(resultSet)我认为这是解决性能和清晰度问题的最佳方法

是的,我能理解你的动机

>>如何将结果集转换为模型

目前没有好的解决办法。最好的解决方案是增强RawSql,以便可以在其上设置ResultSet。RawSql所做的一件事是提供resultSet列到模型属性的映射,而这正是Ebean内部需要的。增强/代码更改将能够在RawSql对象上设置resultSet。。。并让Ebean在内部跳过resultSet(preparedStatement、binding参数和executeQuery()的创建)。就Ebean内部而言,这都是在CQuery.prepareBindExecuteQueryWithOption()方法中完成的。也就是说,如果RawSql已经提供了一个resultSet,那么跳过这些内容

这样做而不仅仅滚动您自己的行->模型映射代码的最大好处是,生成的bean仍然具有延迟加载/部分对象知识等。它们的行为与Ebean作为it查询机制的一部分构建的任何其他bean完全相同

也就是说,我个人要离开一周。。。所以在那之前你不会收到我的回复。如果您想亲自进入其中,则需要修改CQuery.prepareBindExecuteQueryWithOption()内部代码

如果你一直在关注ebean谷歌小组,你会知道,但以防万一,你还没有注意到,Play中的Model和Finder对象就在上周被合并到ebean中。这有助于两个项目。。。减少了混乱等。github master中的Ebean源代码是4.0.4,4.x中的字节码增强是不同的,我不相信在游戏中支持

我现在基本上要离线一个星期,所以我会在那之后回顾这件事


干杯,罗伯。

我要分享我自己的解决方案

  • 我得到了一个名为ResultSetUtils的类(你可以用谷歌搜索它的一些实现)
  • 为了从resultset返回类型化列表,我添加了一个泛型方法

    public static <T> List<T> populateInList(Class<T> c, final ResultSet rs) {
    
          List<T> listTyped = new ArrayList<T>();
    
          try {
                if (rs != null) {
    
                    while (rs.next()) {
                        T o = c.newInstance();
    
                        // MAGIC LINE
                        populate(o, rs);
    
                        listTyped.add(o);
                    }
    
                    rs.close();
                }
    
            } catch (final Exception e) {
    
                // TODO Auto-generated catch block
                System.err.println(e.getMessage());
            }
    
            return listTyped;
    }
    
  • 报表类(如ReportTestReport)该类应扩展ReportBase

    • 意图:知道存储过程的名称、参数和dto结果

      public class ReportTestReport extends ReportBase<ReportTestResult, ReportTestParam> {
      
          @Override
          protected String getProcedureName() {
      
              return STORED_NAME;
          }
      }
      
      • OptionsHC是一个在HighCharts框架中表示option obj的类

      • 最后一步是将OptionHC转换为Json,并在JavaScript中使用它(highCharts的常见用法)

  • 什么是ReportBase? ReportBase类的策略是
    public interface ReportParam {
    
        public int countParameteres();
        public void setParametersInCallableStatement(CallableStatement callableStatement) throws SQLException;
    }
    
    public class ReportTestReport extends ReportBase<ReportTestResult, ReportTestParam> {
    
        @Override
        protected String getProcedureName() {
    
            return STORED_NAME;
        }
    }
    
    public OptionsHC buildColumnReportV1(){
    
        OptionsHC optionChart = new OptionsHC();
    
        optionChart.chart = new ChartHC("column");
    
        this.setTitle(optionChart);
    
        optionChart.yAxis = new AxisHC(new TitleHC("Fruit eaten"));
    
        .....       
    
        return optionChart;
    }
    
            public class ReportTestReport extends ReportBase<ReportTestResult, ReportTestParam> {
    
            ...
    
                protected List<TResult> execute(Class<TResult> classT) {
    
                    List<TResult> resultDTO = null;
    
                    CallableStatement callableStatement = null;
    
                    Logger.debug("Running procedure> " + this.getProcedureName());
    
                    Transaction tx = Ebean.beginTransaction();
    
                    String sql = ProcedureBuilder.build(this.getProcedureName(), this.countParameters());
    
                    Logger.debug("SQL > " + sql);
    
                    try {
    
                        Connection dbConnection = tx.getConnection();
    
                        callableStatement = dbConnection.prepareCall(sql);
    
                        this.getFilter().setParametersInCallableStatement(callableStatement);
    
                        ResultSet rs = callableStatement.executeQuery();
    
                        resultDTO = ResultSetUtils.populateInList(classT, rs);
    
                        Ebean.commitTransaction();
    
                        Logger.debug("commitTransaction > " + sql);
    
                    } catch (Exception e) {
                        Ebean.rollbackTransaction();
    
                        Logger.debug("rollbackTransaction > " + sql);
    
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }finally{
                        Ebean.endTransaction();
                    }
    
                    return resultDTO;
                }
    
            ...
    
            }