简体   繁体   中英

Hibernate - Complex Query from multiple Tables to one object

I have a complex query crossing 7 tables and want to know how to implement it within Hibernate.

My current attempt is to make the query using session.createSQLQuery and I would map the result to a particular entity.

I am not sure how to do that as in the past I have only worked with one table to one entity. Where would I need to specify that I would like to use a complex query that could span multiple tables? Does that go only in my code? My hbm.xml file? I can't think of anything else beyond my current attempt.

Here is an example of my query:

String stringQuery = 
        "select  WI.Customer_Id, CU.Card, CU.Code, "+
                "PI.Identity_Card, PI.Name, PI.Surname, PI.Gender, "+
                "AD.Zip, AD.Geo_Lat, AD.Geo_Long, "+
                "CO.City_Geo_Level, "+
                "CU.Address_id, CA.Name, "+
                "CU.Category_Id, "+
                "CU.Status, "+
                "Sum(MO.Charged_Points) as Charged_Points, "+
                "Sum(MO.Total_Money) as Total_Money, "+
                "Count(MO.id) as AmountTransWinner "+
        "from Promotions_Winner WI "+ 
        "join Customers CU "+
          "on WI.Customer_id = CU.id "+
        "join Personal_Info PI "+
          "on CU.Personal_Info_Id = PI.id "+
        "join Address AD "+
          "on CU.Address_Id = AD.id "+
        "join Countries CO "+
          "on AD.country_id = CO.id "+
        "join Campaigns CA "+
          "on CU.Campaign_Id = CA.id "+
        "join Movements MO "+
          "on WI.Movement_Id = MO.id "+
        "where WI.Promotion_Id = :pPromotionID "+
        "group by "+
          "WI.Customer_Id, CU.Card, CU.Fidely_Code, "+
          "PI.Identity_Card, PI.Name, PI.Surname, PI.Gender, "+
          "AD.Zip, AD.Geo_Lat, AD.Geo_Long, "+
          "CO.City_Geo_Level, "+
          "CU.Address_id, CA.Name, "+
          "CU.Category_Id, "+
          "CU.Status";

Their are two ways to do this.

1. You will get a list object array.

 List<Object[]>

Here one element of array represent one row of your query.

2. You can use a hibernate feature ResultTransformer - Create a simple class for the output of your query. - Create a ResultTransformer.

Ex.

 public class MyResultTransformer implements ResultTransformer {


/*
Method to convert to generic type list
*/
    @Override
    public List<Employee> transformList(List arg0) {
        List<Employee> employees = new ArrayList<Employee>();
        for (Object employee : arg0) {
            employees.add((Employee) employee);
        }
        return employees;
    }

    /*
    Code to transform your query output to Object
    */
    @Override
    public Employee transformTuple(Object[] arg0, String[] arg1) {
        System.out.println("MyResultTransformer.transformTuple()");
        Employee tempEmp = new Employee();
        tempEmp.setEmployee_id((BigInteger) arg0[0]);
        return tempEmp;
    }
}

- set transformer to the query.

Query query=session.createSQLQuery("SELECT * FROM employeedetail"); // You can use named query, SQL native also
      query.setResultTransformer(new MyResultTransformer());
          List<Employee> employees=query.list();

You don't need SQL to execute this query. HQL will do fine. And such a query returns a List<Object[]> , each Object[] containing a row of the result set. So you will find the customer ID at index 0, the card at index 1, etc. You just have to loop througn the rows and create an instance of your lightweight object at each iteration.

See http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html_single/#queryhql-select

Finally I could solved using this code:

String stringQuery = 
                "select " +
                        "CU.Card as card, " +
                        "CU.Fidely_Code as fidelyCode, "+
                        "PI.Identity_Card as identityCard, " +
                        "PI.Name as name, " +
                        "PI.Surname as surname, " +
                        "PI.Gender as gender, "+
                        "AD.Zip as zip, " +
                        "AD.Geo_Lat as geo_lat, " +
                        "AD.Geo_Long as geo_long, "+
                        "CO.City_Geo_Level as cityGeoLevel, "+
                        "CA.Name as campaignName, "+
                        "CU.Status as status, "+
                        "Sum(MO.Charged_Points) as pointsCharged, "+
                        "Sum(MO.Total_Money) as amountPurchase, "+
                        "Count(MO.id) as amountTransWinner "+
                "from Promotions_Winner WI "+ 
                "join Customers CU "+
                  "on WI.Customer_id = CU.id "+
                "join Personal_Info PI "+
                  "on CU.Personal_Info_Id = PI.id "+
                "join Address AD "+
                  "on CU.Address_Id = AD.id "+
                "join Countries CO "+
                  "on AD.country_id = CO.id "+
                "join Campaigns CA "+
                  "on CU.Campaign_Id = CA.id "+
                "join Movements MO "+
                  "on WI.Movement_Id = MO.id "+
                "where WI.Promotion_Id = :pPromotionID "+
                "group by "+
                  "WI.Customer_Id, CU.Card, CU.Fidely_Code, "+
                  "PI.Identity_Card, PI.Name, PI.Surname, PI.Gender, "+
                  "AD.Zip, AD.Geo_Lat, AD.Geo_Long, "+
                  "CO.City_Geo_Level, "+
                  "CU.Address_id, CA.Name, "+
                  "CU.Category_Id, "+
                  "CU.Status ";

        //Query query = this.getSession().createSQLQuery(stringQuery).addEntity("", PromotionsWinnerLittle.class);
        //Query query = this.getSession().createSQLQuery(stringQuery).setResultSetMapping("PromotionsWinnerLittle");
        Query query = this.getSession().createSQLQuery(stringQuery)
            .addScalar("card", StandardBasicTypes.LONG)
            .addScalar("fidelyCode", StandardBasicTypes.LONG)
            .addScalar("identityCard", StandardBasicTypes.STRING)
            .addScalar("name", StandardBasicTypes.STRING)
            .addScalar("surname", StandardBasicTypes.STRING)
            .addScalar("gender", StandardBasicTypes.STRING)
            .addScalar("zip", StandardBasicTypes.STRING)
            .addScalar("geo_lat", StandardBasicTypes.BIG_DECIMAL)
            .addScalar("geo_long", StandardBasicTypes.BIG_DECIMAL)
            .addScalar("cityGeoLevel", StandardBasicTypes.LONG)
            .addScalar("campaignName", StandardBasicTypes.STRING)
            .addScalar("status", StandardBasicTypes.LONG)
            .addScalar("pointsCharged", StandardBasicTypes.BIG_DECIMAL)
            .addScalar("amountPurchase", StandardBasicTypes.LONG)
            .addScalar("amountTransWinner", StandardBasicTypes.LONG)            
            .setResultTransformer(Transformers.aliasToBean(PromotionsWinnerLittle.class));

        //Query query = this.getSession().createSQLQuery(stringQuery);

        query = query.setLong("pPromotionID", promotionID);

        List lista = query.list();

I Just added the "As" part on Select and the addScalar + setResultTransformer

So as far as I can see this is a join of 7 tables. If you're using hibernate you'd map each of these tables to entities and then use @JoinColumn to map to each of it's dependencies. This is the sort of SQL query that hibernate is there to prevent occuring.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM