鉴于典型的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...
}
我是否会让自己陷入伤害这个世界?
答案 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
没有被注入可能不是你想要的,但你拥有它。