2017-07-16 11 views
1

、私はいくつかのアドバイスを必要とする管理挿入、更新スケジュールされたタスクは、私がスケジュールされたタスクで動作するように使用されていないよ

私は20分ごとに実行される機能を設計しています(は私の思考は良いか悪いがあります)。この関数はjsonファイル(私は制御できない)からデータを取り出し、そのデータをデータベースに挿入します。

これを実行していたときに、毎回更新されるのと同じデータであるというユニークなID問題がデータベースビューに作成されるとは思われませんでした。

私は2つの機能を行うことを考え

1:最初の挿入(INSERT)

2:(UPDATE)IDに基づいてデータを更新し

@Component 
public class LoadSportsCompetition { 

    @PostConstruct 
    public void insert() { 
    // 1 : get json data 
    // 2 : insert in DB 
    } 

    @Scheduled(cron="0 0/20 * * * ?") 
    public void update() { 
    // 1 : get json data 
    // 2 : update rows by ID  
    } 

} 
+0

あなたの実際*質問*は何ですか? – joanolo

+0

私はそれが良いやり方であれば放浪しています –

+0

どのバージョンのPostgreSQLを使用していますか?より新しい(9.5+)バージョンを使用している場合は、おそらく 'INSERT ... ON CONFLICT DO UPDATE ...; 'を使い、すべてを1ステップで実行したいと思うでしょう。 ['INSERT'](https://www.postgresql.org/docs/current/static/sql-insert.html) – joanolo

答えて

1

(おそらく)PostgreSQL 9.5以降でこれを処理する最良の方法は、INSERT ... ON CONFLICT ... DO UPDATEです。

のはこれがあなたの元のテーブルであると仮定しましょう(非常に単純には、この例のために):

CREATE TABLE tbl 
(
    tbl_id INTEGER, 
    payload JSONB, 

    CONSTRAINT tbl_pk 
     PRIMARY KEY (tbl_id) 
) ; 

我々は始まるデータとそれを埋める:

INSERT INTO tbl 
    (tbl_id, payload) 
VALUES 
    (1, '{"a":12}'), 
    (2, '{"a":13, "b": 25}'), 
    (3, '{"a":15, "b": [12,13,14]}'), 
    (4, '{"a":12, "c": "something"}'), 
    (5, '{"a":13, "x": 1234.567}'), 
    (6, '{"a":12, "x": 1234.789}') ; 

今、私たちは非を行います(つまり、ON CONFLICT ... DOは実行されません)。

これで、

ON CONFLICT句によって処理され、今すぐ更新

-- A conflicting insert 
INSERT INTO tbl 
    (tbl_id, payload) 
VALUES 
    (3, '{"a": 16, "b": "I don''t know"}') 
ON CONFLICT ON CONSTRAINT tbl_pk DO 
UPDATE 
    SET payload = excluded.payload ; 

そして、一列に競合、およびその他を挿入する2つの行挿入を実行するPRIMARY KEYコンフリクトを生成するNE INSERT

-- Now one of each 
-- A conflicting insert 
INSERT INTO tbl 
    (tbl_id, payload) 
VALUES 
    (4, '{"a": 18, "b": "I will we updated"}'), 
    (9, '{"a": 17, "b": "I am nuber 9"}') 
ON CONFLICT ON CONSTRAINT tbl_pk DO UPDATE 
    SET payload = excluded.payload ; 

現在の表をご確認ください:

SELECT * FROM tbl ORDER BY tbl_id ; 
 
tbl_id | payload        
-----: | :---------------------------------- 
    1 | {"a": 12}       
    2 | {"a": 13, "b": 25}     
    3 | {"a": 16, "b": "I don't know"}  
    4 | {"a": 18, "b": "I will we updated"} 
    5 | {"a": 13, "x": 1234.567}   
    6 | {"a": 12, "x": 1234.789}   
    7 | {"x": 1234.56, "y": 3456.78}  
    9 | {"a": 17, "b": "I am nuber 9"}  

コードは受信データをループして取得し、INSERT/UPDATE(時にはMERGEまたはUPSERTと呼ばれます)を一度に1行ずつ、またはバッチで複数行VALUESで実行する必要があります。

あなたはhere


dbfiddle ですべてのコードを取得することができますが、バッチで作業する場合より適している一つの代替もあります。あなたはhere dbfiddle で見ることができるようにあなたは、同じ結果が得られます

-- Avoiding (most) concurrency issues. 

BEGIN TRANSACTION ; 
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE ; 

WITH data_to_load (tbl_id, payload) AS 
(
    VALUES 
     (3, '{"a": 16, "b": "I don''t know"}' :: jsonb), 
     (4, '{"a": 18, "b": "I will we updated"}'), 
     (7, '{"x": 1234.56, "y": 3456.78}'), 
     (9, '{"a": 17, "b": "I am nuber 9"}') 
), 
update_existing AS 
(
    UPDATE 
     tbl 
    SET 
     payload = data_to_load.payload 
    FROM 
     data_to_load 
    WHERE 
     tbl.tbl_id = data_to_load.tbl_id 
) 
-- Insert the non-existing 
INSERT INTO 
    tbl 
    (tbl_id, payload) 
SELECT 
    tbl_id, payload 
FROM 
    data_to_load 
WHERE 
    data_to_load.tbl_id NOT IN (SELECT tbl_id FROM tbl) ; 

COMMIT TRANSACTION ; 

INSERT 1に続いて1つのUPDATE句を、持っているWITHステートメントを使用します。どちらの場合も


は、エラー処理のための準備ができて、そしてによる同時アクションに彼ら競合がまたあなたのデータベースを変更する場合は、あなたの取引を再試行して調製すること。は、(第2の場合のように)明示的に指定する、または暗黙のすることができますあなたの取引、あなたは自動コミットのいくつかの種類を持っている場合は、すべて単一INSERT

+1

非常に良い説明、私は1回だけ挿入し、後で更新することによって簡単なトリックを行いました。私はおそらく後であなたのソリューションを統合します –

関連する問題