2011-11-03 66 views
10

我有一个非常难看的遗留数据库系统,我需要与之集成。基本上,我正在做一些只读的系统报告,而且我不想设置代表我正在使用的每个表的一千个实体。相反,我想为每个我生成的报告类型定义一个实体(基本上是来自不同表格的一堆列的联合),然后让这个讨厌的(许多联合的,许多联合的)hibernate映射, sql查询到这些实体的列表。没有基础表的休眠实体

问题是:我可以创建一个没有基础表的实体,并使用sql语句填充所述实体列表吗?

谢谢!

回答

8

我们做这种事情所有的时间 - 这里是我们如何做到这一点:

  1. 定义一个简单的bean类对象,以表示你的报表输出的每一行:

    public class CityStateRevenueReport { 
    
        private String mId; 
        private String mState; 
        private String mCity; 
        private Double mRevenue; 
    
        public String getId() { return mId; } 
        public void setId(String i) { mId = i; } 
        public String getState() { return mState; } 
        public void setState(String s) { mState = s; } 
        public String getCity() { return mCity; } 
        public void setCity(String c) { mCity = c; } 
        public Double getReveneue() { return mRevenue; } 
        public void setRevneue(Double d) { mRevenue = d; } 
    } 
    
  2. 定义休眠映射文件,CityStateRevneueReport.hbm.xml:

    <?xml version="1.0" ?> 
    <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd&quot;> 
    <hibernate-mapping> 
        <class entity-name="CityStateRevenueReport"> 
         <id name="Id" type="java.lang.String" column="report_id"> 
          <generator class="sequence" /> 
         </id> 
         <property name="city" type="string" column="city" /> 
         <property name="state" type="string" column="state" /> 
         <property name="revenue" type="double" column="revenue" /> 
        </class> 
        <sql-query name="runReport"> 
         <![CDATA[ 
         SELECT {r.*} FROM 
          (select some_id_value as report_id, 
            state_abbreviation as state, 
            city_name as city, 
            dollar_amount as revenue 
           from -- tables, joins, other SQL insanity 
          ) r 
         ]]> 
         <return alias="r" class="CityStateRevenueReport" /> 
        </sql-query> 
    </hibernate-mapping> 
    
  3. 个然后运行查询并填充实例:

    public List<CityStateRevenueReport> runReport() { 
    
        List<CityStateRevenueReport> reports = 
              new ArrayList<CityStateRevenueReport>(); 
        List<HashMap> maps = session.getNamedQuery("runReport").list() 
        for (HashMap map : results) { 
         CityStateRevenueReport report = new CityStateRevenueReport(); 
         report.setState(map.get("state")); 
         report.setCity(map.get("city")); 
         report.setRevenue(Double.parseDouble(map.get("revenue")); 
         reports.add(report); 
        } 
        return reports; 
    } 
    
+0

我更改为这个答案,因为它使用Hibernate并更好地回答了原始问题。 – idbentley

+0

在hibernate映射类中,应该使用“name”而不是“entity-name”,并且hibernate将能够自行创建结果对象,而无需使用样板代码手动创建它们。 这将是很好,如果这只能用注释完成,但我找不到方法。 –

3

使用实体查询:

http://docs.jboss.org/hibernate/core/3.3/reference/en/html/querysql.html#d0e13696

sess.createSQLQuery("SELECT ID, NAME, BIRTHDATE FROM CATS").addEntity(Cat.class); 

或者在数据库中创建一个视图和地图对抗。

这里有一个较长的教程使用addEntity:

http://timezra.blogspot.com/2009/05/mapping-hibernate-entities-to-views.html

private Collection<AuthorAggregate> findByFirstName() { 
    return sessionFactory.getCurrentSession() // 
      .createSQLQuery(AUTHORS_BY_FIRST_NAME) // 
      .addEntity(AuthorAggregate.class) // 
      .list(); 
} 
2

如果你可以自由选择休眠或没有,我建议你看一看Spring JDBC。它比休眠更轻,并且能够完成工作。根据您的要求,它会很好地适合照片。

+0

非常感谢 - 这似乎是我需要一个更好的解决方案。 – idbentley