2016-09-05 1 views
1

私はどのようにデータベースではないコードの角度から重複する行を積極的に避けるには?

CREATE TABLE `tb_user_portrait` (
    id BIGINT NOT NULL AUTO_INCREMENT COMMENT 'primary key', 
    user_id BIGINT NOT NULL DEFAULT 0 COMMENT 'custormer id', 
    portrait_hash CHAR(255) NOT NULL DEFAULT '' COMMENT 'portrait image hash', 
    is_valid TINYINT NOT NULL DEFAULT 1 COMMENT 'validation flag of this row', 
    primary key(id) 
) 

、テーブルには、顧客の頭の肖像画を保存するtb_user_portrait呼ばれ、そのスキーマが非常に簡単に見え得る顧客は頭を数回肖像画アップロードすることができるので、私は、任意の一意のキーを設定しないでください。ただし、各ユーザーは有効なポートレートを1つしか持たないと仮定されています(つまり、それぞれ1つのis_valid=1レコードしか持てません)。私が最初に有効なレコードを見つけると、無効な設定が

アップロード操作に対処するための私のコードは、あまりにも

def upload(user_id, portrait_hash, is_valid=1): 
    # find the last is_valid=1 records, and set invalid 
    portrait = DBSession().query(UserPortrait).\ 
     filter(UserPortrait.user_id == user_id).\ 
     filter(UserPortrait.is_valid == 1).\ 
     scalar() 
    if portrait: 
     portrait.is_valid = 0 
     DBSession().add(portrait) 
    # create new valid portrait and save it to db 
    new_portrait = UserPortrait(
     user_id=user_id, 
     portrait_hash=portrait_hash, 
     is_valid=is_valid) 
    DBSession().add(new_portrait) 
    DBSession().commit() 

シンプルですが、私はいつもMultipleRowsFoundに遭遇し、複数の記録(is_valid=1がそこにいます)をデータベースに格納します。

ところで、私はSQLAlchemyを使用し、session.autoflushをオンにします。

なぜそれが起こるのだろうか?これを避けるためのベストプラクティスはありますか? SQLAlchemyのから

答えて

0

自動フラッシュ - 真の、すべてのクエリ操作は続行する前に、このセッションにフラッシュ()の呼び出しを発行します。これは、データベース照会が結果を検索するためにflush()を繰り返し呼び出す必要がないように便利な機能です。 autoflushはautocommit = Falseと組み合わせて使用​​するのが一般的です。このシナリオでは、flush()への明示的な呼び出しはめったに必要ありません。通常は、変更を確定するためにcommit()(フラッシュ)を呼び出すだけで済みます。

基本的にデータベースに変更をコミットしないため、それが機能しないため、is_invalid = 1という複数のレコードがあります。

... 
if portrait: 
    portrait.is_valid = 0 
    DBSession().add(portrait) 
    DBSession().flush() # <-- here 

new_portrait = UserPortrait(
    user_id=user_id, 
    portrait_hash=portrait_hash, 
    is_valid=is_valid) 
... 

をそして、それはまだ、代わりに動作しない場合:代わりにsession.autoflushをオンにするの

ので、ここでは、手動でそれをやろう

DBSession().flush() 

だけ使用します。

DBSession().commit() 
関連する問題