开发者

Hibernate Criteria One-to-Many Relationship

开发者 https://www.devze.com 2023-03-31 09:50 出处:网络
I have two entities: Dealers and Makes. Dealers have multiple makes.I am able to insert the records as a one-to-many relationship between these two entities.

I have two entities: Dealers and Makes. Dealers have multiple makes.I am able to insert the records as a one-to-many relationship between these two entities.

However, I am not able to retrieve the records based on dealer ID. I tried many different ways and it's still throwing this exception: Property not found make(it is table) of : class name(full classname)

If anyone could provide me with some hints, it would be greatly appreciated.

Dealer:

 import java.util.HashSet;
    import java.util.Set;    
    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.FetchType;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Id;
    import javax.persistence.Table;
    import javax.persistence.OneToMany;
    import javax.persistence.JoinTable;
    import javax.persistence.CascadeType;
    import javax.persistence.JoinColumn;
    @Entity
    @Table(name = "dealer")
    public class Dealer implements java.io.Serializable{
        /**
       开发者_运维技巧  * 
         */
        private static final long serialVersionUID = 1L;

        public Dealer(){

        }
        public Dealer(String DealerName,String dealerPhno,Set makes){
            this.dealerName=DealerName;
            this.dealerphno=dealerPhno;
            this.dealerMakes=makes;

        }
        public void setDealerMakes(Set<Make> dealerMakes) {
            this.dealerMakes = dealerMakes;
        }
        @Id
        @GeneratedValue
        @Column(name = "dealer_id")
        private long dealerId;
        public long getDealerId() {
            return dealerId;
        }
        public void setDealerId(long dealerId) {
            this.dealerId = dealerId;
        }
        public String getDealerName() {
            return dealerName;
        }
        public void setDealerName(String dealerName) {
            this.dealerName = dealerName;
        }
        public String getDealerphno() {
            return dealerphno;
        }
        public void setDealerphno(String dealerphno) {
            this.dealerphno = dealerphno;
        }
        @Column(name = "dealer_name" ,unique=true, nullable = false, length=20)
        private String dealerName;
        @Column(name = "dealer_phno" , nullable = false, length=20)
        private String dealerphno;
        @OneToMany(cascade = CascadeType.ALL)
        //@OneToMany(fetch=FetchType.EAGER)
        @JoinColumn(name="dealer_id", nullable=false)
        //@JoinTable(name = "dealer_make", joinColumns = { @JoinColumn(name = "dealer_id") }, inverseJoinColumns = { @JoinColumn(name = "make_id") })
        private Set<Make> dealerMakes = new HashSet<Make>(0);

        public Set<Make> getDealerMakes() {
            return dealerMakes;
        }

    }

Make

import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Entity;
import javax.persistence.Table;
@Entity
@Table(name = "make")
public class Make implements java.io.Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 2L;
    public Make(){

    }
    public Make(String makeName,String modelName,String price){

        this.makeName=makeName;
        this.modelName=modelName;
        this.price=price;
    }
    public long getMakeId() {
        return makeId;
    }
    public void setMakeId(long makeId) {
        this.makeId = makeId;
    }
    public String getMakeName() {
        return makeName;
    }
    public void setMakeName(String makeName) {
        this.makeName = makeName;
    }
    public String getModelName() {
        return modelName;
    }
    public void setModelName(String modelName) {
        this.modelName = modelName;
    }
    public String getPrice() {
        return price;
    }
    public void setPrice(String price) {
        this.price = price;
    }
    @Id
    @GeneratedValue
    @Column(name = "make_id")
    private long makeId;
    @Column(name = "make_name" , nullable = false, length=8)
    private String makeName;
    @Column(name = "model_name" , nullable = false, length=8)
    private String modelName;
    @Column(name = "price" , nullable = false, length=8)
    private String price;

}

Query I tried:

 Criteria dealer=sessionFactory.getCurrentSession().createCriteria(Dealer.class);
 Criteria make=dealer.createCriteria(make);
 make.add(Restrictions.gt("dealerId",new Long(dealerId)));
 List<Dealer> results=dealer.list(); //throwing exception

Ouput i am expecting:

Dealer_Id dealername phonenumber

1 halal 074563485

Make has below records:

make_id makename makeprice dealer_id

1 ford 3000$ 1

2 hyundai 2000$ 1

I want results like dealer details with make details.


OK. So you want to load dealers with their makes, and you only want the dealers having an ID greater than a given ID.

First of all, you could just load dealers. The list of their makes would automatically be loaded by Hibernate when you would call getDealerMakes():

Criteria c = session.createCriteria(Dealer.class);
c.add(Restrictions.gt("dealerId", dealerId)); // let's say delerId = 6
List<Dealer> dealers = c.list(); // execute SQL query select d.* from dealer d where d.dealer_id > 6
for (Dealer dealer : dealers) {
    Set<Make> make = dealer.getDealerMakes() // execute SQL query select m.* from make m where m.dealer_id = <theIdOfTheCurrentDealer>
}

This has the disadvantage of executing N + 1 queries.

So if you want to load the dealers and their makes in a single query, you need to set a fetch mode so that the makes are loaded. Note that since the join uses the association that you defined between Dealer and Make, you don't need to tell Hibernate that the ID of the dealer table must be equal to the dealer_id of the make table: Hibernate already knows that thanks to the JoinColumn annotation that you put on the association. The query is thus the following:

Criteria c = session.createCriteria(Dealer.class);
c.add(Restrictions.gt("dealerId", dealerId));

// this tells Hibernate that the makes must be fetched from the database
// you must use the name of the annotated field in the Java class: dealerMakes
c.setFetchMode("dealerMakes", FetchMode.JOIN);

// Hibernate will return instances of Dealer, but it will return the same instance several times
// once per make the dealer has. To avoid this, you must use a distinct root entity transformer
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
List<Delaer> dealers = c.list(); // executes the SQL query:
// select d.*, m.* from dealer d left join make m on d.dealer_id = m.dealer_id where d.dealer_id > 6
for (Dealer dealer : dealers) {
    Set<Make> make = dealer.getDealerMakes() // no SQL query. The makes are already loaded
}


criteria.setFetchMode("dealerMakes", FetchMode.JOIN);
criteria.createCriteria("dealerMakes");
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

This do the trick!


    public List<Dealer> findDealers() {
    Criteria dealer=sessionFactory.getCurrentSession().createCriteria(Dealer.class);
    Criteria make=dealer.createCriteria(make);
    make.setFetchMode("dealer", FetchMode.JOIN);
    make.add(Restrictions.gt("dealerId",new Long(dealerId)));
    criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); // depends on wat u want
    return criteria.list();
    }

try to return like this, hope it works, let me know if there is more to it

0

精彩评论

暂无评论...
验证码 换一张
取 消