Dojo submit and Database Engine

今天给前面纯javascript写的Magic Grid增加一个排行的功能,也就是在玩家完成游戏后,可以输入姓名并提交,可以查看当前排名Top10的玩家名称和分数。

功能上并不复杂,不过当前工作的项目是J2EE的,那么就使用相关的技术来实现这个小功能:SSH+MySql+Maven。

整个过程中遇到了两个问题印象比较深刻。

使用Ajax提交结果

Struts常用的Ajax插件有下面几种:

对我这个只是提交的小应用来说,几种都差不多,网上似乎关于Dojo的例子不少,所以选用了struts-dojo-tags。使用起来也非常简单,

  1. 在pom.xml中加入依赖
1
2
3
4
5
  <dependency>
         <groupId>org.apache.struts</groupId>
         <artifactId>struts2-dojo-plugin</artifactId>
         <version>2.2.1</version>
   </dependency>
  1. 在jsp文件头部添加下面一行语句
1
  <%@ taglib prefix="sx" uri="/struts-dojo-tags" %>

下面是我第一次写的用来提交的表单代码

1
2
3
4
5
6
7
8
9
<s:form action="submit" method="post" theme="simple">
  <sx:div id="rank">
      <s:label value="Input your name: " for="rankBean.name"/>
      <s:textfield key="rankBean.name"/>
      <s:hidden key="rankBean.score"/>
      <img id="loadingImage" src="images/loading.gif" style="display:none"/>
      <sx:submit targets="rank" showLoadingText="false" indicator="loadingImage"/>
  </sx:div>
</s:form>

sx:submit设定了用来接收响应的元素是id为rank的div,在得到响应之前显示一个loading image。 这个“照搬”Struts网站上关于Dojo submit使用的代码看似没有问题,但是很tricky的是每次点击submit按钮都会同时发送两个相同的post请求。 纠缠了很久才发现,我使用的并不正确,其中id为rank的div不能使用sx:div, 而只要改为struts本身提供的s:div便只会发送一个请求了。

但是现在仍然还不知道这样解决的原因何在,网上只找到了一篇相关的blog,只有一个评论──“won’t fix”。有待后续找到答案,也诚恳希望有相关经验的同志们给予答复。

Database Engine

在Spring框架内写Hibernate的测试,利用Spring的Transaction机制,可以方便的保持测试数据的整洁。 测试代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<pre class="brush:java">@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
@Transactional
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"../config/applicationContextForTest.xml"})
public class HibernateRankDaoTest {

    @Autowired
    private SessionFactory sessionFactory;
    @Autowired
    private HibernateRankDao rankDao;
    private Rank rank;

    @Before
    public void setUp() throws Exception {
        rank = RankUtil.defaultRank();
        rankDao.saveOrUpdate(rank);
    }

    @Test
    public void should_update_rank(){
        Rank saved = rankDao.get(rank.getName());
        saved.setScore(200);
        rankDao.saveOrUpdate(saved);
        Rank result = rankDao.get(rank.getName());
        assertEquals(saved.getId(), result.getId());
        assertEquals(200, result.getScore());
    }
}

测试功能也非常简单直接,但是无论如何也无法在执行完测试后rollback所有的数据。尝试了各种Spring和Hibernate的配置,都没有作用。 最后发现,问题其实是Mysql数据库本身。Mysql默认使用的engine是MyISAM,而它是不支持Transaction的!改成InnoDB,就一切OK了。 关于InnoDB与MyISAM比较,可参考 http://www.mikebernat.com/blog/MySQL-InnoDBvsMyISAM

comments powered by Disqus