最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

使用SpringData同時訪問MySQL和Neo4j數(shù)據(jù)庫

 更新時間:2025年08月08日 11:01:38   作者:磊磊落落  
本文通過使用SpringData在SpringBoot中配置MySQL和Neo4j雙數(shù)據(jù)源,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

本文將以實例的方式探索「如何使用 Spring Data 同時訪問 MySQL 和 Neo4j 數(shù)據(jù)庫?」,涉及 Spring Boot 中多個數(shù)據(jù)源的配置、多個事務(wù)的配置,以及多組 Repository 的使用。

為了使演示工程更接近于實際,我們特為該工程設(shè)定一個場景:即使用該工程實現(xiàn) MySQL 到 Neo4j 的數(shù)據(jù)遷移。技術(shù)上會涉及使用兩組 Repository 進行讀寫,以及關(guān)系型數(shù)據(jù)庫的表到 Neo4j 的 Node 和 Relationship 的轉(zhuǎn)換。

介紹工程結(jié)構(gòu)和主要代碼塊之前,先演示一下該工程實現(xiàn)的功能:

1 功能展示

該工程針對 MySQL 的三張表進行了數(shù)據(jù)遷移,遷移到 Neo4j 后變?yōu)榱?Node 和 Relationship。

MySQL 中的三張表為:actor(演員)、movie(電影)、actor_movie(演員電影關(guān)系表)。

建表語句與插入語句如下:

CREATE TABLE actor (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    nationality VARCHAR(100) NOT NULL,
    year_of_birth INT NOT NULL
);

CREATE TABLE movie (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    released_at INT NOT NULL
);

CREATE TABLE actor_movie (
    actor_id BIGINT NOT NULL,
    movie_id BIGINT NOT NULL,
    role VARCHAR(100) NOT NULL,
    PRIMARY KEY (actor_id, movie_id)
);

INSERT INTO actor(name, nationality, year_of_birth) VALUES
    ('吳京', '中國', 1974),
    ('盧靖姍', '中國', 1985);

INSERT INTO movie(name, released_at) VALUES
    ('戰(zhàn)狼 Ⅱ', 2017),
    ('太極宗師', 1998),
    ('流浪地球 Ⅱ', 2023),
    ('我和我的家鄉(xiāng)', 2020);

INSERT INTO actor_movie(actor_id, movie_id, role) VALUES
    (1, 1, '冷峰'),
    (1, 2, '楊昱乾'),
    (1, 3, '劉培強'),
    (2, 1, 'Rachel'),
    (2, 4, 'EMMA MEIER');

進行數(shù)據(jù)遷移后,Neo4j 中的 Node 和 Relationship 如下:

功能展示完成后,下面介紹該示例工程的結(jié)構(gòu)以及關(guān)鍵代碼塊。

2 工程結(jié)構(gòu)及關(guān)鍵代碼分析

該示例工程是一個使用 Maven 管理的 Spring Boot 工程,其各依賴項及其版本如下:

Java: Liberica JDK 17.0.7
Maven: 3.9.2
Spring Boot: 3.4.5

2.1 工程結(jié)構(gòu)及依賴

該示例工程的結(jié)構(gòu)如下:

spring-data-jpa-and-neo4j-demo
├─ src
│  ├─ main
│  │  ├─ java
│  │  │  └─ com.example.demo
│  │  │     ├─ config
│  │  │     │  ├─ MySQLConfig.java
│  │  │     │  └─ Neo4jConfig.java
│  │  │     ├─ repository
│  │  │     │  ├─ graph
│  │  │     │  │  ├─ GraphActorRepository.java
│  │  │     │  │  └─ GraphMovieRepository.java
│  │  │     │  └─ relational
│  │  │     │  │  ├─ ActorRepository.java
│  │  │     │  │  ├─ MovieRepository.java
│  │  │     │  │  └─ ActorMovieRepository.java
│  │  │     ├─ service
│  │  │     │  ├─ MigrationService.java
│  │  │     │  └─ impl
│  │  │     │     └─ MigrationServiceImpl.java
│  │  │     ├─ model
│  │  │     │  ├─ graph
│  │  │     │  │  ├─ GraphActor.java
│  │  │     │  │  └─ GraphMovie.java
│  │  │     │  └─ relational
│  │  │     │  │  ├─ Actor.java
│  │  │     │  │  ├─ Movie.java
│  │  │     │  │  └─ ActorMovie.java
│  │  │     └─ DemoApplication.java
│  │  └─ resources
│  │     └─ application.yaml
│  └─ test
│     └─ java
│        └─ com.example.demo
│           └─ service
│              └─ MigrationServiceTest.java
└─ pom.xml

