JPA本机查询结果集使用重复数据和列表进行映射

时间:2016-05-11 19:06:40

标签: java jpa jpa-2.0 sqlresultsetmapping

我想将本机查询中的数据映射到包含列表的对象。

假设我有这个问题(这是我想要做的一个人为的例子)

select p.id, p.name, a.address, a.city, s.salestotal, s.salesmonth 
from person p, address a, sales s where <Joined somehow>

它返回此数据

1   John    123 This Street     100 June
1   John    456 That Street     100 June
1   John    789 There Street    100 June
2   Bill    987 Apple Street    321 April
2   Bill    654 Banana Street   321 April
2   Bill    321 Orange Street   321 April
2   Bill    741 Pear Street     321 April
3   Mary    951 Oak Ave         195 May

请注意,人员和销售人员的数据会重复,但地址是唯一的。

所以我想把它映射到一个看起来像这样的对象:

public class PersonSalesAddressSummary{

private Person person;
private Sales sales;
private List<Address> addresses; 
//getters and setters etc...

}

其中Person,Sales和Address都是映射实体。

我最想得到的是3 PersonSalesAddressSummary的列表,但我不确定如何设置结果集映射......我认为这是可能的,但我不知道从哪里开始。甚至一些关于如何正确地表达这个问题的帮助也会有所帮助!

编辑: 更清楚的是,我想最终得到的一个目标是:

PersonSalesAddressSummary
Person = 1 John
Sales = 100 June
List<Address> = 123 This Street,
                456 That Street,
                789 There Street

至少我希望更清楚

2 个答案:

答案 0 :(得分:1)

正如@Nicholas所说,SqlResultSetMapping只会映射列或实体。恕我直言,这是针对您的特殊映射案例的解决方案之一

你的SqlResultSetMapping可能是

