当前位置: 首页 > 知识库问答 >
问题:

测试失败,出现TransactionRequiredException:加载JPA和Neo4J配置时没有事务正在进行中异常

胡玉书
2023-03-14

我有一个JPA web应用程序,其中包含一些针对JPA存储库的集成测试。目前还没有针对Neo4J存储库的集成测试。

现在,我已经向这个现有的JPA web应用程序添加了一些Neo4J功能。

我现在使用Neo4J存储库和JPA存储库。我的实体和存储库的名称不同,并且位于不同的包中。

我的所有测试都扩展了以下类:

@WebAppConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { ApplicationConfiguration.class, WebSecurityTestConfiguration.class, WebConfiguration.class })
@Transactional
public abstract class AbstractControllerTest {
...
}

当应用程序配置没有任何配置时,测试可以正常运行

Neo4J configuration:
@Configuration
@ComponentScan(basePackages = { "it.robot.rest.config" })
@Import({ DatabaseConfiguration.class, Log4jWeb.class })
public class ApplicationConfiguration {
}

但在添加Neo4J配置时出现异常错误:

@Configuration
@ComponentScan(basePackages = { "it.robot.rest.config" })
@Import({ DatabaseConfiguration.class, Neo4JRepositoryConfiguration.class, Log4jWeb.class })
public class ApplicationConfiguration {
}

例外情况是:

javax.persistence.TransactionRequiredException: no transaction is in progress

以下是Neo4J配置(我尝试了Neo4jConfiguration和CrossStoreNeo4jConfiguration类,得到了相同的异常):

@Configuration
@EnableNeo4jRepositories(basePackages = { "it.robot.data.neo4j.repository" } )
@EnableTransactionManagement
@ComponentScan(basePackages = { "it.robot.data.neo4j.service" })
public class Neo4JRepositoryConfiguration extends Neo4jConfiguration {

  public static final String URL = "http://localhost:7474/db/data/";
  public static final String LOGIN = "neo4j";
  public static final String PASSWORD = "mypassword";

  Neo4JRepositoryConfiguration() {
    setBasePackage("it.robot.data.neo4j.domain"); 
  }

  @Bean
  GraphDatabaseService graphDatabaseService() { 
    return new SpringCypherRestGraphDatabase(URL, LOGIN, PASSWORD);
  }

}

以下是JPA的配置:

@Configuration
@Import({ JpaService.class, Log4j.class })
@EnableTransactionManagement
@ComponentScan(basePackages = { "it.robot.data.config" })
@EnableJpaRepositories(basePackages = { "it.robot.data.jpa" }, repositoryFactoryBeanClass  = it.robot.data.jpa.repository.GenericRepositoryFactoryBean.class)
public class DatabaseConfiguration {
...
}

Neo4jConfiguration类事务管理器似乎与JPA事务管理器具有相同的名称("transactionManager"),并将其重写。

我对使用Spring提供的JPA事务管理器的Neo4J感到满意,但我想知道这是否可行。

一些额外的信息...

我使用的是spring-data-neo4j和spring-data-neo4j-rest版本3.3。2.释放

我使用的是服务器Neo4J数据库,而不是嵌入式数据库,当然,Neo4J服务器已经启动。

我禁用了数据库上的身份验证,因为它挡住了我的去路,我的curl请求似乎没有更新密码:

curl -H "Accept:application/json" 
 -H "Content-Type: application/json" 
 "http://localhost:7474/user/neo4j/password" 
 -X POST -d "{ \"password\" : \"myownpassword\" }"

我所知道的唯一一个用户似乎不太直言不讳:

stephane@stephane-ThinkPad-X301:~> curl -H "Accept:application/json" -H "Content-Type: application/json" "http://localhost:7474/user/neo4j"
stephane@stephane-ThinkPad-X301:~> 
stephane@stephane-ThinkPad-X301:~>

我没有在图中创建任何“模式/结构”,也不确定是否应该这样做。

Neo4J实体:

@NodeEntity
@SequenceGenerator(name = "id_generator", sequenceName = "sq_id_part")
public class Neo4JPart extends BaseEntity {

  @Column(nullable = false)
  private String name;
  @Column(nullable = false, unique = true)
  private String serialNumber;
  private Integer weight;
  @ManyToOne
  @JoinColumn(name = "manufacturer_id", nullable = false)
  private Neo4JManufacturer manufacturer;
  @Fetch
  @RelatedTo(type = "part", direction = Direction.BOTH)
  public Set<Neo4JPart> parts;

