春天 + JPA“超出锁定等待超时;尝试重新启动事务”

发布于 2025-01-02 11:28:13 字数 3633 浏览 0 评论 0原文

我是 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...
}

DAO:

@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 造成的:如果我注释掉 TeaDown() 方法,则不会发生错误

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文