K. Hasani
K. Hasani

Reputation: 21

Spring/Hibernate getting List of Objects containing lists

I'm trying to get a list of objects from database using Hibernate but something seems weird for me.

In the DB I have 5 Runs with 3 Positions each.

When I get the List of runs from RunDao I obtain a list of 15 Run objects ! The three first runs have the same ID.

In my case I just want to get the 5 Runs. Am I doing something wrong ?

How to get only the 5 runs ?

Thanks a lot

Here are my classes Run / Position / RunDao :

Run.java

@Entity
@Table(name="kr_runs")
public class Run {

    private long id;
    private Date date;
    private int indexedPages;
    private int pr;
    @JsonIgnore
    private Site site;
    private Set<Position> positions = new HashSet<Position>(0);
    
    public Run() {
       
    }

    @Id
    @GeneratedValue
    @Column(name="id")
    public long getId() {
        return id;
    }

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

    @Temporal(value=TemporalType.TIMESTAMP)
    public Date getDate() {
        return date;
    }

    public void setDate( Date date ) {
        this.date = date;
    }

    @Column(name="indexed_pages")
    public int getIndexedPages() {
        return indexedPages;
    }

    public void setIndexedPages( int indexedPages ) {
        this.indexedPages = indexedPages;
    }

    @Column
    public int getPr() {
        return pr;
    }

    public void setPr( int pr ) {
        this.pr = pr;
    }

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "kr_site_id", nullable = false)
    public Site getSite() {
        return site;
    }

    public void setSite( Site site ) {
        this.site = site;
    }

    @Cascade({CascadeType.ALL})
    @OneToMany(fetch = FetchType.EAGER, mappedBy = "run")
    public Set<Position> getPositions() {
        return positions;
    }

    public void setPositions( Set<Position> positions ) {
        this.positions = positions;
    }
    
    

}

Position.java

@Entity
@Table(name="kr_positions")
public class Position {

    private long id;
    private int pos;
    private String url;
    @JsonIgnore
    private Run run;
    private Keyword keyword;
    
    public Position() {
        
    }

    @Id
    @GeneratedValue
    @Column(name="id")
    public long getId() {
        return id;
    }

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

    @Column
    public int getPos() {
        return pos;
    }

    public void setPos( int pos ) {
        this.pos = pos;
    }

    @Column
    public String getUrl() {
        return url;
    }

    public void setUrl( String url ) {
        this.url = url;
    }

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "kr_run_id", nullable = false)
    public Run getRun() {
        return run;
    }

    public void setRun( Run run ) {
        this.run = run;
    }

    //@Cascade({CascadeType.SAVE_UPDATE})
    //@OneToOne(mappedBy="position")
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "kr_keyword_id", nullable = false)
    public Keyword getKeyword() {
        return keyword;
    }

    public void setKeyword( Keyword keyword ) {
        this.keyword = keyword;
    }
    
    

}

RunDao.java

@Transactional
public class RunDao extends HibernateDao<Run, Long> implements IRunDao {

    public List<Run> find( long siteID, Date date_start, Date date_end ) {
       
        Criteria cr = currentSession().createCriteria(Run.class);
        cr.add(Restrictions.eq("site.id", siteID));
        cr.add(Restrictions.ge("date",date_start));
        cr.add(Restrictions.lt("date",date_end));
        
        List<Run> list = (List<Run>) cr.list();
        
        if (list.isEmpty()) return null;
        else return list;
    }
}

Solved

Thanks to the help of Guillaume I found a solution.

@OneToMany(fetch = FetchType.EAGER, mappedBy = "run")

by

@OneToMany(fetch = FetchType.LAZY, mappedBy = "run")

// Get data from DAO
List<Run> list = runDao.find(siteID, cal.getTime(), date_today);
for(Run run : list)
{
    Hibernate.initialize(run.getPositions());  // run.getPositions().size(); if you are note in @Transactional
}

Upvotes: 2

Views: 1515

Answers (1)

Guillaume F.
Guillaume F.

Reputation: 6473

Everything in your code looks correct. The only thing I'm not too certain about @OneToMany(fetch = FetchType.EAGER ... since I've had bugs in the past with EAGER fetch types.

Try to leave it LAZY and add a fetch join in your criteria query instead.

Upvotes: 2

Related Questions