  public Neo4JPart() {
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public String getSerialNumber() {
    return serialNumber;
  }

  public void setSerialNumber(String serialNumber) {
    this.serialNumber = serialNumber;
  }

  public Integer getWeight() {
    return weight;
  }

  public void setWeight(Integer weight) {
    this.weight = weight;
  }

  public Neo4JManufacturer getManufacturer() {
    return manufacturer;
  }

  public void setManufacturer(Neo4JManufacturer manufacturer) {
    this.manufacturer = manufacturer;
  }

  public Set<Neo4JPart> getParts() {
    return parts;
  }

  public void setParts(Set<Neo4JPart> parts) {
    this.parts = parts;
  }

  public String toString() {
    String results = name + "'s compatible parts include\n";
    if (parts != null) {
      for (Neo4JPart part : parts) {
        results += "\t- " + part.name + "\n";
      }
    }
    return results;
  }

}

@MappedSuperclass
public class BaseEntity {

  @GraphId
  @GeneratedValue(strategy = GenerationType.AUTO, generator = "id_generator")
  @Column(name = "id")
  private Long id;

  @Version
  @Column(nullable = false)
  private int version;

  public Long getId() {
    return id;
  }

  public void setId(Long id) {
    this.id = id;
  }

  public int getVersion() {
    return this.version;
  }

  public void setVersion(int version) {
    this.version = version;
  }

  @Override
  public boolean equals(Object obj) {
    if (this == obj) {
      return true;
    }

    if (this.id == null || obj == null || !(this.getClass().equals(obj.getClass()))) {
      return false;
    }

    BaseEntity that = (BaseEntity) obj;

    return this.id.equals(that.getId());
  }

  @Override
  public int hashCode() {
    return id == null ? 0 : id.hashCode();
  }

}

和Neo4J仓库:

public interface Neo4JPartRepository extends GraphRepository<Neo4JPart> {

  public Neo4JPart findByName(String name);

  public Neo4JPart findBySerialNumber(String serialNumber);

  public Page<Neo4JPart> findByManufacturer(@Param("manufacturer") Neo4JManufacturer manufacturer, Pageable page);

  public List<Neo4JPart> findByManufacturer(@Param("manufacturer") Neo4JManufacturer manufacturer);

  public Page<Neo4JPart> findByPartsName(String name, Pageable page);

}

public interface Neo4JManufacturerRepository extends GraphRepository<Neo4JManufacturer> {

  Neo4JManufacturer findByName(String name);

}

Maven依赖关系是:

  <org.springframework.version>4.1.2.RELEASE</org.springframework.version>
  <hibernate.version>4.3.6.Final</hibernate.version>

