Java 如何在Hibernate中绕过缓存第一级刷新

Java 如何在Hibernate中绕过缓存第一级刷新,java,database,spring,hibernate,jpa,Java,Database,Spring,Hibernate,Jpa,有没有人能解释一下,为什么我的父母在我刷新实体时没有填充子对象 我在这里包括了parentDao2Test类以及ParentService、ChildService、DBChild和DBParent。parentDAO和childDao基本上很简单。ParentDAO2测试通过SpringJUnit4ClassRunner junit runner运行 public class ParentDao2Test { @Autowired private ParentService paren

有没有人能解释一下,为什么我的父母在我刷新实体时没有填充子对象

我在这里包括了parentDao2Test类以及ParentService、ChildService、DBChild和DBParent。parentDAO和childDao基本上很简单。ParentDAO2测试通过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();
    }
}
公共类ParentDao2Test{
@自动连线专用家长服务;
@试验
公共void testCRUD(){
DBParent=parentService.createParent();
assertTrue(parent.getId()>0);
parent=parentService.createChildForParent(parent.getId());
assertTrue(parent.getChilds().size()>0);
}
}
公共班级家长服务{
@自动连线的ParentDao ParentDao;
@自动连线儿童服务儿童服务;
@事务性(传播=传播。需要\u新建)
public DBParent createParent(){
DBParent parent=新的DBParent();
parentDao.persist(parent);
返回父母;
}
@事务性(传播=传播。需要\u新建)
public DBParent createChildForParent(长parentId){
DBParent parent=parentDao.findById(parentId);
childService.createChildForParent(parentId);
HashMap props=newhashmap();
put(“org.hibernate.cacheMode”,cacheMode.IGNORE);
parentDao.refresh(父级);
返回父母;
}
}
公营儿童服务{
@自动连线的ChildDao ChildDao;
@自动连线的ParentDao ParentDao;
@事务性(传播=传播。需要\u新建)
public DBChild createChildForParent(长parentId){
DBParent parent=parentDao.findById(parentId);
DBChild=newdbchild();
child.setName(“名称”);
坚持(孩子);
parent.addChild(child);
parentDao.persist(parent);
parentDao.flush();
返回儿童;
}
}
@实体
@表(name=“Parent”)
公共类DBParent{
@身份证
@列(name=“id”)
@GeneratedValue(策略=GenerationType.AUTO)
私人长id;
@OneToMany(fetch=FetchType.EAGER,cascade={CascadeType.ALL},orphanRemoving=true)
@JoinColumn(name=“childs”,nullable=true)
private Set childs=new HashSet();
公共DBParent(){
超级();
}
}
@实体
@表(name=“child”)
公共类DBChild{
@身份证
@列(name=“id”)
@GeneratedValue(策略=GenerationType.AUTO)
私人长id;
@列(name=“name”,null=false,长度=1024)
私有字符串名称;
公共DBChild(){
超级();
}
}

经过一整天的深入调试,我终于找到了问题所在

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

有一种方法可以解决此行为: 将事务隔离级别声明为READ_UNCOMMITTED或READ_COMMITTED。如果使用标准方言,可能会遇到著名的“标准JPA不支持自定义隔离级别”异常。在这种情况下,您可以应用以下解决方法: 春季3.3: 春季3.2:

为了使代码正常工作,我必须更改以下方法:

@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;
}



尝试在父表上使用merge而不是persist,并检查在插入子实体后是否在数据库中填充了子表“childs”字段。