让@Entity继续存在

时间:2014-07-01 05:28:04

标签: java jpa

鉴于典型的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...
}

我是否会让自己陷入伤害这个世界?

2 个答案:

答案 0 :(得分:1)

一个可能的原因是,您可以创建更通用的解决方案,而不是复制每个类中的CRUD(创建,读取,更新,删除)操作,从而允许您使用多个类的实例。

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

答案 1 :(得分:1)

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

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没有被注入可能不是你想要的,但你拥有它。