hibernate事务问题

专打小盆友 发布于 2011/12/01 15:42
阅读 1K+
收藏 0

收藏!数据建模最全知识体系解读!>>>

我参照网上写的一个二叉树的分类树,修改节点的时候碰到一个很奇怪的问题谁能帮我看看什么原因啊。。。。

application-contetx.xml数据库配制

<bean id="sessionFactory"

class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">

<property name="dataSource" ref="dataSource" />

<property name="packagesToScan">

<list>

<value>com.cms.entity</value>

</list>

</property>

<property name="hibernateProperties">

<props>

<prop key="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</prop>

<prop key="hibernate.show_sql">true</prop>

<prop key="hibernate.format_sql">true</prop>

<prop key="hibernate.jdbc.batch_size">20</prop>

<!-- <prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>-->

<prop key="hibernate.query.substitutions">true 1, false 0</prop> 

                <prop key="hibernate.cache.use_query_cache">true</prop>

</props>

</property>

<property name="entityInterceptor">   

<ref local="treeInterceptor"/>

</property> 

<property name="cacheProvider">

<ref local="cacheProvider"/>

</property>

</bean>

Controller中映射的方法

@RequestMapping(value = "/lan/v_edit.do",method=RequestMethod.POST)

public String update(HttpServletRequest request, 

Channel bean,

@RequestParam("parentId") Integer parentId,

ModelMap model) {

channelMng.update(bean,parentId);

return "redirect:v_list.do";

}

Service中update方法:

public Channel update(Channel bean,Integer parentId) {

// 更新父栏目

Channel curParent;

if (parentId != null) {

curParent = findById(parentId);

} else {

curParent = null;

}

bean.setParent(curParent);

Updater<Channel> updater = new Updater<Channel>(bean);

bean = dao.updateByUpdater(updater);

return bean;

}

Dao中的更新方法:

@SuppressWarnings("deprecation")

public Channel updateByUpdater(Updater<Channel> updater) {

ClassMetadata cm = sessionFactory.getClassMetadata(getEntityClass());

Channel bean = updater.getBean();

Channel po = (Channel) getSession().get(getEntityClass(),

cm.getIdentifier(bean, POJO));

updaterCopyToPersistentObject(updater, po, cm);

return po;

}

private void updaterCopyToPersistentObject(Updater<Channel> updater, Channel po,

ClassMetadata cm) {

String[] propNames = cm.getPropertyNames();

String identifierName = cm.getIdentifierPropertyName();

Channel bean = updater.getBean();

Object value;

for (String propName : propNames) {

if (propName.equals(identifierName)) {

continue;

}

try {

value = MyBeanUtils.getSimpleProperty(bean, propName);

if (!updater.isUpdate(propName, value)) {

continue;

}

cm.setPropertyValue(po, propName, value, POJO);

} catch (Exception e) {

throw new RuntimeException(

"copy property to persistent object failed: '"

+ propName + "'", e);

}

}

}

Entity拦截器treeInterceptor中更新树方法:

@Override

public boolean onFlushDirty(Object entity, Serializable id,

Object[] currentState, Object[] previousState,

String[] propertyNames, Type[] types) {

if (!(entity instanceof HibernateTree)) {

return false;

}

HibernateTree<?> tree = (HibernateTree<?>) entity;

for (int i = 0; i < propertyNames.length; i++) {

if (propertyNames[i].equals(tree.getParentName())) {

HibernateTree<?> preParent = (HibernateTree<?>) previousState[i];

HibernateTree<?> currParent = (HibernateTree<?>) currentState[i];

return updateParent(tree, preParent, currParent);

}

}

return false;

}

 