可以看到,其是一個標準的 Maven 工程,DemoApplication.java 為啟動類,application.yaml 為配置文件。config 包下用于放置配置類,MySQLConfig.javaNeo4jConfig.java 分別用于配置 MySQL 和 Neo4j 的連接信息讀取和事務(wù)管理。repository 包下用于放置訪問數(shù)據(jù)庫的 Repository 接口,其中 relational 子目錄下放置的是訪問 MySQL 的 Repository,graph 子目錄下放置的是訪問 Neo4j 的 Repository。model 包下放置 Model 類,relational 子目錄下放置的是對應(yīng) MySQL 表的 Model 類,graph 子目錄下放置的是對應(yīng) Neo4j Node 的 Model 類。此外 service 包下用于放置服務(wù)類,我們編寫的 MigrationService.java 及其實現(xiàn)即是做 MySQL 到 Neo4j 數(shù)據(jù)遷移的。

該示例工程用到的依賴如下:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-neo4j</artifactId>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>

    <!-- driver -->
    <dependency>
        <groupId>com.mysql</groupId>
        <artifactId>mysql-connector-j</artifactId>
        <version>9.2.0</version>
    </dependency>

    <!-- test -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

可以看到,該工程主要有兩項依賴 spring-boot-starter-data-jpaspring-boot-starter-data-neo4j,前者用于訪問 MySQL,后者用于訪問 Neo4j。此外,使用 lombok 方便 Getters 和 Setters 的編寫,mysql-connector-j 為訪問 MySQL 的驅(qū)動,spring-boot-starter-test 為單元測試依賴。

2.2 工程配置

該工程的配置文件 application.yaml 的內(nèi)容如下

spring:
  datasource:
    jdbc-url: jdbc:mysql://localhost:3306/test?autoReconnect=true&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
    username: root
    password: root
  jpa:
    show-sql: true
  neo4j:
    uri: bolt://localhost:7687/neo4j
    authentication:
      username: neo4j
      password: neo4j

logging:
  level:
    org.neo4j.ogm: DEBUG
    org.springframework.data.neo4j: DEBUG

可以看到,我們配置了兩個數(shù)據(jù)源:spring.datasource 配置的是 MySQL 的連接信息,spring.neo4j 配置的是 Neo4j 的連接信息。此外,我們還開啟了 SQL 和 Neo4j Cypher 語句的打印。

介紹完工程結(jié)構(gòu)、依賴和配置后,下面介紹關(guān)鍵的代碼塊。

2.3 Config 類

要支持在 Spring Boot 中同時操作 MySQL 和 Neo4j,配置類是關(guān)鍵。

下面是 MySQLConfig.java 的代碼:

package com.example.demo.config;
// ...

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        basePackages = "com.example.demo.repository.relational",
        entityManagerFactoryRef = "mysqlEntityManagerFactory",
        transactionManagerRef = "mysqlTransactionManager"
)
public class MySQLConfig {

    @Bean(name = "mysqlDataSource")
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource mysqlDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "mysqlEntityManagerFactory")
    public LocalContainerEntityManagerFactoryBean mysqlEntityManagerFactory(
            EntityManagerFactoryBuilder builder,
            @Qualifier("mysqlDataSource") DataSource dataSource) {
        return builder.dataSource(dataSource)
                .packages("com.example.demo.model.relational")
                .persistenceUnit("mysql")
                .build();
    }

    @Bean(name = "mysqlTransactionManager")
    public PlatformTransactionManager mysqlTransactionManager(
            @Qualifier("mysqlEntityManagerFactory") EntityManagerFactory factory) {
        return new JpaTransactionManager(factory);
    }
}

可以看到,我們在該類中指定了 MySQL Repository 的位置、數(shù)據(jù)庫連接信息在配置文件中的位置,并配置了 MySQL 的實體管理器和事務(wù)管理器。

下面是 Neo4jConfig.java 的代碼:

package com.example.demo.config;
// ...

@Configuration
@EnableTransactionManagement
@EnableNeo4jRepositories(
        basePackages = "com.example.demo.repository.graph",
        transactionManagerRef = "neo4jTransactionManager"
)
public class Neo4jConfig {

    @Bean(name = "neo4jTransactionManager")
    public PlatformTransactionManager transactionManager(Driver driver) {
        return Neo4jTransactionManager.with(driver)
                .build();
    }
}

可以看到,我們在該配置類中指定了 Neo4j Repository 的位置并配置了 Neo4j 的事務(wù)管理器。

2.4 Model 類

Model 類用于對應(yīng) MySQL 數(shù)據(jù)庫的表或?qū)?yīng) Neo4j 數(shù)據(jù)庫的 Node。

下面是 Actor.java 的代碼,其對應(yīng) MySQL 的 actor 表。

package com.example.demo.model.relational;
// ...

@Data
@Entity(name = "actor")
public class Actor {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long actorId;
    private String name;
    private String nationality;
    private Integer yearOfBirth;
}

