I have a really ugly legacy database system that I need to integrate with. Essentially I'm doing some read only reporting on the system, and I don't want to set up a thousand entities representing each of the tables that I'm working on. Instead, I'd like to just define an Entity for each of the report-types that I generate (essentially a union of a bunch of columns from different tables), and then let hibernate map from the nasty (many joined, many unioned) sql query to a list of such entities.
The question is: can I create an entity that doesn't have an underlying table, and use a sql statement to populate a list of said entities?
Thanks!
Not with Hibernate. It requires a primary key.
Of-course if you use it only for querying purpose then it should be fine.
More precisely, a JPA entity must have some Id defined. But a JPA Id does not necessarily have to be mapped on the table primary key (and JPA can somehow deal with a table without a primary key or unique constraint).
Entity means the class which you will use in your program and Table means the actual Database table that you will access through your program. Hibernate being an ORM requires you to declare the relationship between the tables and the classes mapping to them.
We do that sort of thing all the time - and here is how we do it:
Define a simple bean-like object to represent each row of output in your report:
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; }
}
Define a hibernate mapping file, 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">
<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>
Then run the query and populate instances:
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;
}
Use an Entity query:
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);
Or create a view in the database and map against that.
Here's a longer tutorial using 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();
}
If you're free to choose hibernate or not, I suggest you take a look at Spring JDBC. it's lighter than hibernate and does the job right. With your requirements it will suit nicely into the picture.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With