@SqlResultSetMapping(name = "PersonSalesAddressSummaryDTOMapping",
    classes = @ConstructorResult(
            targetClass = PersonSalesAddressSummary.class,
            columns = {               
                    @ColumnResult(name = "id", type = Integer.class),
                    @ColumnResult(name = "name"),
                    @ColumnResult(name = "address"),
                    @ColumnResult(name = "city"),
                    @ColumnResult(name = "salestotal", type = Integer.class),
                    @ColumnResult(name = "salesmonth"),
            })

和PersonSalesAddressSummary DTO,对不起详细的源代码

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

public class PersonSalesAddressSummary {

    private static Map<PersonSales, List<Address>> mapPersonSales = new HashMap<>();

    private Person person;
    private Sales sales;
    private List<Address> addresses;

    public PersonSalesAddressSummary(Integer id, String name, String address, String city, Integer salestotal, String salesmonth) {
        Person p = new Person(id, name);
        Sales s = new Sales(salestotal, salesmonth);
        PersonSales ps = new PersonSales(p,s);

        Address a = new Address(address,city);

        Optional<List<Address>> addressList =  Optional.ofNullable(mapPersonSales.get(ps));
        if(addressList.isPresent()){
            addressList.get().add(a);
        }else{
            List<Address> addresses = new ArrayList<>();
            addresses.add(a);
            mapPersonSales.put(ps, addresses);
        }
    }

    class PersonSales {
        private Person person;
        private Sales sales;

        public PersonSales(Person person, Sales sales) {
            this.person = person;
            this.sales = sales;
        }

        public Person getPerson() {
            return person;
        }

        public void setPerson(Person person) {
            this.person = person;
        }

        public Sales getSales() {
            return sales;
        }

        public void setSales(Sales sales) {
            this.sales = sales;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            PersonSales that = (PersonSales) o;
            return Objects.equals(person.getId(), that.getPerson().getId())
                    && Objects.equals(person.getName(), that.getPerson().getName())
                    && Objects.equals(sales.getAmount(), that.getSales().getAmount())
                    && Objects.equals(sales.getMonth(), that.getSales().getMonth())
                    ;
        }

        @Override
        public int hashCode() {
            return Objects.hash(person.getId(), person.getName(), sales.getAmount(), sales.getMonth());
        }

        @Override
        public String toString() {
            final StringBuilder sb = new StringBuilder("PersonSalesAddressSummary ").append("\n");
            sb.append("Person = ").append(person.getId()).append(" ").append(person.getName()).append("\n");
            sb.append("Sales = ").append(sales.getAmount()).append(" ").append(sales.getMonth()).append("\n");
            return sb.toString();
        }
    }

    class Person {

        private Integer id;
        private String name;

        public Person(Integer id, String name) {
            this.id = id;
            this.name = name;
        }

        public Integer getId() {
            return id;
        }

        public void setId(Integer id) {
            this.id = id;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Person person = (Person) o;
            return Objects.equals(id, person.id) &&
                    Objects.equals(name, person.name);
        }

        @Override
        public int hashCode() {
            return Objects.hash(id, name);
        }
    }

    class Sales {
        private Integer amount;
        private String month;

        public Sales(Integer amount, String month) {
            this.amount = amount;
            this.month = month;
        }

        public Integer getAmount() {
            return amount;
        }

        public void setAmount(Integer amount) {
            this.amount = amount;
        }

        public String getMonth() {
            return month;
        }

        public void setMonth(String month) {
            this.month = month;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Sales sales = (Sales) o;
            return Objects.equals(amount, sales.amount) &&
                    Objects.equals(month, sales.month);
        }

        @Override
        public int hashCode() {
            return Objects.hash(amount, month);
        }
    }

    class Address {
        private String address;
        private String city;

        public Address(String address, String city) {
            this.address = address;
            this.city = city;
        }

        public String getAddress() {
            return address;
        }

        public void setAddress(String address) {
            this.address = address;
        }

        public String getCity() {
            return city;
        }

        public void setCity(String city) {
            this.city = city;
        }

        @Override
        public String toString() {
            final StringBuilder sb = new StringBuilder("Address ");
            sb.append(" = ").append(address);
            sb.append(" ").append(city);
            return sb.toString();
        }
    }

    public Person getPerson() {
        return person;
    }

    public void setPerson(Person person) {
        this.person = person;
    }

    public Sales getSales() {
        return sales;
    }

    public void setSales(Sales sales) {
        this.sales = sales;
    }

    public List<Address> getAddresses() {
        return addresses;
    }

    public void setAddresses(List<Address> addresses) {
        this.addresses = addresses;
    }

    public static void main(String[] args){

        new PersonSalesAddressSummary(1, "John", "123", "This Street",      100, "June");
        new PersonSalesAddressSummary(1, "John", "456", "This Street",      100, "June");
        new PersonSalesAddressSummary(1, "John", "789", "There Street",     100, "June");
        new PersonSalesAddressSummary(2, "Bill", "987", "Apple Street",     321, "April");
        new PersonSalesAddressSummary(2, "Bill", "654", "Banana Street",    321, "April");
        new PersonSalesAddressSummary(2, "Bill", "321", "Orange Street",    321, "April");
        new PersonSalesAddressSummary(2, "Bill", "741", "Pear Street",      321, "April");
        new PersonSalesAddressSummary(3, "Mary", "951", "Oak Ave",          195, "May");

        mapPersonSales.entrySet().stream().forEach(System.out::println);
    }
}

输出

PersonSalesAddressSummary 
Person = 3 Mary
Sales = 195 May
=[Address  = 951 Oak Ave]

PersonSalesAddressSummary 
Person = 2 Bill
Sales = 321 April
=[Address  = 987 Apple Street, Address  = 654 Banana Street, Address  = 321 Orange Street, Address  = 741 Pear Street]

PersonSalesAddressSummary 
Person = 1 John
Sales = 100 June
=[Address  = 123 This Street, Address  = 456 This Street, Address  = 789 There Street]

如果我有任何错误,请纠正我,非常感谢

答案 1 :(得分:0)

据我所知,您无法从本机查询中提取父级&gt;子关系。原生查询总是会为您提供原始行,可以是对象,也可以是元组,但是您可以将它映射到对象。