0

我使用 query.iterate() 并将所有实体添加到 ArrayList 以进行二级缓存。但是当我将此 ArrayList 更改为 JSONArray 时,出现了 StackOverFlowError。

但奇怪的是当我使用 query.list() 时。没有错!

我在这里有一个实体:

@Entity
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
public class Word {
    @Id
    @GeneratedValue
    private int id;
    private String literal;
    private String chineseMean;
    //..getter and setter
}

和一个 DAO 对象的方法(使用 iterate()):

public List<Word> getWords(final String wordBook, final int startId,
            final int length) {
        Session session = getSession();
        Query q = session.createQuery("from " + wordBook);
        q.setFirstResult(startId-1);
        q.setMaxResults(length);
        Iterator<Word> iterator = q.iterate();
        List<Word> wordList = new ArrayList<Word>();
        while(iterator.hasNext()){
            wordList.add(iterator.next());
        }
        return wordList;
    }

并使用列表():

public List<Word> getWords_nobuffer(final String wordBook, final int startId,
            final int length) {
        Session session = getSession();
        Query q = session.createQuery("from " + wordBook);
        q.setFirstResult(startId-1);
        q.setMaxResults(length); 
        return q.list();
    }

错误位置(使用 iterate()):

List<Word> words = worddao.getWords("Word",5, 10);
JSONArray ja = new JSONArray(words);//stackoverflowerror!!!!

这种方式没有错:

List<Word> words = worddao.getWords_nobuffer("Word",5, 10);
JSONArray ja = new JSONArray(words);//everything is ok

当我尝试使用它时:

List<Word> words = worddao.getWords("Word",5, 10);
List<Word> words2 = worddao.getWords_nobuffer("Word",5, 10);
JSONArray ja = new JSONArray(words2);//everything is ok too, all entities are selected from second level cache

StackOverFlowError 是怎么发生的?

4

1 回答 1

0

发现问题了。休眠中的实体默认使用惰性模式。

所以在调试模式下,我们可以发现单词 object 被更改为:

{
    id : 0,
    chineseMean : null,
    literal : null,
    handler : JavassistLazyInitializer  // this is key! 
    //all the value of field was put in this object, this object must be used to implement lazy load.
}

所以,JSONArray 出了点问题……(啊……太复杂了,找不到)

并将实体更改为:

@Entity
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
@Proxy(lazy=false)//look at here!
public class Word {
    @Id
    @GeneratedValue
    private int id;
    private String literal;
    private String chineseMean;
    //..getter and setter
}

这使得 JSONArray 工作!

于 2014-05-21T15:17:19.007 回答