如何在Hibernate中刷新绕过缓存1级

时间:2013-11-16 22:33:13

标签: java database spring hibernate jpa

有人可以解释一下,为什么即使我正在刷新实体,我的父母也没有填充这个孩子?

我在这里包含了parentDao2Test类以及ParentService,ChildService,DBChild和DBParent。 parentDAO和childDao基本简单。 parentDao2Test通过SpringJUnit4ClassRunner junit runner运行。

public class ParentDao2Test {
    @Autowired private ParentService parentService;
    @Test
    public void testCRUD() {
        DBParent parent = parentService.createParent();
        assertTrue(parent.getId() > 0);
        parent = parentService.createChildForParent(parent.getId());
        assertTrue(parent.getChilds().size() > 0);
    }
 }

public class ParentService{
    @Autowired ParentDao parentDao;
    @Autowired ChildService childService;

    @Transactional(propagation=Propagation.REQUIRES_NEW) 
    public DBParent createParent() {
        DBParent parent = new DBParent();
        parentDao.persist(parent);
        return parent;
    }

    @Transactional(propagation=Propagation.REQUIRES_NEW) 
    public DBParent createChildForParent(long parentId) {
        DBParent parent = parentDao.findById(parentId);
        childService.createChildForParent(parentId);

        HashMap<String, Object> props = new HashMap<String, Object>();
        props.put("org.hibernate.cacheMode", CacheMode.IGNORE);
        parentDao.refresh(parent);
        return parent;
    }
}

public class ChildService {
    @Autowired ChildDao childDao;
    @Autowired ParentDao parentDao;

    @Transactional(propagation=Propagation.REQUIRES_NEW) 
    public DBChild createChildForParent(long parentId) {
        DBParent parent = parentDao.findById(parentId);
        DBChild child = new DBChild();
        child.setName("Name");
        childDao.persist(child);
        parent.addChild(child);
        parentDao.persist(parent);
        parentDao.flush();
        return child;
    }
}

@Entity
@Table(name = "Parent")
public class DBParent {
    @Id
    @Column(name="id")
    @GeneratedValue(strategy=GenerationType.AUTO) 
    private long id;

    @OneToMany(fetch = FetchType.EAGER, cascade = {CascadeType.ALL}, orphanRemoval=true)
    @JoinColumn(name = "childs", nullable=true)
    private Set<DBChild> childs = new HashSet<DBChild>();

    public DBParent() {
        super();
    }
}

@Entity
@Table(name = "child")
public class DBChild {
    @Id
    @Column(name="id")
    @GeneratedValue(strategy=GenerationType.AUTO) 
    private long id;

    @Column(name="name", nullable = false, length=1024)
    private String name;

    public DBChild() {
        super();
    }
}

1 个答案:

答案 0 :(得分:0)

经过一整天的深度调试,我终于找到了问题的问题。

我看到了这种行为,因为我的事务是在REPEATABLE_READ中配置的(这是默认值)。这意味着Spring保证在同一事务中对相同数据的两次读取将始终返回相同的结果。由于隔离级别优先于我的缓存逐出或实体刷新,即使我刷新或逐出父实体,这也没有效果。

有一种方法可以解决此问题: 将事务隔离级别声明为READ_UNCOMMITTED或READ_COMMITTED。如果您使用的是标准方言,则可能会遇到着名的“标准JPA不支持自定义隔离级别”异常。在这种情况下,您可以应用以下解决方法: 春天3.3:http://amitstechblog.wordpress.com/2011/05/31/supporting-custom-isolation-levels-with-jpa/ 春天3.2:http://shahzad-mughal.blogspot.com/2012/04/spring-jpa-hibernate-support-for-custom.html

为了使我的代码能够工作,我不得不改变以下方法:

@Transactional(propagation=Propagation.REQUIRES_NEW, isolation=Isolation.READ_COMMITTED) 
public DBParent createChildForParent(long parentId) {
    DBParent parent = parentDao.findById(parentId);
    childService.createChildForParent(parentId);

    parentDao.getSession().evict(parent);
    parent = parentDao.findById(parentId);
    return parent;
}