gpt4 book ai didi

hibernate - Spring 中对实体管理器的静态访问和不寻常的架构

转载 作者:行者123 更新时间:2023-12-02 09:12:13 27 4
gpt4 key购买 nike

快速问题:

我有网络应用程序(wicket+spring+jpa),并且正在考虑相当不寻常的架构设计。请检查并提出您的意见。

考虑类包装器:

@Service
public class Wrapper {
protected static EntityManager entityManager;

@PersistenceContext
private void injectEntityManager(EntityManager entityManager) {
Wrapper.entityManager = entityManager;
}

如您所见,我现在已经静态注入(inject)了 EntityManager。

现在考虑简单的实体 DogEntity

@Entity
public class DogEntity {
String name;
}

对于该实体,我们创建包装器 Dog

public class Dog extends Wrapper {
private DogEntity entity;

private Dog(DogEntity entity) {
this.entity = entity;
}

public static Dog create(String name) {
entity = new DogEntity();
entity.name = name;
entityManager.persist(entity); // for a moment forget that this code is not in transaction
return new Dog(entity);
}
}

现在在我的网络应用程序(在我的 Controller 中)我可以做这样的事情:

saveButton = new Button("save") {

public void onSubmit() {
Dog dog = Dog.create(name);
// other code
}

从代码的角度来看,这个架构看起来很完美。我们有代表业务对象的包装器。它们都有持久状态,在名为 DogSaver 的应用程序中没有愚蠢的服务,其方法 save(DogEntity) 只在实体管理器上调用持久化。代码确实具有很高的可读性,并且还有其他一些优点,但我不会详细介绍。

我真正关心的是这个静态EntityManager。我对 Spring 的内部结构没有足够的了解,不知道这种方法是否正确且安全。是否存在事情可能变得丑陋的情况?我知道 EntityManare 是无状态的(根据 JPA 规范),它总是从事务中获取持久化上下文,因此使其静态似乎不是一个坏主意。但我担心我可能会弄乱一些东西。

有什么想法吗?

最佳答案

你应该看看Spring Roo。他们有一些类似的东西(没有 DAO 或服务),但 EntityManager 不是静态的。

他们使用实体中的 @Configurable 注释来实现这一点:

@Entiy
@Configurable
class MyEntity() {

@PersistenceContext
transient EntityManager Car.entityManager;

...

public static MyEntity findMyEntityById(Long id) {
if (id == null) return null;
return entityManager().find(MyEntity.class, id);
}

public static EntityManager entityManager() {
EntityManager em = new MyEntity().entityManager;
if (em == null) throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
return em;
}
}

无论如何,它有两三个缺点:

但它也有一些不错的效果:例如 persist 和 delete 方法变得非常自然,它们只是实体的成员:

@Transactional
public void persist() {
if (this.entityManager == null) this.entityManager = entityManager();
this.entityManager.persist(this);
}
<小时/>

要使非 Roo 项目可用于 @Configurable,您至少需要这样做:

扩展pom.xml:

<properties>
<spring.version>3.0.5.RELEASE</spring.version>
<aspectj.version>1.6.11</aspectj.version>
<aspectj-maven-plugin.version>1.2</aspectj-maven-plugin.version>
<maven-compiler-plugin.version>2.3.2</maven-compiler-plugin.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

...

<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectj.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>

...

        <plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>${aspectj-maven-plugin.version}</version>
<!-- NB: do use 1.3 or 1.3.x due to MASPECTJ-90 - wait for 1.4 -->
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>${aspectj.version}</version>
</dependency>
<!--
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-aspects</artifactId>
<version>3.0.5.RELEASE</version>
</dependency>
-->
</dependencies>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
<configuration>
<outxml>true</outxml>
<aspectLibraries>
<aspectLibrary>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</aspectLibrary>
<!--
<aspectLibrary>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-aspects</artifactId>
</aspectLibrary>
-->
</aspectLibraries>
<source>1.6</source>
<target>1.6</target>
<encoding>utf-8</encoding>
</configuration>
</plugin>

Spring 配置:

<!-- Turn on AspectJ @Configurable support. As a result, any time you instantiate an object,
Spring will attempt to perform dependency injection on that object.
This occurs for instantiation via the "new" keyword, as well as via reflection.
This is possible because AspectJ is used to "weave" Roo-based applications at compile time.
In effect this feature allows dependency injection of any object at all in your system,
which is a very useful feature (without @Configurable you'd only be able to
dependency inject objects acquired from Spring or subsequently presented to
a specific Spring dependency injection method). -->
<context:spring-configured />

<tx:annotation-driven mode="aspectj" transaction-manager="transactionManager" />

<!--
Spring Security:
requires version 3.0.4 of Spring Security XSD: spring-security-3.0.4.xsd
<global-method-security ... mode="aspectj">
-->

关于hibernate - Spring 中对实体管理器的静态访问和不寻常的架构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7007205/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com