其他分享
首页 > 其他分享> > hibernate – 对spring中的实体管理器的静态访问和不寻常的架构

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

作者:互联网

快速提问:

我有webapplication(wicket spring jpa)并且正在考虑相当不寻常的架构设计.请检查并发表您的意见.

考虑类包装器:

@Service
public class Wrapper {
    protected static EntityManager entityManager;

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

如你所见,我现在已经静态注入了EntityManager.

现在考虑简单的实体DogEntity

@Entity
public class DogEntity {
   String name;
}

对于那个实体,我们创建了包装狗

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);
  }
}

现在在我的webapplication(在我的控制器中)我可以做这样的事情:

saveButton = new Button("save") {

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

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

我真正关心的是这个静态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;
  }    
}

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

>你需要AspectJ
>此行EntityManager em = new MyEntity().entityManager;非常难看
>如果你想模仿持久的“层”,测试会变得有点困难.但幸运的是,Spring提供了一个特殊的AOP拦截器(@see JavaDoc of org.springframework.mock.staticmock.AnnotationDrivenStaticEntityMockingControl)

但它也有一些很好的效果:例如,持久化和删除方法变得非常自然,它们只是实体的成员:

@Transactional
public void persist() {
    if (this.entityManager == null) this.entityManager = entityManager();
    this.entityManager.persist(this);
}

要创建一个可用于@Configurable的无Roo项目,您需要至少执行以下操作:

扩展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"> 
  -->

标签:spring,jpa,hibernate,entitymanager,static-members
来源: https://codeday.me/bug/20190826/1734214.html