下面是 GraphActor.java 的代碼,其對應(yīng) Neo4j 的 Actor Node。

package com.example.demo.model.graph;
// ...

@Data
@Node("Actor")
public class GraphActor {

    @Id
    @GeneratedValue
    private Long id;

    private Long actorId;
    private String name;
    private String nationality;
    private Integer yearOfBirth;
}

relationalgraph 包下其它的 Model 類與此兩者類似,為了控制篇幅,其代碼就不在這里一一列出了。

2.5 Repository 接口

Repository 用于真正與數(shù)據(jù)庫交互。

下面是 ActorRepository.java 的代碼,其用于對 MySQL 的 actor 表進行增刪改查。

package com.example.demo.repository.relational;
// ...

public interface ActorRepository extends JpaRepository<Actor, Long> {
}

下面是 GraphActorRepository.java 的代碼,其用于對 Neo4j 的 Actor Node 進行增刪改查。

package com.example.demo.repository.graph;
// ...

public interface GraphActorRepository extends Neo4jRepository<GraphActor, Long> {

    @Transactional("neo4jTransactionManager")
    @Query("""
            UNWIND $actors AS actor
            MERGE (a:Actor {actorId: actor.actorId})
            ON CREATE SET a = actor
            ON MATCH SET a += actor
            """)
    void batchInsertOrUpdate(List<Map<String, Object>> actors);
}

可以看到,與普通 JPA Repository 類似,Neo4j 的 Repository 上同樣支持編寫自定義查詢。之所以編寫該方法,是因為使用該自定義 Cypher 方式編寫的 Actor 批量插入或更新方法比原生方式效率更高。

relationalgraph 包下其它的 Repository 與此兩者類似,這里也不一一列出了。

2.6 Service 類

MigrationService 實現(xiàn)類的代碼如下,其對前面的 Model 和 Repository 進行了使用,實現(xiàn)了 MySQL 到 Neo4j 的數(shù)據(jù)遷移。

package com.example.demo.service.impl;
// ...

@Service
public class MigrationServiceImpl implements MigrationService {

    @Autowired
    private ActorRepository actorRepository;
    @Autowired
    private MovieRepository movieRepository;
    @Autowired
    private ActorMovieRepository actorMovieRepository;
    @Autowired
    private GraphActorRepository graphActorRepository;
    @Autowired
    private GraphMovieRepository graphMovieRepository;

    @Override
    public void migrateActorsAndMovies() {
        // migrate all actors
        migrateAllActors();

        // migrate all movies
        migrateAllMovies();

        // delete all ACTED_IN relations
        graphMovieRepository.deleteAllActedInRelations();

        // rebuild ACTED_IN relations
        List<Map<String, Object>> actedInRelations = getAllActedInRelations();
        graphMovieRepository.batchInsertOrUpdateActedInRelations(actedInRelations);
    }

    private void migrateAllActors() {
        List<Actor> actors = actorRepository.findAll();

        List<Map<String, Object>> graphActors = actors.stream()
                .map(this::assembleActor)
                .toList();

        graphActorRepository.batchInsertOrUpdate(graphActors);
    }

    private void migrateAllMovies() {
        List<Movie> movies = movieRepository.findAll();

        List<Map<String, Object>> graphMovies = movies.stream()
                .map(this::assembleMovie)
                .toList();

        graphMovieRepository.batchInsertOrUpdate(graphMovies);
    }

    private List<Map<String, Object>> getAllActedInRelations() {
        List<ActorMovie> actorMovies = actorMovieRepository.findAll();

        return actorMovies.stream()
                .map(this::assembleActedIn)
                .toList();
    }

    private Map<String, Object> assembleActor(Actor actor) {
        GraphActor graphActor = new GraphActor();
        BeanUtils.copyProperties(actor, graphActor);
        graphActor.setId(null);

        return ObjectToMapUtil.toMap(graphActor);
    }

    private Map<String, Object> assembleMovie(Movie movie) {
        GraphMovie graphMovie = new GraphMovie();
        BeanUtils.copyProperties(movie, graphMovie);
        graphMovie.setId(null);

        return ObjectToMapUtil.toMap(graphMovie);
    }

    private Map<String, Object> assembleActedIn(ActorMovie actorMovie) {
        return Map.of(
                "actorId", actorMovie.getId().getActorId(),
                "movieId", actorMovie.getId().getMovieId(),
                "role", actorMovie.getRole()
        );
    }
}

可以看到,該實現(xiàn)類對 MySQL 進行讀取,對 Neo4j 進行寫入,實現(xiàn)了兩個數(shù)據(jù)庫的模式轉(zhuǎn)換和數(shù)據(jù)遷移。