private boolean updateParent(HibernateTree<?> tree,

HibernateTree<?> preParent, HibernateTree<?> currParent) {

// 都为空、或都不为空且相等时,不作处理

if ((preParent == null && currParent == null)

|| (preParent != null && currParent != null && preParent

.getId().equals(currParent.getId()))) {

return false;

}

String beanName = tree.getClass().getName();

if (log.isDebugEnabled()) {

log.debug("update Tree {}, id={}, "

+ "pre-parent id={}, curr-parent id={}", new Object[] {

beanName, tree.getId(),

preParent == null ? null : preParent.getId(),

currParent == null ? null : currParent.getId() });

}

Session session = getSession();

// 保存刷新模式,并设置成手动刷新

FlushMode model = session.getFlushMode();

session.setFlushMode(FlushMode.MANUAL);

// 先空出位置。当前父节点存在时,才需要空出位置。

Integer currParentRgt;

Integer currParentLft;

if (currParent != null) {

// 获得节点跨度

String hql = "select bean." + tree.getLftName() + ",bean."

+ tree.getRgtName() + " from " + beanName

+ " bean where bean.id=:id";

Object[] position = (Object[]) session.createQuery(hql)

.setParameter("id", tree.getId()).uniqueResult();

int nodeLft = ((Number) position[0]).intValue();

int nodeRgt = ((Number) position[1]).intValue();

int span = nodeRgt - nodeLft + 1;

log.debug("current node span={}", span);

 

// 获得当前父节点左位置

Object[] currPosition = (Object[]) session.createQuery(hql)

.setParameter("id", currParent.getId()).uniqueResult();

currParentLft = ((Number) currPosition[0]).intValue();

currParentRgt = ((Number) currPosition[1]).intValue();

log.debug("current parent lft={} rgt={}", currParentLft,

currParentRgt);

 

// 空出位置

String hql1 = "update " + beanName + " bean set bean."

+ tree.getRgtName() + " = bean." + tree.getRgtName()

+ " + " + span + " WHERE bean." + tree.getRgtName()

+ " > :parentLft";

String hql2 = "update " + beanName + " bean set bean."

+ tree.getLftName() + " = bean." + tree.getLftName()

+ " + " + span + " WHERE bean." + tree.getLftName()

+ " > :parentLft";

if (!StringUtils.isBlank(tree.getTreeCondition())) {

hql1 += " and (" + tree.getTreeCondition() + ")";

hql2 += " and (" + tree.getTreeCondition() + ")";

}

session.createQuery(hql1).setInteger("parentLft", currParentLft)

.executeUpdate();

session.createQuery(hql2).setInteger("parentLft", currParentLft)

.executeUpdate();

//session.refresh(currParent);

log.debug("vacated span hql: {}, {}, parentRgt={}", new Object[] {

hql1, hql2, currParentRgt });

} else {

currParentLft = 2;

// 查找最大的右边位置

String hql = "select max(bean." + tree.getRgtName() + ") from "

+ beanName + " bean";

if (!StringUtils.isBlank(tree.getTreeCondition())) {

hql += " where " + tree.getTreeCondition();

}

currParentRgt = ((Number) session.createQuery(hql).uniqueResult())

.intValue();

currParentRgt++;

log.debug("max node left={}", currParentRgt);

}

// 再调整自己

String hql = "select bean." + tree.getLftName() + ",bean."

+ tree.getRgtName() + " from " + beanName

+ " bean where bean.id=:id";

Object[] position = (Object[]) session.createQuery(hql).setParameter(

"id", tree.getId()).uniqueResult();

int nodeLft = ((Number) position[0]).intValue();

int nodeRgt = ((Number) position[1]).intValue();

int span = nodeRgt - nodeLft + 1;

if (log.isDebugEnabled()) {

log.debug("before adjust self left={} right={} span={}",

new Object[] { nodeLft, nodeRgt, span });

}

Integer offset = currParentLft - nodeLft+1;

hql = "update " + beanName + " bean set bean." + tree.getLftName()

+ "=bean." + tree.getLftName() + "+:offset, bean."

+ tree.getRgtName() + "=bean." + tree.getRgtName()

+ "+:offset WHERE bean." + tree.getLftName()

+ " between :nodeLft and :nodeRgt";

if (!StringUtils.isBlank(tree.getTreeCondition())) {

hql += " and (" + tree.getTreeCondition() + ")";

}

session.createQuery(hql).setParameter("offset", offset).setParameter(

"nodeLft", nodeLft).setParameter("nodeRgt", nodeRgt)

.executeUpdate();

if (log.isDebugEnabled()) {

log.debug("adjust self hql: {}, offset={}, nodeLft={}, nodeRgt={}",

new Object[] { hql, offset, nodeLft, nodeRgt });

}

 

// 最后删除(清空位置)

String hql1 = "update " + beanName + " bean set bean."

+ tree.getRgtName() + " = bean." + tree.getRgtName() + " - "

+ span + " WHERE bean." + tree.getRgtName() + " > :nodeRgt";

String hql2 = "update " + beanName + " bean set bean."

+ tree.getLftName() + " = bean." + tree.getLftName() + " - "

+ span + " WHERE bean." + tree.getLftName() + " > :nodeRgt";

if (!StringUtils.isBlank(tree.getTreeCondition())) {

hql1 += " and (" + tree.getTreeCondition() + ")";

hql2 += " and (" + tree.getTreeCondition() + ")";

}

session.createQuery(hql1).setParameter("nodeRgt", nodeRgt)

.executeUpdate();

session.createQuery(hql2).setParameter("nodeRgt", nodeRgt)

.executeUpdate();

if (log.isDebugEnabled()) {

log.debug("clear span hql1:{}, hql2:{}, nodeRgt:{}", new Object[] {

hql1, hql2, nodeRgt });

}

// 再调整自己

String hql44 = "select bean." + tree.getLftName() + ",bean."

+ tree.getRgtName() + " from " + beanName

+ " bean where bean.id=:id";

Object[] position44 = (Object[]) session.createQuery(hql44).setParameter(

"id", tree.getId()).uniqueResult();

int nodeLft44 = ((Number) position44[0]).intValue();

int nodeRgt44 = ((Number) position44[1]).intValue();

System.out.println(nodeLft44+"======"+nodeRgt44);

session.setFlushMode(model);

return true;

}

比如我现在有四个节点:

ID  name   pid   lft   rgt

33  食品   null   1     8

34  蔬菜   33     2     7

35  白菜   34     3      4

36  萝卜   34     5      6

我现在要把36放到33下面(pid=33)

理想的结果是

ID  name   pid   lft   rgt

33  食品   null   1     8

34  蔬菜   33     4     7

35  白菜   34     5     6

36  萝卜   33     2      3

但是实际结果是ID36的lft 、rgt没有改过来还是5 、6

我断点加在拦截器中updateparent方法调试的时候一直到下面System.out.println(nodeLft44+"======"+nodeRgt44);输出都是对的,断点接着往下走到hibernate :DefaultFlushEventListener这个方法的时候会重新发一条update语句把ID36数据的lft、rgt又重新修改回去了,这两天始终没弄明白为什么。。。其它几个的lft和rgt都对了,就把ID36的重新置回去了。。。求解啊!!!!

 

加载中
返回顶部
顶部