adonisJS/transaction(+エラーの4つの解決策)を使用
プロジェクトで取引を行うロジックを補完する必要があるので、仕事のついでに整理しておきました.
私が定義したトランザクション
1回のリクエストでデータベースの複数のテーブルにデータを入れる必要がある場合は、
すべてのデータ入力に成功または失敗した操作.
例えば私は友達に1万元送金します.
1.私の口座からお金が流出しました.
2.友人の口座にお金を預ける.
この過程は両方とも成功するか、両方とも失敗するかのどちらかだ.
私のお金だけが友達の口座に入っていなければ、お金は消えてしまいます.
->もしあなたが私のお金だけを持って行って、あなたの友達の口座にお金がないなら、
transactionのrollbackで私の口座からお金が流出しないようにします.
注意:トランザクションとは?
adonisの基本例.
すべてのソースをチェックした後、最後のチェックを行うためにテストを行いました.
そしてエラーに遭遇しました.
理由1:非同期を正しく掛けていないため
常に上のデータを発見してから起動します.
これはmapの特性のためです.
mdn:mapメソッドは、各配列の要素が所与の関数を呼び出す新しい配列を返します.
mapの内部はpromiseオブジェクトで、同期処理するならpromise.allでいいです
順番通りに同期処理するためです.
△動機、非同期、約束の概念をさらに学ぶ必要があると思います.
理由2:commitの後にもう一つのトランザクションがあります.
これは、データベースにどのデータを格納する論理であり、一時的に格納する必要があります.
位置を変えると、エラーは発生しません.
理由3:構文エラー
待機と負荷は同じテーブルです.
この機会に取引についてよく知っています.
ちなみにcommitやrollbackが抜けているとDBが拡張する可能性があります.
トランザクションを適用すると、すべての論理が完了した後にコミットされます.
エラーが発生した場合は、rollbackが必須かどうかを確認してください.
トランザクションを適用した後、数日後にデータ異常の通知を受けました.
実際のデータと統計表に記録されているデータの数が異なることが確認された.
新しく修正された取引のためであることが確認された.
transactionに新しいデータを格納->これらのデータを計算することによって統計データを格納します.
新しいデータは一時的に格納され、統計データは実際のデータのみを計算します.
->一時データを計算できるようにtrxキーを与えた.
🎢 トランザクションの概念
私が定義したトランザクション
1回のリクエストでデータベースの複数のテーブルにデータを入れる必要がある場合は、
すべてのデータ入力に成功または失敗した操作.
例えば私は友達に1万元送金します.
1.私の口座からお金が流出しました.
2.友人の口座にお金を預ける.
この過程は両方とも成功するか、両方とも失敗するかのどちらかだ.
私のお金だけが友達の口座に入っていなければ、お金は消えてしまいます.
->もしあなたが私のお金だけを持って行って、あなたの友達の口座にお金がないなら、
transactionのrollbackで私の口座からお金が流出しないようにします.
注意:トランザクションとは?
🎢 トランザクションをadonisJSに適用
adonisの基本例.
import Database from '@ioc:Adonis/Lucid/Database'
import User from 'App/Models/User'
await Database.transaction(async (trx) => {
const user = new User()
user.username = 'virk' // 1. user 테이블에 데이터를 넣는다
user.useTransaction(trx) // 2. transaction 부분 완료 (임시 저장개념)
await user.save()
/**
* The relationship will implicitly reference the
* transaction from the user instance
*/
await user.related('profile').create({ // 3. user 와 연결된 profile 테이블에 데이터를 넣는다.
fullName: 'Harminder Virk',
avatar: 'some-url.jpg',
})
})
補足コードconst trx = await Database.transaction() // transaction 시작
try {
user.name = request.input('name') // 데이터를 넣는다.
user.tel = request.input('tel')
user.address = request.input('address')
user.useTransaction(trx) // user 테이블 부분완료 (임시저장)
await (await user.save()).refresh()
post.title = request.input('title') // 데이터를 넣는다.
post.body = request.input('body')
post.isHidden = request.input('isHidden')
post.useTransaction(trx) // post 테이블 부분완료 (임시저장)
await (await post.save()).refresh()
await trx.commit() // 완료 (여기까지 왔으면 문제없다는 것이다. 실제로 저장진행)
return response.ok(user)
} catch (error) {
await trx.rollback() // 실패가 발생하면 이쪽으로 빠지는데, 철회 상태가 된다. (DB를 확인해보면 수행한 작업들이 아무것도 들어와 있지 않다.)
throw new TransactionExceptionHandler()
}
注意:docs.adonisjs.com(本書)🎢 エラーTransaction queryが完了しました。
すべてのソースをチェックした後、最後のチェックを行うためにテストを行いました.
そしてエラーに遭遇しました.
Transaction query already complete, run with DEBUG=knex:tx for more info
同じエラーメッセージが3回も受信され、解決されたのはもう一つの原因です.理由1:非同期を正しく掛けていないため
// 수정 전
posts.map(async (post: Post) => {
post.isHidden = request.input('isHidden)
post.useTransaction(trx)
await (await post.save()).refresh()
})
// 수정 후
await Promise.all(
posts.map(async (post: Post) => {
post.isHidden = request.input('isHidden)
post.useTransaction(trx)
await (await post.save()).refresh()
})
)
これらのデータは、まず一時的に格納され、次に別のデータロジックが格納されます.常に上のデータを発見してから起動します.
これはmapの特性のためです.
mdn:mapメソッドは、各配列の要素が所与の関数を呼び出す新しい配列を返します.
mapの内部はpromiseオブジェクトで、同期処理するならpromise.allでいいです
順番通りに同期処理するためです.
△動機、非同期、約束の概念をさらに学ぶ必要があると思います.
理由2:commitの後にもう一つのトランザクションがあります.
const trx = await Database.transaction()
try {
// 1번 데이터 저장 로직
// 2번 데이터 저장 로직
// ...
await trx.commit()
// 아래 코드를 await trx.commit()위로 올렸다.
await DataHistory.changeDataHistory(user.id, ...)
return response.created(channel)
} catch (error) {
await trx.rollback()
throw new TransactionExceptionHandler()
}
ChangeDataHistoryの論理これは、データベースにどのデータを格納する論理であり、一時的に格納する必要があります.
位置を変えると、エラーは発生しません.
理由3:構文エラー
const trx = await Database.transaction()
try {
// 1번 데이터 저장 로직
// 2번 데이터 저장 로직
// ...
user.load('post') // -> await user.load('post')
await trx.commit()
return user
} catch (error) {
console.log('error', error)
await trx.rollback()
return {
error: error,
}
}
loadはuserに接続されたpostデータを取得する論理であり,非同期処理が必要である.待機と負荷は同じテーブルです.
ポスト
この機会に取引についてよく知っています.
ちなみにcommitやrollbackが抜けているとDBが拡張する可能性があります.
トランザクションを適用すると、すべての論理が完了した後にコミットされます.
エラーが発生した場合は、rollbackが必須かどうかを確認してください.
🎢 統計データに反映されていないデータエラー
トランザクションを適用した後、数日後にデータ異常の通知を受けました.
実際のデータと統計表に記録されているデータの数が異なることが確認された.
新しく修正された取引のためであることが確認された.
transactionに新しいデータを格納->これらのデータを計算することによって統計データを格納します.
新しいデータは一時的に格納され、統計データは実際のデータのみを計算します.
->一時データを計算できるようにtrxキーを与えた.
public static async userPostCount (user: User, trx:TransactionClientContract | null) {
let query = Post.query().count('* as total')
if (trx) {
query.useTransaction(trx) // 이렇게 임시저장된 데이터도 쿼리에 걸어준다.
}
query.where('user_id', user.id)
const total = await query.first()
return total
}
Reference
この問題について(adonisJS/transaction(+エラーの4つの解決策)を使用), 我々は、より多くの情報をここで見つけました https://velog.io/@flobeeee/adonisJS-transaction-사용하기-에러상황-3가지-해결テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol