ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

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

2019-08-26 22:19:51  阅读:222  来源: 互联网

标签:spring jpa hibernate entitymanager static-members


快速提问:

我有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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有