Hibernate标准一对多关系

时间:2021-05-19 06:47:15

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)

但是,我无法根据经销商ID检索记录。我尝试了很多不同的方法,它仍然抛出这个异常:找不到属性make(它是表):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

经销商_Id经销商名称phonenumber

1 halal 074563485

1 halal 074563485

Make has below records:

制作有以下记录:

make_id makename makeprice dealer_id

make_id makename makeprice dealer_id

1 ford 3000$ 1

1 ford 3000 $ 1

2 hyundai 2000$ 1

2 hyundai 2000 $ 1

I want results like dealer details with make details.

我希望结果像经销商的详细信息和详细信息。

3 个解决方案

#1


5  

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

好。因此,您希望使用其品牌加载经销商,并且您只希望经销商的ID大于给定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():

首先,您可以加载经销商。当你调用getDealerMakes()时,Hibernate会自动加载它们的make列表:

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.

这具有执行N + 1个查询的缺点。

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:

因此,如果要在单个查询中加载经销商及其品牌,则需要设置获取模式以便加载品牌。请注意,由于连接使用您在Dealer和Make之间定义的关联,您不需要告诉Hibernate经销商表的ID必须等于make表的dealer_id:Hibernate已经知道,感谢JoinColumn您放在关联上的注释。因此查询如下:

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
}

#2


1  

    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

试着像这样回来,希望它有效,让我知道是否还有更多

#3


1  

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

This do the trick!

这样做的伎俩!

#1


5  

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

好。因此,您希望使用其品牌加载经销商,并且您只希望经销商的ID大于给定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():

首先,您可以加载经销商。当你调用getDealerMakes()时,Hibernate会自动加载它们的make列表:

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.

这具有执行N + 1个查询的缺点。

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:

因此,如果要在单个查询中加载经销商及其品牌,则需要设置获取模式以便加载品牌。请注意,由于连接使用您在Dealer和Make之间定义的关联,您不需要告诉Hibernate经销商表的ID必须等于make表的dealer_id:Hibernate已经知道,感谢JoinColumn您放在关联上的注释。因此查询如下:

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
}

#2


1  

    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

试着像这样回来,希望它有效,让我知道是否还有更多

#3


1  

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

This do the trick!

这样做的伎俩!