【问题标题】:JPA Entities are not managed / relations not persistedJPA 实体不受管理/关系不持久
【发布时间】:2013-06-17 08:58:04
【问题描述】:

设置

我在 JBoss 4.3.2 上使用 JPA 1.0、Spring 3.0.6 和休眠 3.2.1。有一些 EJB 在某些时候调用 DAO 来尝试持久化两个实体。

问题

结果出乎意料:实体在调用.persist(entity)后没有被管理

有趣的是:一个非常相似的测试应用程序,它使用包含 DAO 的相同 jars,Beans persistence.xml 作为服务器应用程序,保持一切正常。调用.persist() 后管理bean。

实体

我有一个类Subscriber,它有一个SubscriberState

@Entity
@Table(name = "subscriber")
public class Subscriber implements java.io.Serializable {

    // all the other stuff

    @ManyToOne
    @JoinColumn(name = "status")
    private SubscriberState state;

}

由于遗留原因,SubscriberState 具有关系 Subscriber

@Entity
@Table(name = "subscriber_state")
public class SubscriberState implements java.io.Serializable {

    // ...blah

    @ManyToOne
    @JoinColumn(name = "subscriber", nullable = false)
    private Subscriber subscriber;
}

我要做什么来坚持

现在我尝试持久化一个订阅者,它将在 persist() 之后不受管理:

 final Subscriber subscriber = new Subscriber();
 // set up...
 entityManager.persist(subscriber);
 entityManager.contaons(subscriber); //will yield FALSE

添加SubscriberState 即可。但是只有一侧的关系会被存储到数据库中:

SubscriberState subscriberState = new SubscriberState();
subscriberState.setSubscriber(subscriber);
entityManager.persist(subscriberState);
entityManager.merge(subscriber);

SubscriberState.setSubscriber 看起来像这样: 公共无效 setSubscriber(最终订阅者订阅者){ this.subscriber = 订阅者; 订阅者.setState(this); }

查看数据库告诉我,SubscriberState 知道它是 Subscriber,但订阅者不知道它是 State

配置

这是(现在已修改和精简的)persistence.xml:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>

org.hibernate.ejb.HibernatePersistence java:jdbc/SODS

    <properties>
        <property name="hibernate.dialect" value="${db.hibernate.dialect}" />
        <property name="hibernate.validator.apply_to_ddl" value="false" />
        <property name="hibernate.validator.autoregister_listeners" value="false" />
        <property name="hibernate.cache.provider_class" value="org.jboss.ejb3.entity.TreeCacheProviderHook" />
        <property name="hibernate.treecache.mbean.object_name" value="jboss.cache:service=EJB3EntityTreeCache" />
        <property name="jboss.entity.manager.jndi.name" value="java:/SOEntityManager-${app.version}" />
        <property name="jboss.entity.manager.factory.jndi.name" value="java:/SOEntityManagerFactory-${app.version}" />
        <property name="hibernate.transaction.factory_class" value="org.hibernate.transaction.JTATransactionFactory" />
        <property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.JBossTransactionManagerLookup" />
    </properties>

    <class>com.stackoverflow.some.classes.i.cant.show.Here</class>

这里是我的 spring 上下文的相关部分:

    <context:annotation-config />

    <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />

    <jee:jndi-lookup id="entityManagerFactory" jndi-name="java:/SOEntityManagerFactory-${app.version}" />
    <jee:jndi-lookup id="entityManager" jndi-name="java:/SOEntityManager-${app.version}" />
    <jee:jndi-lookup id="soDataSource" jndi-name="java:jdbc/SODS" />

    <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager" />

    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.simple.SimpleJdbcTemplate">
        <constructor-arg ref="soDataSource" />
    </bean>

    <context:component-scan base-package="blah - secret" />
    <import resource="daoContext.xml" />
</beans>

任何想法,为什么这个配置不起作用?

【问题讨论】:

  • 如果您从subscriberState.setSubscriber(subscriber) 中删除逻辑并只设置订阅者,然后调用subscriber.setState(subscriberState); 会发生什么?也?包含返回 false 很奇怪,但是订阅者会进入数据库,否则当订阅者状态尝试引用它时会违反约束。
  • 还不能测试。资源被重新分配,其他项目优先。但是我会检查我是否可以再次处理这个问题!
  • 您是否收到任何异常?或者只是没有存储实体?

标签: java spring jpa orm jboss


【解决方案1】:

我没有看到在您的 DAO 或服务层中使用 @Transaction

添加 SubscriberState 将起作用。但是只有一侧的关系会被存储到数据库中

你应该在

中使用级联选项
@ManyToOne(cascade = CascadeType.PERSIST)
@JoinColumn(name = "subscriber", nullable = false)
private Subscriber subscriber;

这将在持久化操作中保存关系的双方

另外我看到的是两个单向关系,不是一个双向关系,尝试使用mappedBy

@ManyToOne
@JoinColumn(name = "status")
private SubscriberState state;

除非那不是你想要的,但你应该重新考虑你的设计,使一侧 OneToMany 和另一侧 ManyToOne,使用 mappedBy 来定义关系的来源(所有者)

【讨论】:

  • 我无法重新设计它。这(可悲)不是我(=我的客户)想要的。顺便说一句,我的 DAO 周围有一个交易。
【解决方案2】:

这发生在我的应用程序 JPA with MySQL 上。在属性文件中加载适当的数据库驱动程序类。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-09-22
    • 2018-04-09
    • 2013-07-02
    • 1970-01-01
    • 1970-01-01
    • 2014-10-20
    • 2012-12-17
    • 1970-01-01
    相关资源
    最近更新 更多