【问题标题】:Hibernate: Mapping custom column names in stored procedure named queryHibernate:在名为查询的存储过程中映射自定义列名
【发布时间】:2011-06-19 07:56:51
【问题描述】:

我目前有以下围绕存储过程的命名查询:-

<hibernate-mapping>
    <sql-query name="mySp">
        <return-scalar column="name_first" type="string" />
        <return-scalar column="name_last" type="string" />

        { call some_sp :param }
    </sql-query>
</hibernate-mapping>

name_firstname_last 列是存储过程返回的确切列名。我创建了一个包含相同列名的 bean,以便我可以将查询结果映射到该 bean。

public class MyBean {
    private String  name_first;
    private String  name_last;  

    ...
}

调用命名查询并将结果映射到 bean 的 Hibernate 代码:-

MyBean myBean = (MyBean) sessionFactory.getCurrentSession()
                        .getNamedQuery("mySp")
                        .setParameter("param", param)
                        .setResultTransformer(Transformers.aliasToBean(MyBean.class))
                        .uniqueResult();

所有这些都可以正常工作,但我不想依赖存储过程中的列名,而是想在MyBean 中使用我自己的列名,例如:-

public class MyBean {
    private String  firstName; // instead of name_first
    private String  lastName;  // instead of name_last  

    ...
}

如何将我的列名映射到上述命名查询中存储过程的列?

谢谢。

更新 - 我在下面添加了我的最终解决方案。

【问题讨论】:

    标签: java hibernate stored-procedures named-query


    【解决方案1】:

    【讨论】:

    • 谢谢,我在Answers 部分添加了我的最终解决方案。
    【解决方案2】:

    只需手动构建您的 bean:

    Object[] columns = (Object[]) sessionFactory.getCurrentSession()
                            .getNamedQuery("mySp")
                            .setParameter("param", param)
                            .uniqueResult();
    MyBean myBean = new MyBean((String) columns[0], (String) columns[1]);
    

    这还有一个额外的好处:它可以让你的 MyBean 不可变。

    【讨论】:

      【解决方案3】:

      根据@partenon 对使用自定义ResultTransformer 的回答,这是最终解决方案:-

      MyBean myBean = (MyBean) sessionFactory.getCurrentSession()
                          .getNamedQuery("mySp")
                          .setParameter("param", param)
                          .setResultTransformer(new BasicTransformerAdapter() {
                              private static final long   serialVersionUID    = 1L;
      
                              @Override
                              public Object transformTuple(Object[] tuple, String[] aliases) {
                                  String firstName = (String) tuple[0];
                                  String lastName = (String) tuple[1];
      
                                  return new MyBean(firstName, lastName);
                              }
                          })
                          .uniqueResult();
      

      【讨论】:

      • limc,您是否有异常,例如: org.hibernate.loader.Loader.processResultSet(Loader.java:950) at org.hibernate.loader 的线程“main”java.lang.NullPointerException 中的异常.Loader.doQuery(Loader.java:921) 在 org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:355) 在 org.hibernate.loader.Loader.doList(Loader.java:2554) 在 org.hibernate。 org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2370) 上的 loader.Loader.doList(Loader.java:2540)?
      【解决方案4】:

      对于非托管和非实体类型,您仍然希望使用支持 @Column 注释的类型转换器。方法如下:

      这里是实体类型:

      @Data /* lombok */
      public class MyType {
          @Column(name = "field1")
          private String normalFieldName;
          @Column(name = "field2")
          private String normalFieldNameAnother;
      }
      

      这里是仓库功能代码:

        // alias mapper that do convert from column manes to field names based on @Column annotation 
          Function<String[], String[]> aliasesTransformer = new Function<String[], String[]>() {
              private final Map<String, Field> fieldAliasToField = Stream.of(FieldUtils.getFieldsWithAnnotation(MyType.class, Column.class))
                      .collect(Collectors.toMap(f -> f.getAnnotation(Column.class).name(), Functions.identity()));
              @Override
              public String[] apply(String[] o) {
                  return Stream.of(o).map(el -> {
                      if (fieldAliasToField.containsKey(el)) {
                          return fieldAliasToField.get(el).getName();
                      } else {
                          return el;
                      }
                  }).toArray(String[]::new);
              }
          };
      
      String sql = "select\n"
                  + "    h.field1, "
                  + "    s.field2, "
                  + "from "
                  + "    table1 s, "
                  + "    table2 h "
                  + "where "
                  + "    s.common_key = h.common_key";
          EntityManager em = emf.createEntityManager();
          //noinspection unchecked
          List<MyType> res = (List<MyType>)em.createNativeQuery(sql)
                  .unwrap(org.hibernate.query.Query.class)
                  .setResultTransformer(new AliasToBeanResultTransformer(MyType.class) {
                      @Override
                      public Object transformTuple(Object[] tuple, String[] aliases) {
                          return super.transformTuple(tuple, aliasesTransformer.apply(aliases));
                      }
                  }).list();
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-02-11
        • 1970-01-01
        • 2016-09-22
        • 1970-01-01
        • 2014-08-26
        • 1970-01-01
        • 2012-06-24
        相关资源
        最近更新 更多