如何在JPA NamedQuery中连接具有多个分支的表

时间:2017-01-21 23:26:05

标签: hibernate jpa java-ee ejb eclipselink

我正在JavaEE开发一个Web应用程序,我正在使用JPA 命名查询来查询数据库。但是,当我不得不连接具有多个分支的表时,我不知道如何做到这一点,并且我尝试为以下情况构建并执行一些查询,但它总是返回null

这是一张描述我情况的图片: IMAGE

我试图使用@NamedQuery从多个JOIN中选择多个表(实体)中的字段。请注意我从以下类中删除了setter和getters以减少代码大小。

@MappedSuperclass
@EntityListeners({Logger.class})
public abstract class SuperEntity  implements Serializable,HasName{

    @Transient
    private static final long serialVersionUID = -6420076371961889265L;

    @Id
    @SequenceGenerator(initialValue = 0, allocationSize = 1, name = "IdGenerator")
    @GeneratedValue(strategy=GenerationType.SEQUENCE,generator = "IdGenerator")
    private long ID;

    @Version
    private long version;
}




            @Entity
            public class Party extends SuperEntity {

                @Length(min = 1, max = 30, message = "Invalid party name.")
                private String name;

                @Enumerated(EnumType.STRING)
                @NotNull
                private PartyType type;

                @Length(min = 1, max = 13, message = "Invalid phone number")
                private String phone;

                @Email(message = "Invalid email address.")
                @NotNull
                private String email;

                @NotNull
                @NotEmpty(message = "Party address is required.")
                private String address;

                @Valid
                @OneToMany(cascade = CascadeType.ALL, mappedBy = "party", fetch = FetchType.EAGER)
                private List<Vehicle> vehicles = new ArrayList<Vehicle>();

        }

                @Entity
            public class Vehicle extends SuperEntity {

                @Valid
                @Embedded
                private VehicleAttributes attributes;

                @ManyToOne(cascade={CascadeType.PERSIST,CascadeType.MERGE})
                @JoinColumn(name = "partyID")
                private Party party;

                @Valid
                @OneToMany(cascade = CascadeType.ALL, mappedBy = "vehicle",fetch=FetchType.EAGER)
                private List<FixRequest> fixRequests = new ArrayList<FixRequest>();
           } 


            @NamedQuery(name = FixRequest.GET_NOT_PAID_REQUESTS_BY_PARTY_QUERY, query = "Select new org.master.jpa.UnpaidFixRequestObject(v.attributes.type,v.attributes.model,fr.ID,fr.requestDate,SUM(f.cost),SUM(p.paidAmount)) From Vehicle v,FixRequest fr,Payment p,Fix f,FixJoin fj WHERE v=fr.vehicle AND fr=p.fixRequest AND fr=fj.fixRequest AND fj.fix=f AND v.party.ID=:partyID GROUP BY v.attributes.type,v.attributes.model,fr.ID,fr.requestDate")
            @Entity
            public class FixRequest extends SuperEntity implements Serializable {

            @Transient
            static final String GET_NOT_PAID_REQUESTS_BY_PARTY_QUERY = "getNotPaidRequestsByParty";
            @Transient
            static final String GET_NOT_PAID_REQUESTS_BY_PARTY_QUERY_PARTY_PARAM = "partyID";
                @NotNull
                @Temporal(TemporalType.TIMESTAMP)
                private Date requestDate;

                @NotNull
                @Temporal(TemporalType.DATE)
                private Date requestedFixDate;

                @ManyToOne(cascade={CascadeType.PERSIST,CascadeType.MERGE})
                @JoinColumn(name = "vehicleID")
                private Vehicle vehicle;

                @OneToMany(cascade = CascadeType.ALL,fetch=FetchType.EAGER,mappedBy="fixRequest")
                private List<TroubleJoin> request_Troubles = new ArrayList<TroubleJoin>();

                @OneToMany(cascade = CascadeType.ALL,fetch=FetchType.EAGER,mappedBy="fixRequest")
                private List<FixJoin> requset_Fixes = new ArrayList<FixJoin>();

                @OneToMany(cascade = CascadeType.ALL,fetch=FetchType.EAGER,mappedBy="fixRequest")
                private List<Payment> payments = new ArrayList<Payment>();

                private String details;
        }

        @Entity
        public class FixJoin extends SuperEntity implements Serializable {

            public FixJoin() {
                super();
            }

            @ManyToOne(cascade={CascadeType.PERSIST,CascadeType.MERGE})
            @JoinColumn(name = "fixRequestID")
            private FixRequest fixRequest;

            @ManyToOne(cascade={CascadeType.PERSIST,CascadeType.MERGE})
            @JoinColumn(name = "fixID")
            private Fix fix;

            private String details;
        }

        @Entity
        public class Fix extends SuperEntity implements Serializable {

            @NotEmpty
            @NotNull
            private String type;

            @NotEmpty
            @NotNull
            private String detail;

            @Column(precision = 2)
            @Min(value = 1)
            private double cost;

            @OneToMany(cascade={CascadeType.PERSIST,CascadeType.MERGE},fetch=FetchType.LAZY,mappedBy="fix")
            private List<FixJoin> requset_Fixes = new ArrayList<FixJoin>();
        }

        @Entity
        public class Payment extends SuperEntity implements Serializable {

            @Transient
            private static final long serialVersionUID = 1L;

            @Column(precision = 2)
            private double paidAmount;

            @Enumerated(EnumType.STRING)
            private PaymentMethod paymentMethod;

            private int checkNumber;

            private String bank;

            private String payer;

            private String reciever;

            private String notes;

            @ManyToOne(cascade={CascadeType.PERSIST,CascadeType.MERGE})
            @JoinColumn(name = "fixRequestId")
            private FixRequest fixRequest;
        }

        @Stateless
        public class QueryFacade {

            @PersistenceContext
            EntityManager entityManager;


        public List<UnpaidFixRequestObject> getUnpaidFixRequestObjects(long partyID){
            TypedQuery<UnpaidFixRequestObject> typedQuery = entityManager.createNamedQuery(FixRequest.getGetNotPaidRequestsByPartyQuery(),UnpaidFixRequestObject.class);
            typedQuery.setParameter(FixRequest.getGetNotPaidRequestsByPartyQueryPartyParam(), partyID);
            return typedQuery.getResultList();
        }
        }

        @ViewScoped
        @ManagedBean
        public class PaymentFace {

            @EJB
            private FootprintEntityFacade<Payment> paymentFacade;

            @EJB
            QueryFacade queryFacade;

            private List<Party> parties;
            private List<UnpaidFixRequestObject> unpaidFixRequests;

            private String selectedParty = "";
            private String selectedFixRequest = "";
            private Payment payment;

            private boolean showCreditPaymentControls = false;

            @PostConstruct
            public void init() {
                parties = new ArrayList<Party>();
                unpaidFixRequests = new ArrayList<UnpaidFixRequestObject>();

                parties = queryFacade.getAllParties();
                for (Party p : parties) {
                    p.setName(p.getID() + " - " + p.getName() + " - " + p.getAddress());
                }
            unpaidFixRequests = queryFacade.getUnpaidFixRequestObjects(parties.get(0).getID());
        }
    }

任何帮助将不胜感激。 提前谢谢。

2 个答案:

答案 0 :(得分:0)

好的尝试此查询,我添加了显式连接:

"Select new org.master.jpa.UnpaidFixRequestObject(v.attributes.type,v.at‌​tributes.model,fr.ID‌​,fr.requestDate,SUM(‌​f.cost),SUM(p.paidAm‌​ount)) " +
            " From FixRequest fr" +
            "   inner join fr.payments p" +
            "   inner join fr.vehicle v" +
            "   inner join v.party pt" +
            "   inner join fr.requset_Fixes rf" +
            "   inner join rf.fix f"
            " WHERE pt.ID=:partyID " +
            " GROUP BY v.attributes.type,v.attributes.model,fr.ID,fr.requestDate"

答案 1 :(得分:0)

编写 @Maciej 的查询并通过将ID从SuperEntity移动到所有其他类来更改模型。

  

实体层次结构的默认访问类型取决于实体类的属性上的映射注释的放置以及未明确指定访问类型的实体层次结构的映射超类。

了解详情:Multiple @MappedSuperclass