带有容器管理事务的 EclipseLink - persist() 不提交

Posted

技术标签:

【中文标题】带有容器管理事务的 EclipseLink - persist() 不提交【英文标题】:EclipseLink with container managed transactions - persist() does not commit 【发布时间】:2013-03-11 16:17:02 【问题描述】:

我正在使用带有 WebLogic 10.3.5 容器管理事务的 EclipseLink 2.1.3 与 Oracle 11g DB 交互。

我可以毫无问题地选择数据,但无法持久化实体。

日志中没有引发异常或错误,但没有数据提交到 ANNOUNCEMENT_DELIVERY_LOG 表。

AnnouncementDeliveryLog 实体与 Announcement 实体具有 @ManyToOne 关系。我首先检索一个现有的 Announcement Entity,然后根据查询结果创建一个 AnnouncementDeliveryLog Entity,将这两个 Entities 关联起来,并持久化。

任何关于我做错了什么或如何从 WebLogic 上的 EclipseLink 获取更多日志信息的建议将不胜感激。

AnnouncementDeliveryLog 实体:

@Entity
@Table(name = "ANNOUNCEMENT_DELIVERY_LOG")
public class AnnouncementDeliveryLog implements Serializable 

    @Id
    @Column(nullable = false)
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="ANNOUNCEMENT_DELIVERY_LOG_SEQ")
    @SequenceGenerator(name="ANNOUNCEMENT_DELIVERY_LOG_SEQ", sequenceName="ANNOUNCEMENT_DELIVERY_LOG_SEQ")
    private BigDecimal id;
    @Column(name = "RECIPIENT_ADDRESS ", nullable = false, unique = true, length = 240)
    private String recipientAddress;
    @ManyToOne
    @JoinColumn(name = "ANNOUNCEMENT_ID ")
    private Announcements announcement;

公告实体:

@Entity
@Table(name = "ANNOUNCEMENTS")
public class Announcements implements Serializable 
    @Id
    @Column(nullable = false)
    private BigDecimal id;
    @OneToMany(mappedBy = "announcement")
    private List<AnnouncementDeliveryLog> announcementDeliveryLogList;

Session Facade SLSB 执行事务:

@Stateless(name = "DeliveryEngineSessionFacade",
           mappedName = "Announcements-JMSDeliveryEngine-DeliveryEngineSessionFacade")
public class DeliveryEngineSessionFacadeBean implements DeliveryEngineSessionFacadeLocal 
    @Resource
    SessionContext sessionContext;
    @PersistenceContext(unitName = "JMSDeliveryEnginePersistenceUnit")
    private EntityManager em;

    private List<AnnouncementDeliveryLog> createNormalizedEmailADLsForAnnouncement(int announcementId) 
        List<Object[]> rawResultList;
        ArrayList<AnnouncementDeliveryLog> typedResultList = new ArrayList<AnnouncementDeliveryLog>();

        Query query =
            em.createNamedQuery(AnnouncementDeliveryLog.FIND_NORMALIZED_RECIPIENTS_FOR_ANNOUNCEMENT);
        query.setParameter(1, announcementId);
        rawResultList = query.getResultList();

        for (Object[] resultElement : rawResultList) 
            AnnouncementDeliveryLog adl = new AnnouncementDeliveryLog(getAnnouncementById(announcementId), (String)resultElement[1], (String)resultElement[2], "TO_SEND");
            adl = persistAnnouncementDeliveryLog(adl);
            typedResultList.add(adl);
        

        return typedResultList;
    

public AnnouncementDeliveryLog persistAnnouncementDeliveryLog(AnnouncementDeliveryLog announcementDeliveryLog) 
    em.persist(announcementDeliveryLog);
    return announcementDeliveryLog;


public Announcements getAnnouncementById(int announcementId) 
    Query query = em.createNamedQuery(Announcements.FIND_BY_ID);
    query.setParameter("id", announcementId);
    return (Announcements)query.getSingleResult();



SLSB 调用 Session Facade:

@Stateless(name = "RecipientsPopulationTimer",
           mappedName = "Announcements-AnnouncementDeliveryEngine-RecipientsPopulationTimer")
@Local(RecipientsPopulationTimerLocal.class)
public class RecipientsPopulationTimerBean implements RecipientsPopulationTimerLocal 
    @EJB
    DeliveryEngineSessionFacadeLocal sessionFacade;

persistence.xml

<?xml version="1.0" encoding="UTF-8" ?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
             version="2.0">
    <persistence-unit name="JMSDeliveryEnginePersistenceUnit">
        <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
        <jta-data-source>jdbc/announcementsDS</jta-data-source>
        <class>announcements.deliveryengine.jpa.entities.AnnEmailRecipientsFlattened</class>
        <class>announcements.deliveryengine.jpa.entities.AnnImRecipientsFlattened</class>
        <class>announcements.deliveryengine.jpa.entities.AnnouncementDeliveryLog</class>
        <class>announcements.deliveryengine.jpa.entities.Announcements</class>
        <class>announcements.deliveryengine.jpa.entities.AnnouncementRecipients</class>
        <class>announcements.deliveryengine.jpa.entities.AnnouncementRecipientsFlattenedId</class>
        <properties>
            <property name="eclipselink.target-server" value="WebLogic 10"/>
            <property name="eclipselink.logging.level" value="FINE"/>
            <property name="eclipselink.logging.exceptions" value="true"/>
            <property name="eclipselink.logging.timestamp" value="true"/>
            <property name="eclipselink.logging.thread" value="true"/>
            <property name="eclipselink.logging.session" value="true"/>
            <property name="eclipselink.logging.level.sql" value="FINE"/>
            <property name="eclipselink.logging.parameters" value="true"/>
            <property name="eclipselink.target-database" value="Oracle11"/>
        </properties>
    </persistence-unit>
</persistence>

【问题讨论】:

您没有显示我假设在 persistAnnouncementDeliveryLog 中的调用 persist 的代码,也没有显示如何将代码包装在事务中。只有在事务提交时才会发出语句 抱歉,我现在添加了 persist() 代码。我以为容器完全管理了交易?如果不是这样,我如何表示交易? 我认为容器会为每个方法调用隐含地给我一个 REQUIRED 事务类型。我是否必须明确注释我的方法才能成为这种情况? 【参考方案1】:

RecipientsPopulationTimerBean 被一个有超时的组件调用。

这意味着 EJB 事务被回滚,因为 DB 事务花费了太长时间。

在适当的 DB 事务方法上设置 @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) 可防止 EJB 超时和相关的 DB 回滚。

【讨论】:

以上是关于带有容器管理事务的 EclipseLink - persist() 不提交的主要内容,如果未能解决你的问题,请参考以下文章

使用 EclipseLink 处理 Spring 事务

内部异常:java.sql.SQLException:事务无法继续STATUS_COMMITTED

eclipselink 连接池

应用程序管理的 JPA,何时需要事务

添加带有 JPA 注释的现有方法签名的接口会破坏 Eclipselink

提交带有全屏片段的片段事务