2016-10-20 5 views
2

neo4jデータベースに問題があります。データを初期化しようとすると、1つのサンプルデータを作成するだけで、データを初期化しようとすると、2つのサンプルデータが作成されることがあります。二度目の呼び出しについての痕跡はありません。これはNeo4j 3.0.6およびneo4j-ogm 2.0.5 - データベースに重複データを作成

@Configuration 
@EnableNeo4jRepositories(basePackages = "com.example.neo.repository") 
@EnableTransactionManagement 
public class Neo4jConfig extends Neo4jConfiguration { 
    @Override 
    @Bean 
    public SessionFactory getSessionFactory() { 
     // with domain entity base package(s) 
     return new SessionFactory("com.example.neo.model", "BOOT-INF.classes.com.example.neo.model"); 
    } 

    // needed for session in view in web-applications 
    @Override 
    @Bean 
    @Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS) 
    public Session getSession() throws Exception { 
     return super.getSession(); 
    } 
} 

これは私が私の関数と呼ば方法です私のNeo4jのコンフィグである。これは持っているinitializationService機能

private String[][] currencyList = { 
     { "USD", "7.5" }, 
     { "DKK", "1" }, 
     { "AFN", "1"},{ "EUR", "1"},{ "ALL", "1"},{ "DZD", "1"},{ "USD", "1"},{ "AOA", "1"},{ "XCD", "1"}, 
     { "ARS", "1"},{ "AMD", "1"},{ "AWG", "1"},{ "SHP", "1"},{ "AUD", "1"},{ "AZN", "1"},{ "BSD", "1"}, 
     { "BHD", "1"},{ "BDT", "1"},{ "BBD", "1"} 
} 
@Override 
public void initCurrency() { 
    for (String[] currency : currencyList) { 
     Currency existCurrency = currencyService.findByName(currency[0]); 

     if (existCurrency == null) { 
      existCurrency = new Currency(currency[0], Double.valueOf(currency[1])); 
      currencyService.save(existCurrency); 
     } 
    } 
} 
+1

おそらく、通貨コードに一意性制約を追加する必要があります。重複を防止し、何がうまくいかないかを明らかにするためです。 –

+0

@JasperBlues findByNameを使用して、一意のIDを既に追加して重複を防止しています。 CUrrencyが存在する場合は、保存コードをスキップする必要があります。しかし、私がneo4jデータベースをチェックすると、二重のデータにdiffernt unique IDがあります。 –

+1

Jasperが意味することは、 'CREATE CONSTRAINT ON(n:Currency)ASSERT n.name IS UNIQUE'(通貨の' name'プロパティに 'USD'が入っていると仮定して通貨の名前を一意にする必要があるということです。 'ラベル)。アプリケーションは、同じ通貨名を持つ2つのノードを作成することができず、2つ目のノードは失敗し、ログに例外があります。 –

答えて

2

重複を避けるための唯一の信頼できる方法です

@RequestMapping(value = "/initCurrency") 
public ModelAndView initCurrency() { 
    initializationService.initCurrency(); 

    ModelAndView model = new ModelAndView("redirect:/"); 
    return model; 
} 

プロパティの実際のunicity constraint

CREATE CONSTRAINT ON (n:Currency) ASSERT n.name IS UNIQUE; 

SDN 4には方法がありません(まだ)モデルからそのような制約を作成するには(SDN 3.xに@Indexedまたは@Indexed(unique = true)という注釈が付いています)、 (例えば、Liquigraph!を使用して)クエリを実行します。読み取りと書き込みの間にはロックがありませんので、作成を守るために検索を行う

は、インターリーブ実行に次のシナリオをもたらし得る、(シーケンシャル呼び出しはOKです)同時環境では十分ではありません。

  • スレッドAが存在することを確認し、ノードを見つけることができません
  • スレッドBが存在することを確認し、ノードを見つけるのいずれか
  • スレッドAは、「USB」
  • スレッドBという名前の通貨ノードを作成していませんsで別の通貨ノードを作成するameの名前
二重になるので、2つの同時呼び出し が起きているので、です。実際にタイムアウトが短く、再試行するように構成されたロードバランサ? HTTPログを有効にしたり、Springコントローラやサービスにいくつかのログを追加したり、 tcpdumpなどでトラフィックを捕捉したりします。一意性制約がアクティブになったら、2番目の呼び出しを分離する方が簡単です。
+0

うん。その理由は、2つのスレッドが同時に実行されるため、その理由は重複データを作成するためです。それはあなたの説明のようです。とにかくこの情報をありがとう、本当に役に立ちました。 –

+1

OGM '2.1.0-SNAPSHOT'では' @ Index'と '@Index(unique = true)'がサポートされていることに言及する価値があります:https://github.com/neo4j/neo4j-ogm/pull/243 – digx1

関連する問題