How to get Spring Data Neo4j and Spring Data JPA t

2020-04-11 04:21发布

I have an application that does some batch jobs using MySQL and, via REST, Neo4j server version.

I can't figure out how to make them to work together correctly: I can get to make work both of them, but not at the same time. The posts I've found around are not specific to the server version of Neo4j, and maybe that's where the problem is, since everything else seems ok to me.

My configuration:

JpaConfig

@Configuration
@EnableTransactionManagement(order=Ordered.HIGHEST_PRECEDENCE)
@PropertySource("META-INF/database.properties")
@ImportResource("classpath*:META-INF/repository.xml")
public class JpaConfig {
@Autowired
Environment env;

@Bean(destroyMethod = "close")
public DataSource dataSource() {
    DataSource dataSource = new DataSource();
    dataSource.setDriverClassName(env.getProperty("database.driverClassName"));
    dataSource.setUrl(env.getProperty("database.url"));
    dataSource.setUsername(env.getProperty("database.username"));
    dataSource.setPassword(env.getProperty("database.password"));
    dataSource.setTestOnBorrow(true);
    dataSource.setTestOnReturn(true);
    dataSource.setTestWhileIdle(true);
    dataSource.setTimeBetweenEvictionRunsMillis(1800000);
    dataSource.setNumTestsPerEvictionRun(3);
    dataSource.setMinEvictableIdleTimeMillis(1800000);
    dataSource.setValidationQuery("SELECT 1");
    return dataSource;
}

@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
    LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();
    entityManagerFactory.setDataSource(dataSource());
    entityManagerFactory.setPackagesToScan("it.smartblue.mcba.domain");
    entityManagerFactory.setJpaDialect(new HibernateJpaDialect());
    Map<String, String> jpaProperties = new HashMap<>();
    jpaProperties.put("hibernate.connection.charSet", "UTF-8");
    jpaProperties.put("hibernate.ejb.naming_strategy", "org.hibernate.cfg.EJB3NamingStrategy");
    jpaProperties.put("hibernate.bytecode.provider", "javassist");
    jpaProperties.put("hibernate.dialect", "org.hibernate.dialect.MySQL5InnoDBDialect");
    entityManagerFactory.setJpaPropertyMap(jpaProperties);
    entityManagerFactory.setPersistenceProvider(new HibernatePersistence());
    return entityManagerFactory;
}

@Bean
public PlatformTransactionManager transactionManager() {
    JpaTransactionManager transactionManager = new JpaTransactionManager();
    transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
    return transactionManager;
}

@Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
    return new PersistenceExceptionTranslationPostProcessor();
}
}

Neo4j.xml

<!-- neo4j configuration -->
<neo4j:config graphDatabaseService="graphDatabaseService" entityManagerFactory="entityManagerFactory"/>
<bean id="graphDatabaseService" class="org.springframework.data.neo4j.rest.SpringRestGraphDatabase">
    <constructor-arg index="0" value="http://192.168.11.186:7474/db/data" />
</bean>
<neo4j:repositories base-package="it.smartblue.mcba.neo4j.repository" />

With this configuration Mysql works perfectly, but Neo4j doesn't save any property to the nodes it creates.

If I remove the attribute entityManagerFactory="entityManagerFactory" Neo4j works, but I can't write to MySQL.

My services methods are annotated with @Transactional or @Neo4jTransactional, not both at the same time.

Inside the class org.springframework.data.neo4j.rest.SpringRestGraphDatabase for the graphDatabaseService bean I've found:

@Override
public Transaction beginTx() {
    // return super.beginTx();
    return new NullTransaction();
}

@Override
public TransactionManager getTxManager() {
    return new NullTransactionManager();
}

Maybe it's a work in progress? Or maybe I miss something...

I'm using Spring 3.1.2, Hibernate 4.1.4. Here is part of my pom.xml.

<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-jpa</artifactId>
    <version>1.2.0.RC1</version>
</dependency> 
  <!-- Neo4j dependencies -->
    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-neo4j</artifactId>
        <version>2.1.0.RC4</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-neo4j-rest</artifactId>
        <version>2.1.0.RC4</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-neo4j-cross-store</artifactId>
        <version>2.1.0.RC4</version>
    </dependency>

1条回答
聊天终结者
2楼-- · 2020-04-11 04:37

Finally I made it.

Instead of having two different transactionManagers, now I have only one ChainedTransactionManager.

I removed the transactionManager bean from JpaConfig and the neo4j.xml file, and added the following Neo4jConfig

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.neo4j.config.EnableNeo4jRepositories;
import org.springframework.data.neo4j.config.JtaTransactionManagerFactoryBean;
import org.springframework.data.neo4j.config.Neo4jConfiguration;
import org.springframework.data.neo4j.rest.SpringRestGraphDatabase;
import org.springframework.data.neo4j.transaction.ChainedTransactionManager;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;

@EnableNeo4jRepositories(basePackages = { "it.smartblue.mcba.neo4j.repository" })
@Configuration
public class Neo4jConfig extends Neo4jConfiguration {

    @Autowired
    LocalContainerEntityManagerFactoryBean entityManagerFactory;

    @Bean
    public SpringRestGraphDatabase graphDatabaseService() {
        return new SpringRestGraphDatabase("http://192.168.11.186:7474/db/data");
    }

    @Override
    @Bean(name = "transactionManager")
    public PlatformTransactionManager neo4jTransactionManager() throws Exception {
        return new ChainedTransactionManager(new JpaTransactionManager(entityManagerFactory.getObject()),
                new JtaTransactionManagerFactoryBean(graphDatabaseService()).getObject());
    }
}

Now I have to use on my methods only the @Transactional annotation

查看更多
登录 后发表回答