Kami memiliki sistem di mana koneksi basis data dapat digunakan sekali menggunakan metode umum, dan dilewatkan di seluruh kelas yang relevan untuk digunakan. Ada keraguan bahwa melewatkan koneksi database sebagai parameter ke kelas yang berbeda akan menyebabkan masalah, jadi saya memeriksa di sini untuk melihat apakah ini benar-benar layak, dan apakah ada pola yang lebih baik untuk melakukannya?
Saya tahu ada beberapa alat ORM untuk melakukan kegigihan tetapi kita belum bisa membahasnya, belum ..
Setiap umpan balik disambut, terima kasih.
java
database
patterns-and-practices
ipohfly
sumber
sumber
Jawaban:
Ya itu aman untuk melewati koneksi. Anda menangani koneksi di blok kontrol luar. Tidak ada yang tidak aman tentang itu.
Apa yang tidak aman adalah menulis kode yang tidak menjamin koneksi dibuang dengan benar tepat waktu. Lupa membersihkan sumber daya tidak ada hubungannya dengan menyebarkannya. Anda bisa dengan mudah menulis kode yang meninggalkan koneksi yang menggantung tanpa melewati di mana saja.
Di C ++, Anda dilindungi oleh RAII jika Anda mengalokasikan pada stack atau menggunakan smart pointer. Dalam C # buat aturan keras bahwa semua objek pakai (seperti koneksi) dideklarasikan di blok "using". Di Jawa bersih dengan logika try-akhirnya. Memiliki ulasan kode pada semua kode lapisan data untuk memastikan hal ini.
Kasus penggunaan yang paling umum adalah ketika Anda memiliki beberapa operasi yang dapat digabungkan dalam banyak permutasi. Dan masing-masing permutasi ini harus berupa transaksi atom (semua berhasil atau kembalikan). maka Anda harus melewati transaksi (dan karena itu koneksi yang sesuai) berkeliling ke semua metode.
Misalkan kita memiliki banyak tindakan foobar () yang dapat digabungkan dalam berbagai cara sebagai transaksi atom.
BTW Anda akan ingin membuka koneksi selambat mungkin, buang mereka sesegera mungkin. Rekan satu tim Anda mungkin benar jika Anda memperlakukan koneksi sebagai anggota objek, memperkenalkan mereka sebagai keadaan yang tidak perlu, dan membiarkan koneksi terbuka lebih lama dari yang diperlukan. Tetapi tindakan melewati koneksi atau transaksi sebagai parameter tidak salah secara inheren.
BTW. Bergantung pada dukungan bahasa Anda untuk fungsi kelas satu Anda dapat mengambil dalam daftar tindakan foobar (). Jadi satu fungsi bisa menangani semua permutasi dari tindakan. Menghilangkan duplikasi blok kontrol luar untuk setiap permutasi.
sumber
Sepertinya Anda mencari Dependency Injection . Artinya, koneksi gabungan akan dibuat sekali dan disuntikkan di mana pun dibutuhkan. Tentu saja meneruskan koneksi melalui parameter metode adalah salah satu cara untuk menyuntikkan ketergantungan, tetapi wadah IoC seperti Guice, PicoContainer atau Spring adalah cara lain (lebih aman) yang dapat Anda lakukan.
Menggunakan DI berarti Anda dapat dengan rapi membungkus logika seputar penciptaan, pembukaan, penggunaan, dan penutupan koneksi - jauh dari logika bisnis inti Anda.
Spring JDBC et al adalah contoh lain dari melakukan perilaku semacam ini untuk Anda
sumber
Melewatkan hal-hal basis data daripada data hal-hal yang dapat menyebabkan masalah. Sejauh itu, kapan pun praktis, jangan lulus dari basis data kecuali seseorang dapat menjamin kebersihan basis data yang benar.
Masalah dengan melewati hal-hal basis data adalah bahwa hal itu dapat menjadi ceroboh. Saya telah melihat lebih dari satu bug dalam kode dengan seseorang yang melewati koneksi basis data, bahwa seseorang kemudian mengambil hasil yang diatur ke dan menyimpan di objek lokal (hasil set, masih terhubung ke database) dan kemudian mengikat kursor di database untuk waktu yang signifikan. Contoh lain seseorang melewati set hasil ke orang lain (yang kemudian disimpan) dan kemudian metode yang melewati set hasil menutupnya (dan pernyataan) mengarah ke kesalahan ketika metode lain mencoba untuk bekerja dengan set hasil yang tidak lagi.
Semua ini bermula dari tidak menghormati database, koneksi, pernyataan, set hasil, dan siklus hidup mereka.
Untuk menghindari hal ini, ada pola dan struktur yang ada yang bermain lebih baik dengan database dan tidak memiliki hal-hal database yang harus keluar dari kelas yang mereka kuasai. Data masuk, data keluar, basis data tetap ada.
sumber
Root
dari seorang Dao. Tetapi kemudian Anda menyadari bahwa Anda juga menginginkan cara untuk mendapatkanNode
tanpa menarik seluruhRoot
objek dengannya. Bagaimana Anda membuatRoot
Dao memanggilNode
kode Dao (yaitu: menggunakan kembali), tetapi pastikanNode
Dao hanya menutup koneksi ketikaNode
Dao secara langsung dipanggil dan membuat koneksi tetap terbuka ketikaRoot
Dao dipanggil?Melewati
Connection
contoh di sekitar biasanya tidak menjadi masalah, meskipun dalam kebanyakan situasi hanya implementasi DAO yang ada hubungannya dengan mereka. Sekarang, dengan masalah Anda tentang koneksi yang tidak ditutup setelah digunakan, sebenarnya mudah diperbaiki:Connection
objek harus ditutup pada level yang sama seperti dibuka, yaitu dengan metode yang sama. Saya pribadi menggunakan pola kode berikut:Dengan begitu saya memastikan semua koneksi selalu ditutup, bahkan jika ada pengecualian yang dilemparkan ke dalam blok. Saya benar-benar pergi selama menggunakan pola
Statement
danResultSet
contoh yang sama persis , dan semuanya berjalan lancar sejauh ini.Sunting 2018-03-29: Seperti yang ditunjukkan oleh user1156544 dalam komentar di bawah ini, dimulai dengan Java 7 penggunaan konstruk try-with-resources harus disukai. Dengan menggunakannya, pola kode yang saya berikan dalam jawaban awal saya dapat disederhanakan seperti:
sumber
dataSource
daripadaDataSource
(saya akan memperbaiki jawaban saya mengenai hal itu). Jenis yang tepat dari objek itu adalahjavax.sql.DataSource
. Dalam kode lama saya dulu memiliki seorang lajang yang mengelola semua sumber data yang tersedia dalam aplikasi saya. DAO saya tidak perlu tahu tentang itu, karenaDataSource
instance disediakan melalui injeksi ketergantungan.ada tradeoff untuk melakukan hal-hal seperti ini daripada menggunakan singleton yang bisa Anda dapatkan sesuai kebutuhan. Saya telah melakukan berbagai hal di masa lalu.
Secara umum, Anda perlu memikirkan konsekuensi dari manajemen koneksi database, dan ini mungkin atau mungkin tidak ortogonal untuk penggunaan query database. Sebagai contoh, jika Anda memiliki satu koneksi db untuk instance aplikasi yang diberikan dan akan ditutup saat tidak digunakan, itu akan menjadi ortogonal. Letakkan manajemen di kelas tunggal dan jangan menyebarkannya. Ini memungkinkan Anda untuk mengelola koneksi db sesuai kebutuhan. Misalnya, jika Anda ingin menutup koneksi pada setiap commit (dan membuka kembali pada panggilan berikutnya) ini lebih mudah dilakukan pada singleton karena API untuk ini dapat terpusat.
Di sisi lain, anggaplah Anda perlu mengelola kumpulan koneksi di mana panggilan yang diberikan mungkin perlu menggunakan koneksi yang sewenang-wenang. Ini mungkin terjadi ketika melakukan transaksi terdistribusi di beberapa server, misalnya. Dalam hal ini Anda biasanya jauh lebih baik melewati objek koneksi db daripada Anda bekerja dengan lajang. Saya pikir ini biasanya merupakan kasus yang lebih jarang, tetapi tidak ada yang salah dengan melakukannya ketika Anda perlu.
sumber