Spring + JPA“超出锁定等待超时;尝试重启事务”

时间:2012-02-02 17:20:03

标签: spring jpa transactions dbunit

我是Spring和JPA的新手,我遇到了标题中指定的问题。为了简化问题,我有两个类:User和FeedItem。用户可以拥有更多FeedItem,但关系是双向的(FeedItem知道它与哪个用户相关联)。它们都使用JPA + Hibernate持久保存在数据库中:

@Entity
@Table
public class User
{
    @Id
    @GeneratedValue
    @Column(name = "id", nullable = false, length = 8)
    private int id;

    @Column(nullable = false, length = 32, unique = true)
    private String alias;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "user")
    private List<FeedItem> feedItems = new ArrayList<FeedItem>();

    public User()
    {
    }

    public User(String alias)
    {
        this.alias = alias;
    }

    ... getters/setters...
}


@Entity
@Table
public class FeedItem
{
    @Id
    @GeneratedValue
    @Column(name = "id", nullable = false, length = 16)
    private int id;

    @Column(nullable = false, length = 64)
    private String title;

    @ManyToOne
    @JoinColumn(name = "userId", nullable = false)
    private User user;

    public FeedItem()
    {
    }

    public FeedItem(String title, User user)
    {
        this.title = title;
        this.user = user;
    }

    ... getters/setters...
}

DAOs:

@Repository
public class UserJpaDao implements UserDao
{
    private EntityManager em;

    @Transactional
    public User save(User user)
    {
        return this.em.merge(user);
    }

    @Transactional
    public void delete(User user)
    {
        this.em.remove(user);
    }

    @Transactional(readOnly = true)
    public User findById(int id)
    {
        return this.em.find(User.class, id);
    }

    @PersistenceContext
    void setEntityManager(EntityManager entityManager)
    {
        this.em = entityManager;
    }
}


@Repository
public class FeedItemJpaDao implements FeedItemDao
{
    private EntityManager em;

    @Transactional
    public FeedItem save(FeedItem feedItem)
    {
        return this.em.merge(feedItem);
    }

    @Transactional
    public void delete(FeedItem feedItem)
    {
        this.em.remove(feedItem);
    }

    @Transactional
    public FeedItem findById(int id)
    {
        return this.em.find(FeedItem.class, id);
    }

    @PersistenceContext
    void setEntityManager(EntityManager entityManager)
    {
        this.em = entityManager;
    }
}

这是给出错误的测试:

@RunWith(SpringJUnit4ClassRunner.class)
public class FeedItemJpaDaoTest
{
    @Autowired
    private DriverManagerDataSource dataSource;

    @Autowired
    private FeedItemJpaDao feedItemDao;

    @Autowired
    private UserJpaDao userDao;

    @Before
    @Transactional
    public void setUp() throws Exception
    {
        DatabaseOperation.CLEAN_INSERT.execute(getConnection(), getDataSet());
    }

    @After
    @Transactional
    public void tearDown() throws Exception
    {
        DatabaseOperation.DELETE_ALL.execute(getConnection(), getDataSet());
    }

    @Test
    @Transactional
    public void testSave() throws Exception
    {
        User user = userDao.findById(3);
        FeedItem feedItem = new FeedItem("Achievement unlocked!", user);
        feedItem = feedItemDao.save(feedItem);
        assertEquals(feedItem, feedItemDao.findById(feedItem.getId()));
    }

    private IDatabaseConnection getConnection() throws Exception
    {
        return new DatabaseConnection(dataSource.getConnection());
    }

    private IDataSet getDataSet() throws Exception
    {
        return new FlatXmlDataSetBuilder().build(new File("src/test/resources/dataset.xml"));
    }
}

我不明白错误发生的原因 - 任何建议都表示赞赏!

谢谢。

编辑:似乎问题是由于DbUnit:如果我注释掉tearDown()方法,则错误不会出现