【问题标题】:Making an @Entity persist itself使@Entity 自身持久化
【发布时间】:2014-08-21 14:03:04
【问题描述】:

给定一个典型的 JPA 示例 such as this one,我们有这样的代码:

@Entity
public class Company {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    //...etc...
}

和:

public class CompanyDaoImpl implements CompanyDao {
    @PersistenceContext(unitName = "custdb")
    private EntityManager em;

    public void createCompany(final Company c) {
        em.persist(c);
    }
    //...etc...
}

(让我们忽略此示例中的@Stateless 属性)

阅读其他关于anaemic domain models 的网站以及why shouldn't JPA Entities contain business logic 上的问答,我为什么不能说:

@Entity
public class Company {
    @PersistenceContext(unitName = "custdb")
    private EntityManager em;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    public void create() {
        em.persist(this);
    }
    //...etc...
}

这样做我会让自己陷入一个受伤的世界吗?

【问题讨论】:

  • 看看 Spring Roo,尤其是 @RooActiveRecord

标签: java jpa


【解决方案1】:

一个可能的原因是,您可以创建更通用的解决方案,而不是在每个类中重复 CRUD(创建、读取、更新、删除)操作。

看看这个question。接受的答案给出了一个通用 DAO 的示例,该示例使用其操作的对象类型进行了参数化。这是一种很常见的模式。

【讨论】:

【解决方案2】:

在 Spring 测试中使用 JPA(Hibernate),我能够证明这是可能的。 假设这是您相当开明的实体:

models.so.haum.IntropectiveEntity.java

@Entity
public class IntrospectiveEntity {

    @Transient
    private EntityManager em;

    protected IntrospectiveEntity() { }

    public IntrospectiveEntity(final EntityManager em) {
        this.em = em;
    }

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    public void create() {
        em.persist(this);
    }

    public List<IntrospectiveEntity> all() {
        TypedQuery<IntrospectiveEntity> query = em.createQuery("SELECT ie FROM IntrospectiveEntity ie", IntrospectiveEntity.class);
        return query.getResultList();
    }
}

请注意,您必须将 EntityManager 标记为 @Transient,否则 JPA 将尝试将其映射为列。另请注意,我无法注入 EntityManager 实例,因此必须将其作为构造函数 arg 传递。

这是你的测试:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class IntrospectiveEntityTest {

    @PersistenceContext
    private EntityManager em;

    @Test
    @Transactional
    public void namaste() {
        IntrospectiveEntity introspectiveEntity = new IntrospectiveEntity(em);
        introspectiveEntity.create();

        assertThat(introspectiveEntity.all().size(), IsEqual.equalTo(1));
    }

    @Configuration
    @ComponentScan(basePackages = "so")
    static class IntrospectiveEntityConfiguration {

        @Bean
        public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
            JpaTransactionManager transactionManager = new JpaTransactionManager();
            transactionManager.setEntityManagerFactory(entityManagerFactory);
            return transactionManager;
        }

        @Bean
        public LocalContainerEntityManagerFactoryBean entityManager(DataSource dataSource) {
            LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();

            HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
            jpaVendorAdapter.setGenerateDdl(true);
            jpaVendorAdapter.setShowSql(true);
            entityManagerFactory.setJpaVendorAdapter(jpaVendorAdapter);

            entityManagerFactory.setDataSource(dataSource);
            entityManagerFactory.setPackagesToScan("so.models.haum");
            return entityManagerFactory;
        }

        @Bean
        public DataSource dataSource() {
            EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
            EmbeddedDatabase dataSource = builder.setType(EmbeddedDatabaseType.H2).build();
            return dataSource;
        }
    }
}

成功通过。坚持和发现自己。 因此,如果您真的想这样做,那是可能的。显然,没有被注入的EntityManager 可能不是你想要的,但你有它。

【讨论】:

    猜你喜欢
    • 2023-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-19
    • 1970-01-01
    相关资源
    最近更新 更多