  <dependencies>
    <dependency>
      <groupId>com.thalasoft</groupId>
      <artifactId>toolbox</artifactId>
      <version>0.0.1-SNAPSHOT</version>
    </dependency>
    <dependency>
      <groupId>com.mchange</groupId>
      <artifactId>c3p0</artifactId>
      <version>0.9.2.1</version>
    </dependency>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.34</version>
    </dependency>
    <dependency> 
      <groupId>com.oracle</groupId> 
      <artifactId>ojdbc6</artifactId> 
      <version>11.2.0.3</version> 
    </dependency>
    <dependency>
      <groupId>com.h2database</groupId>
      <artifactId>h2</artifactId>
      <version>1.3.172</version>
    </dependency>
    <dependency>
      <groupId>org.hsqldb</groupId>
      <artifactId>hsqldb</artifactId>
      <version>2.3.2</version>
    </dependency>
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-core</artifactId>
      <version>${hibernate.version}</version>
    </dependency>
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-entitymanager</artifactId>
      <version>${hibernate.version}</version>
    </dependency>
    <dependency>
      <groupId>org.hibernate.javax.persistence</groupId>
      <artifactId>hibernate-jpa-2.1-api</artifactId>
      <version>1.0.0.Final</version>
    </dependency>
    <dependency>
      <groupId>org.springframework.data</groupId>
      <artifactId>spring-data-jpa</artifactId>
      <version>1.6.2.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>com.mysema.querydsl</groupId>
      <artifactId>querydsl-core</artifactId>
      <version>3.5.0</version>
    </dependency>
    <dependency>
      <groupId>com.mysema.querydsl</groupId>
      <artifactId>querydsl-apt</artifactId>
      <version>3.5.0</version>
    </dependency>
    <dependency>
      <groupId>com.mysema.querydsl</groupId>
      <artifactId>querydsl-jpa</artifactId>
      <version>3.5.0</version>
    </dependency>
    <dependency>
      <groupId>org.springframework.data</groupId>
      <artifactId>spring-data-commons</artifactId>
      <version>1.10.2.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>javax.validation</groupId>
      <artifactId>validation-api</artifactId>
      <version>1.1.0.Final</version>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.10</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>1.6.4</version>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-log4j12</artifactId>
      <version>1.6.4</version>
    </dependency>
    <dependency>
      <groupId>org.lazyluke</groupId>
      <artifactId>log4jdbc-remix</artifactId>
      <version>0.2.7</version>
    </dependency>
    <dependency>
      <groupId>javax.mail</groupId>
      <artifactId>mail</artifactId>
      <version>1.4</version>
    </dependency>
    <dependency>
      <groupId>joda-time</groupId>
      <artifactId>joda-time</artifactId>
      <version>2.5</version>
    </dependency>
    <dependency>
      <groupId>org.jadira.usertype</groupId>
      <artifactId>usertype.jodatime</artifactId>
      <version>2.0.1</version>
    </dependency>
    <dependency>
      <groupId>javax.transaction</groupId>
      <artifactId>jta</artifactId>
      <version>1.1</version>
    </dependency>
    <dependency>
      <groupId>org.jasypt</groupId>
      <artifactId>jasypt</artifactId>
      <version>1.7</version>
    </dependency>
    <dependency>
      <groupId>org.assertj</groupId>
      <artifactId>assertj-core</artifactId>
      <version>1.6.1</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>${org.springframework.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-beans</artifactId>
      <version>${org.springframework.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>${org.springframework.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context-support</artifactId>
      <version>${org.springframework.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>${org.springframework.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-tx</artifactId>
      <version>${org.springframework.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-orm</artifactId>
      <version>${org.springframework.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>${org.springframework.version}</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-oxm</artifactId>
      <version>${org.springframework.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aop</artifactId>
      <version>${org.springframework.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-expression</artifactId>
      <version>${org.springframework.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework.data</groupId>
      <artifactId>spring-data-neo4j</artifactId>
      <version>3.3.2.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework.data</groupId>
      <artifactId>spring-data-neo4j-rest</artifactId>
      <version>3.3.2.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework.data</groupId>
      <artifactId>spring-data-neo4j-cross-store</artifactId>
      <version>3.3.2.RELEASE</version>
    </dependency>
  </dependencies>

我试图升级到3.4版本。搜索时新可用版本的0版本。专家org,但构建现在会出现以下异常:

AnnotationFormatError: Invalid default: public abstract java.lang.Class org.springframework.data.neo4j.config.EnableNeo4jRepositories.repositoryBaseClass()

我在参考文档中看不到关于repositoryBaseClass的任何内容http://docs.spring.io/spring-data/neo4j/docs/3.4.0.RELEASE/reference/pdf/spring-data-neo4j-reference.pdf

源代码Javadoc只说明:

Configure the repository base class to be used to create repository proxies for this particular configuration.

这让我摸不着头脑,想知道什么是存储库代理,在我的案例中是否需要。

共有1个答案

施翰学
2023-03-14

根据Simon关于如何使用Spring数据JPA Neo4j正确设置跨存储持久性的提示,我可以使用在实现Spring ChainedTransactionManager时提供的解决方案,根据链式事务管理器的“最大努力1PC”模式解决这个问题?

我只是不得不改变我的Neo4j配置。我甚至不必在另一个JPA事务管理器中碰任何东西。

以下是我的Neo4j配置:

@EnableNeo4jRepositories(basePackages = { "it.robot.data.neo4j.repository" })
@EnableTransactionManagement
@ComponentScan(basePackages = { "it.robot.data.neo4j.service" })
public class Neo4JRepositoryConfiguration extends Neo4jConfiguration {

  private static Logger logger = LoggerFactory.getLogger(Neo4JRepositoryConfiguration.class);

  public static final String URL = "http://localhost:7474/db/data/";
  public static final String LOGIN = "neo4j";
  public static final String PASSWORD = "xxxxx";

  Neo4JRepositoryConfiguration() {
    setBasePackage("it.robot.data.neo4j.domain");
  }

  @Bean
  GraphDatabaseService graphDatabaseService() {
    return new SpringCypherRestGraphDatabase(URL, LOGIN, PASSWORD);
  }

  @Autowired
  LocalContainerEntityManagerFactoryBean entityManagerFactory;

  @Override
  public PlatformTransactionManager neo4jTransactionManager(
      GraphDatabaseService graphDatabaseService) {
    return new ChainedTransactionManager(
        new JpaTransactionManager(entityManagerFactory.getObject()),
        new JtaTransactionManagerFactoryBean(graphDatabaseService).getObject());
  }

}
 类似资料: