2012-07-06 110 views
0

嗨,我在休眠中创建了多对一的关系。 以下是该代码。休眠状态下的内存不足

有成千上万的存在于乙表中的记录是链接表A的单记录当我用getBList()方法它将返回数千记录和JAVA的熄灭存储器。 那么我该如何解决这个问题。

@Entity 
@Table(name = "A") 
public class A { 

    private int Id; 
    private String aName; 
    private List<MksReleaseInfo> bList; 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    @Column(name = "id") 
    public int getId() { 
     return releaseId; 
    } 

    public void setId(final int Id) { 
     this.Id = Id; 
    } 

    @Column(name = "aname", unique = true) 
    public String getAName() { 
     return aName; 
    } 

    public void setAName(final String aName) { 
     this.aName = aName; 
    } 
    @OneToMany(mappedBy = "aName") 
    public List<MksReleaseInfo> getBList() { 
     return bList; 
    } 

    public void setBList(final List<B> bList) { 
     this.bList = bList; 
    } 
} 


@Entity 
@Table(name = "B") 
public class B { 

    private int bIndex; 
    private int bpriority; 
    private A aName; 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    @Column(name = "id") 
    protected int getBIndex() { 
     return mksReleaseInfoIndex; 
    } 

    protected void setBIndex(final int bIndex) { 
     this.bIndex = bIndex; 
    } 

    @Column(name = "priority") 
    public int getBPriority() { 
     return bpriority; 
    } 

    public void setBPriority(final int bpriority) { 
     this.bpriority = bpriority; 
    } 

    @ManyToOne 
    @JoinColumn(name = "Id") 
    public A getAName() { 
     return aName; 
    } 

    public void setAName(final A aName) { 
     this.aName = aName; 
    } 
} 

之后所有的评论我已经实现了下面的代码。但它又一次给出了记忆。我是否应该明确清空内存,以及如何?

public List<B> getList(String name, int offset, int limit) throws DAOException { 
     try { 
      String hql = "from B where name = :name"; 
      begin(); 
      Query query = getSession().createQuery(hql); 
      query.setString("name", name); 

      if(offset > 0){ 
       query.setFirstResult(offset); 
      } 

      if(limit > 0){ 
       query.setMaxResults(limit); 
       query.setFetchSize(limit); 
      } 
      commit(); 
      return query.list(); 
     } catch (HibernateException e) { 
      rollback(); 
     } 
    } 

    public Long countB(String name) throws DAOException { 
     try { 
      String hql = "select count(*) from B where name = :name"; 
      begin(); 
      Query query = getSession().createQuery(hql); 
      query.setString("name", name); 
      commit(); 
      return (Long)query.uniqueResult(); 
     } catch (HibernateException e) { 
      rollback(); 
     } 
    } 


    long count = countB(name); 
    int counter = (int) (count/200); 
    if(count%200 > 0){ 
     counter++; 
    } 
    for(int j = 0;j<counter;j++){ 
     lists = getList(name, j*200, 200); 

     for(B count1 : lists){ 
      System.out.println(count1); 
     } 
    } 
+0

所以你说什么问题是,我建议你改变你的算法。您想做什么?我相信有非常罕见的情况,当你需要把数千个“关系”的关系放在一起时。 – 2012-07-06 06:31:44

+0

您也可以测试'StatelessSession',它可以帮助.... – 2012-07-06 06:32:53

回答

1

你可以为了检索B分页的方式给予A对象记录引入DAO

例如:

public interface BDao { 

    Page findByA(A a, PageRequest pageRequest); 

} 

也许你可以采取从方法中Spring Data

1

MaxResults数据源的属性抽放的想法,它将对你得到的记录数设置限制。

另外,还可以使用-Xmx256m增加Java堆内存的大小。这会将最大堆分配大小设置为256MB。您可以根据需要进行设置。

+0

我们可以在查询对象中设置MaxResults属性。但我只是使用getBList()方法。所以我将如何控制这个功能。而事情是,我想从A中的特定记录中记录所有记录,但不是一成不变的,我可以在大量记录中使用它,但是我怎么做才能保证没有内存不足。 – Anant 2012-07-06 07:02:05

+0

不错,你也可以这样做。但是你不觉得,你每次执行查询时都会设置它。 – 2012-07-06 07:05:16

+0

这就是我不想使用查询的原因。并请再次阅读上面的评论,我已编辑。这样你就可以得到我的问题。 – Anant 2012-07-06 07:11:02

1

您可以使用查询分页用于这一目的。在Query类中,您可以找到setFirstResultsetMaxResults方法,这些方法可以帮助您迭代记录。如果您需要加载所有B对象并存储它们,您可以通过设置-Xmx选项来调整java的内存设置。你也可以尝试申报某种减少B类(例如ReducedB),其中只包含所需的字段,并使用带有转换BReducedB减少内存使用迭代。你

还可以检查this问题。我认为它足够接近你想要的东西。

P.S.最终解决方案将取决于您想要解决的特定问题。

+0

我已经完成了相同的工作,但我又收到了内存不足。我在我的问题中更新了我的代码,以便您可以查看它。 – Anant 2012-07-09 10:45:51

+0

我觉得'OUT OF MEMORY'的原因是一样的。你是否同时存储所有B对象?可能从DB获取的对象不是垃圾收集?你可以尝试'jvisualvm'工具来发现内存已经走了。 – gkuzmin 2012-07-10 05:59:59