需要注意的是,我們使用了一個 Java 對象到 Map 類型轉(zhuǎn)換的工具類 ObjectToMapUtil.java,這是因為 Neo4j 的 Repository 目前還不能很好的支持直接傳入一個 List<Actor> 對象。

最后,在單元測試類中調(diào)用該實現(xiàn)類后,即可出現(xiàn)文章開頭展示的效果。

3 小結(jié)

綜上,我們以實現(xiàn) MySQL 到 Neo4j 數(shù)據(jù)遷移為目的演示了如何使用 Spring Data 同時訪問 MySQL 和 Neo4j 數(shù)據(jù)庫。

參考資料

[1] Spring: Spring Data JPA - https://docs.spring.io/spring-data/jpa/reference/jpa.html

[2] Spring: Spring Data Neo4j Reference Documentation - https://docs.spring.io/spring-data/neo4j/reference/

到此這篇關(guān)于使用SpringData同時訪問MySQL和Neo4j數(shù)據(jù)庫的文章就介紹到這了,更多相關(guān)SpringData同時訪問MySQL和Neo4j內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家! 

相關(guān)文章

  • springboot整合dubbo設(shè)置全局唯一ID進行日志追蹤的示例代碼

    springboot整合dubbo設(shè)置全局唯一ID進行日志追蹤的示例代碼

    這篇文章主要介紹了springboot整合dubbo設(shè)置全局唯一ID進行日志追蹤,本文通過圖文示例相結(jié)合給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-10-10
  • Java 判斷兩個字符串是否由相同的字符組成的實例

    Java 判斷兩個字符串是否由相同的字符組成的實例

    今天小編就為大家分享一篇Java 判斷兩個字符串是否由相同的字符組成的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-07-07
  • 一篇文章教你用Java使用JVM工具檢測問題

    一篇文章教你用Java使用JVM工具檢測問題

    這篇文章主要介紹了深入理解Java使用JVM工具檢測問題,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-09-09
  • Java手動實現(xiàn)Redis的LRU緩存機制

    Java手動實現(xiàn)Redis的LRU緩存機制

    在Java中LRU的實現(xiàn)方式是使用HashMap結(jié)合雙向鏈表,HashMap的值是雙向鏈表的節(jié)點,雙向鏈表的節(jié)點也保存一份key value。
    2021-05-05
  • Java ConcurrentModificationException異常解決案例詳解

    Java ConcurrentModificationException異常解決案例詳解

    這篇文章主要介紹了Java ConcurrentModificationException異常解決案例詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下
    2021-09-09
  • SpringBoot實現(xiàn)自定義事件的方法詳解

    SpringBoot實現(xiàn)自定義事件的方法詳解

    這篇文章將用實例來和大家介紹一下如何在SpringBoot中自定義事件來使用觀察者模式。文中的示例代碼講解詳細,對我們學(xué)習(xí)SpringBoot有一定的幫助,需要的可以參考一下
    2022-06-06
  • 關(guān)于報錯IDEA Terminated with exit code 1的解決方法

    關(guān)于報錯IDEA Terminated with exit code 

    如果在IDEA構(gòu)建項目時遇到下面這樣的報錯IDEA Terminated with exit code 1,那必然是Maven的設(shè)置參數(shù)重置了,導(dǎo)致下載錯誤引起的,本文給大家分享兩種解決方法,需要的朋友可以參考下
    2022-08-08
  • 部署springboot項目到云服務(wù)器的兩種方式(jar+war)

    部署springboot項目到云服務(wù)器的兩種方式(jar+war)

    本文主要介紹了部署springboot項目到云服務(wù)器的兩種方式,主要介紹了jar和war兩種方式,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-12-12
  • 史上最簡單的MyBatis動態(tài)SQL入門示例代碼

    史上最簡單的MyBatis動態(tài)SQL入門示例代碼

    動態(tài)sql,可以根據(jù)用戶對字段選擇和輸入,動態(tài)生成一條sql執(zhí)行。接下來通過本文給大家分享MyBatis動態(tài)SQL入門示例代碼,一起看看吧
    2017-03-03
  • Java中字符串的一些常見方法分享

    Java中字符串的一些常見方法分享

    這篇文章主要介紹了Java中字符串的一些常見方法,需要的朋友可以參考下
    2014-02-02

最新評論

民县| 简阳市| 晋江市| 澜沧| 台北县| 瓦房店市| 江源县| 天全县| 嘉义县| 加查县| 岱山县| 宁海县| 胶州市| 苏州市| 濮阳市| 广州市| 民县| 南通市| 梨树县| 灵璧县| 潢川县| 枝江市| 清流县| 长海县| 稷山县| 紫金县| 仪征市| 沙雅县| 新乡市| 包头市| 红河县| 茂名市| 库尔勒市| 江安县| 谷城县| 当雄县| 板桥市| 崇明县| 宁乡县| 泽普县| 武强县|