Search code examples
springjpatransactionsdbunit

Spring + JPA "Lock wait timeout exceeded; try restarting transaction"


I'm new to Spring and JPA and I encountered the problem specified in the title. To simplify the problem, I have two classes: User and FeedItem. User can have more FeedItems but the relationship is bi-directional (FeedItem knows with which User it's associated). They're both persisted in the database using 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...
}

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

This is the test giving the error:

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

I don't understand why the error is happening -- any suggestion is appreciated!

Thank you.

EDIT: Seems like the problem is due to DbUnit: if I comment out the tearDown() method, the error doesn't occour


Solution

  • Solved the problem following this: http://tadaya.wordpress.com/2008/04/27/transaction-aware-datasource-use-dbunit-hibernate-in-spring/