JavaRush /Blog Java /Random-MS /JDBC atau di mana semuanya bermula

JDBC atau di mana semuanya bermula

Diterbitkan dalam kumpulan
Dalam dunia moden, tiada cara tanpa penyimpanan data. Dan sejarah bekerja dengan pangkalan data bermula sangat lama dahulu, dengan kemunculan JDBC. Saya bercadang untuk mengingati sesuatu yang tidak boleh dilakukan oleh rangka kerja moden yang dibina di atas JDBC. Di samping itu, walaupun semasa bekerja dengan mereka, kadangkala anda mungkin memerlukan peluang untuk "kembali ke akar umbi anda." Saya harap ulasan ini akan membantu sebagai pengenalan atau membantu menyegarkan ingatan anda.
JDBC atau tempat semuanya bermula - 1

pengenalan

Salah satu tujuan utama bahasa pengaturcaraan ialah menyimpan dan memproses maklumat. Untuk lebih memahami cara storan data berfungsi, anda perlu meluangkan sedikit masa pada teori dan seni bina aplikasi. Sebagai contoh, anda boleh membaca literatur, iaitu buku " Buku Panduan Arkitek Perisian: Menjadi arkitek perisian yang berjaya dengan melaksanakan gerbang yang berkesan... " oleh Joseph Ingeno. Seperti yang dikatakan, terdapat Tahap Data atau "Lapisan Data" tertentu. Ia termasuk tempat untuk menyimpan data (contohnya, pangkalan data SQL) dan alatan untuk bekerja dengan stor data (contohnya, JDBC, yang akan dibincangkan). Terdapat juga artikel di tapak web Microsoft: “ Mereka bentuk lapisan kegigihan infrastruktur ,” yang menerangkan penyelesaian seni bina untuk memisahkan lapisan tambahan daripada Tahap Data - Lapisan Kegigihan. Dalam kes ini, Tahap Data ialah tahap penyimpanan data itu sendiri, manakala Lapisan Kegigihan ialah beberapa tahap pengabstrakan untuk bekerja dengan data daripada storan daripada tahap Tahap Data. Lapisan Kegigihan boleh memasukkan templat "DAO" atau pelbagai ORM. Tetapi ORM adalah topik untuk perbincangan lain. Seperti yang anda mungkin sudah faham, Tahap Data muncul dahulu. Sejak zaman JDK 1.1, JDBC (Java DataBase Connectivity - sambungan ke pangkalan data di Java) telah muncul di dunia Java. Ini ialah standard untuk interaksi aplikasi Java dengan pelbagai DBMS, dilaksanakan dalam bentuk pakej java.sql dan javax.sql yang disertakan dalam Java SE:
JDBC atau di mana semuanya bermula - 2
Piawaian ini diterangkan oleh spesifikasi " JSR 221 JDBC 4.1 API ". Spesifikasi ini memberitahu kami bahawa API JDBC menyediakan akses program kepada pangkalan data hubungan daripada program yang ditulis dalam Java. Ia juga memberitahu bahawa API JDBC adalah sebahagian daripada platform Java dan oleh itu disertakan dalam Java SE dan Java EE. API JDBC disediakan dalam dua pakej: java.sql dan javax.sql. Mari kenali mereka kemudian.
JDBC atau tempat semuanya bermula - 3

Permulaan kerja

Untuk memahami apa itu JDBC API secara umum, kami memerlukan aplikasi Java. Ia adalah paling mudah untuk menggunakan salah satu sistem pemasangan projek. Sebagai contoh, mari kita gunakan Gradle . Anda boleh membaca lebih lanjut tentang Gradle dalam ulasan ringkas: " Pengenalan Ringkas kepada Gradle ". Mula-mula, mari kita mulakan projek Gradle baharu. Memandangkan fungsi Gradle dilaksanakan melalui pemalam, kita perlu menggunakan “ Gradle Build Init Plugin ” untuk pemula:
gradle init --type java-application
Selepas ini, mari buka skrip binaan - fail build.gradle , yang menerangkan projek kami dan cara mengendalikannya. Kami berminat dengan blok " kebergantungan ", di mana kebergantungan diterangkan - iaitu, perpustakaan/rangka kerja/api tersebut, tanpanya kita tidak boleh bekerja dan bergantung padanya. Secara lalai kita akan melihat sesuatu seperti:
dependencies {
    // This dependency is found on compile classpath of this component and consumers.
    implementation 'com.google.guava:guava:26.0-jre'
    // Use JUnit test framework
    testImplementation 'junit:junit:4.12'
}
Mengapa kita melihat ini di sini? Ini adalah kebergantungan projek kami yang dijana secara automatik oleh Gradle untuk kami semasa membuat projek. Dan juga kerana jambu batu adalah perpustakaan berasingan yang tidak disertakan dengan Java SE. JUnit juga tidak disertakan dengan Java SE. Tetapi kami mempunyai JDBC di luar kotak, iaitu, ia adalah sebahagian daripada Java SE. Ternyata kita mempunyai JDBC. Hebat. Apa lagi yang kita perlukan? Terdapat gambar rajah yang begitu indah:
JDBC atau di mana semuanya bermula - 4
Seperti yang kita dapat lihat, dan ini adalah logik, pangkalan data adalah komponen luaran yang bukan asli kepada Java SE. Ini dijelaskan secara ringkas - terdapat sejumlah besar pangkalan data dan anda boleh bekerja dengan mana-mana pangkalan data. Sebagai contoh, terdapat PostgreSQL, Oracle, MySQL, H2. Setiap pangkalan data ini dibekalkan oleh syarikat berasingan yang dipanggil vendor pangkalan data. Setiap pangkalan data ditulis dalam bahasa pengaturcaraan sendiri (tidak semestinya Java). Untuk dapat bekerja dengan pangkalan data daripada aplikasi Java, pembekal pangkalan data menulis pemacu khas, iaitu penyesuai imejnya sendiri. Yang serasi dengan JDBC tersebut (iaitu, yang mempunyai pemacu JDBC) juga dipanggil "Pangkalan Data Mematuhi JDBC". Di sini kita boleh melukis analogi dengan peranti komputer. Sebagai contoh, dalam pad nota terdapat butang "Cetak". Setiap kali anda menekannya, program memberitahu sistem pengendalian bahawa aplikasi pad nota ingin dicetak. Dan anda mempunyai pencetak. Untuk mengajar sistem pengendalian anda berkomunikasi secara seragam dengan pencetak Canon atau HP, anda memerlukan pemacu yang berbeza. Tetapi bagi anda, sebagai pengguna, tiada apa yang akan berubah. Anda masih akan menekan butang yang sama. Begitu juga dengan JDBC. Anda menjalankan kod yang sama, cuma pangkalan data yang berbeza mungkin berjalan di bawah hud. Saya fikir ini adalah pendekatan yang sangat jelas. Setiap pemacu JDBC sedemikian adalah sejenis artifak, perpustakaan, fail balang. Ini adalah pergantungan untuk projek kami. Sebagai contoh, kita boleh memilih pangkalan data " Pangkalan Data H2 " dan kemudian kita perlu menambah kebergantungan seperti ini:
dependencies {
    implementation 'com.h2database:h2:1.4.197'
Cara mencari pergantungan dan cara menerangkannya ditunjukkan pada tapak web rasmi pembekal pangkalan data atau pada " Maven Central ". Pemacu JDBC bukan pangkalan data, seperti yang anda faham. Tetapi dia hanya penunjuk arah. Tetapi ada perkara seperti " Dalam pangkalan data memori ". Ini adalah pangkalan data yang wujud dalam ingatan sepanjang hayat aplikasi anda. Biasanya, ini sering digunakan untuk tujuan ujian atau latihan. Ini membolehkan anda mengelak daripada memasang pelayan pangkalan data yang berasingan pada mesin. Yang sangat sesuai untuk kita berkenalan dengan JDBC. Jadi kotak pasir kami sudah sedia dan kami mulakan.
JDBC atau tempat semuanya bermula - 5

Sambungan

Jadi, kami mempunyai pemandu JDBC, kami mempunyai API JDBC. Seperti yang kita ingat, JDBC adalah singkatan dari Java DataBase Connectivity. Oleh itu, semuanya bermula dengan Connectivity - keupayaan untuk mewujudkan sambungan. Dan sambungan adalah Sambungan. Mari kita kembali ke teks spesifikasi JDBC dan lihat jadual kandungan. Dalam bab " BAB 4 Gambaran Keseluruhan " (gambaran keseluruhan) kita beralih kepada bahagian " 4.1 Mewujudkan Sambungan " (mewujudkan sambungan) dikatakan terdapat dua cara untuk menyambung ke pangkalan data:
  • Melalui DriverManager
  • Melalui DataSource
Mari kita berurusan dengan DriverManager. Seperti yang dikatakan, DriverManager membenarkan anda menyambung ke pangkalan data pada URL yang ditentukan, dan juga memuatkan Pemacu JDBC yang ditemui dalam CLASSPATH (dan sebelum ini, sebelum JDBC 4.0, anda perlu memuatkan sendiri kelas pemandu). Terdapat bab berasingan "BAB 9 Sambungan" tentang menyambung ke pangkalan data. Kami berminat untuk mendapatkan sambungan melalui DriverManager, jadi kami berminat dengan bahagian "9.3 The DriverManager Class". Ia menunjukkan bagaimana kita boleh mengakses pangkalan data:
Connection con = DriverManager.getConnection(url, user, passwd);
Parameter boleh diambil dari laman web pangkalan data yang telah kami pilih. Dalam kes kami, ini ialah H2 - " H2 Cheat Sheet ". Mari kita beralih ke kelas AppTest yang disediakan oleh Gradle. Ia mengandungi ujian JUnit. Ujian JUnit ialah kaedah yang ditandakan dengan anotasi @Test. Ujian unit bukan topik ulasan ini, jadi kami hanya akan menghadkan diri kami kepada pemahaman bahawa ini adalah kaedah yang diterangkan dengan cara tertentu, yang tujuannya adalah untuk menguji sesuatu. Menurut spesifikasi JDBC dan laman web H2, kami akan menyemak sama ada kami telah menerima sambungan ke pangkalan data. Mari tulis kaedah untuk mendapatkan sambungan:
private Connection getNewConnection() throws SQLException {
	String url = "jdbc:h2:mem:test";
	String user = "sa";
	String passwd = "sa";
	return DriverManager.getConnection(url, user, passwd);
}
Sekarang mari kita tulis ujian untuk kaedah ini yang akan memeriksa sama ada sambungan sebenarnya telah diwujudkan:
@Test
public void shouldGetJdbcConnection() throws SQLException {
	try(Connection connection = getNewConnection()) {
		assertTrue(connection.isValid(1));
		assertFalse(connection.isClosed());
	}
}
Ujian ini, apabila dilaksanakan, akan mengesahkan bahawa sambungan yang terhasil adalah sah (dicipta dengan betul) dan ia tidak ditutup. Dengan menggunakan cuba-dengan-sumber, kami akan mengeluarkan sumber apabila kami tidak memerlukannya lagi. Ini akan melindungi kita daripada sambungan kendur dan kebocoran memori. Memandangkan sebarang tindakan dengan pangkalan data memerlukan sambungan, mari sediakan baki kaedah ujian bertanda @Test dengan Sambungan pada permulaan ujian, yang akan kami keluarkan selepas ujian. Untuk melakukan ini, kita memerlukan dua anotasi: @Before dan @After Mari tambah medan baharu pada kelas AppTest yang akan menyimpan sambungan JDBC untuk ujian:
private static Connection connection;
Dan mari tambah kaedah baharu:
@Before
public void init() throws SQLException {
	connection = getNewConnection();
}
@After
public void close() throws SQLException {
	connection.close();
}
Kini, sebarang kaedah ujian dijamin mempunyai sambungan JDBC dan tidak perlu menciptanya sendiri setiap kali.
JDBC atau di mana semuanya bermula - 6

Kenyataan

Seterusnya kami berminat dengan Pernyataan atau ungkapan. Mereka diterangkan dalam dokumentasi dalam bab " BAB 13 Penyata ". Pertama, ia mengatakan bahawa terdapat beberapa jenis atau jenis pernyataan:
  • Pernyataan: Ungkapan SQL yang tidak mengandungi parameter
  • PreparedStatement : Penyata SQL yang disediakan mengandungi parameter input
  • CallableStatement: Ungkapan SQL dengan keupayaan untuk mendapatkan nilai pulangan daripada SQL Stored Procedures.
Jadi, dengan mempunyai sambungan, kami boleh melaksanakan beberapa permintaan dalam rangka sambungan ini. Oleh itu, adalah logik bahawa kita pada mulanya mendapatkan contoh ungkapan SQL daripada Connection. Anda perlu bermula dengan membuat jadual. Mari kita terangkan permintaan penciptaan jadual sebagai pembolehubah String. Bagaimana hendak melakukannya? Mari gunakan beberapa tutorial seperti " sqltutorial.org ", " sqlbolt.com ", " postgresqltutorial.com ", " codecademy.com ". Mari kita gunakan, sebagai contoh, contoh daripada kursus SQL di khanacademy.org . Mari tambah kaedah untuk melaksanakan ungkapan dalam pangkalan data:
private int executeUpdate(String query) throws SQLException {
	Statement statement = connection.createStatement();
	// Для Insert, Update, Delete
	int result = statement.executeUpdate(query);
	return result;
}
Mari tambah kaedah untuk membuat jadual ujian menggunakan kaedah sebelumnya:
private void createCustomerTable() throws SQLException {
	String customerTableQuery = "CREATE TABLE customers " +
                "(id INTEGER PRIMARY KEY, name TEXT, age INTEGER)";
	String customerEntryQuery = "INSERT INTO customers " +
                "VALUES (73, 'Brian', 33)";
	executeUpdate(customerTableQuery);
	executeUpdate(customerEntryQuery);
}
Sekarang mari kita uji ini:
@Test
public void shouldCreateCustomerTable() throws SQLException {
	createCustomerTable();
	connection.createStatement().execute("SELECT * FROM customers");
}
Sekarang mari kita laksanakan permintaan itu, dan juga dengan parameter:
@Test
public void shouldSelectData() throws SQLException {
 	createCustomerTable();
 	String query = "SELECT * FROM customers WHERE name = ?";
	PreparedStatement statement = connection.prepareStatement(query);
	statement.setString(1, "Brian");
	boolean hasResult = statement.execute();
	assertTrue(hasResult);
}
JDBC tidak menyokong parameter yang dinamakan untuk PreparedStatement, jadi parameter itu sendiri ditentukan oleh soalan, dan dengan menyatakan nilai kami menunjukkan indeks soalan (bermula dari 1, bukan sifar). Dalam ujian terakhir kami menerima benar sebagai petunjuk sama ada terdapat keputusan. Tetapi bagaimanakah hasil pertanyaan diwakili dalam API JDBC? Dan ia dibentangkan sebagai ResultSet.
JDBC atau di mana semuanya bermula - 7

ResultSet

Konsep ResultSet diterangkan dalam spesifikasi API JDBC dalam bab "BAB 15 Set Keputusan". Pertama sekali, ia mengatakan bahawa ResultSet menyediakan kaedah untuk mendapatkan semula dan memanipulasi hasil pertanyaan yang dilaksanakan. Iaitu, jika kaedah pelaksanaan dikembalikan kepada kami, maka kami boleh mendapatkan ResultSet. Mari alihkan panggilan ke kaedah createCustomerTable() ke dalam kaedah init, yang ditandakan sebagai @Before. Sekarang mari kita akhiri ujian shouldSelectData kami:
@Test
public void shouldSelectData() throws SQLException {
	String query = "SELECT * FROM customers WHERE name = ?";
	PreparedStatement statement = connection.prepareStatement(query);
	statement.setString(1, "Brian");
	boolean hasResult = statement.execute();
	assertTrue(hasResult);
	// Обработаем результат
	ResultSet resultSet = statement.getResultSet();
	resultSet.next();
	int age = resultSet.getInt("age");
	assertEquals(33, age);
}
Perlu diperhatikan di sini bahawa seterusnya adalah kaedah yang menggerakkan apa yang dipanggil "kursor". Kursor dalam ResultSet menghala ke beberapa baris. Oleh itu, untuk membaca baris, anda perlu meletakkan kursor ini di atasnya. Apabila kursor dialihkan, kaedah pergerakan kursor kembali benar jika kursor adalah sah (betul, betul), iaitu, ia menunjuk kepada data. Jika ia kembali palsu, maka tiada data, iaitu kursor tidak menunjuk ke data. Jika kami cuba mendapatkan data dengan kursor yang tidak sah, kami akan mendapat ralat: Tiada data tersedia. Menarik juga bahawa melalui ResultSet anda boleh mengemas kini atau memasukkan baris:
@Test
public void shouldInsertInResultSet() throws SQLException {
	Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
	ResultSet resultSet = statement.executeQuery("SELECT * FROM customers");
	resultSet.moveToInsertRow();
	resultSet.updateLong("id", 3L);
	resultSet.updateString("name", "John");
	resultSet.updateInt("age", 18);
	resultSet.insertRow();
	resultSet.moveToCurrentRow();
}

RowSet

Sebagai tambahan kepada ResultSet, JDBC memperkenalkan konsep RowSet. Anda boleh membaca lebih lanjut di sini: " Asas JDBC: Menggunakan Objek RowSet ". Terdapat pelbagai variasi penggunaan. Sebagai contoh, kes paling mudah mungkin kelihatan seperti ini:
@Test
public void shouldUseRowSet() throws SQLException {
 	JdbcRowSet jdbcRs = new JdbcRowSetImpl(connection);
 	jdbcRs.setCommand("SELECT * FROM customers");
	jdbcRs.execute();
	jdbcRs.next();
	String name = jdbcRs.getString("name");
	assertEquals("Brian", name);
}
Seperti yang anda lihat, RowSet adalah serupa dengan simbiosis pernyataan (kami menetapkan arahan melaluinya) dan perintah yang dilaksanakan. Melaluinya kami mengawal kursor (dengan memanggil kaedah seterusnya) dan mendapatkan data daripadanya. Bukan sahaja pendekatan ini menarik, tetapi juga pelaksanaan yang mungkin. Contohnya, CachedRowSet. Ia "terputus sambungan" (iaitu, ia tidak menggunakan sambungan berterusan ke pangkalan data) dan memerlukan penyegerakan eksplisit dengan pangkalan data:
CachedRowSet jdbcRsCached = new CachedRowSetImpl();
jdbcRsCached.acceptChanges(connection);
Anda boleh membaca lebih lanjut dalam tutorial di laman web Oracle: " Menggunakan CachedRowSetObjects ".
JDBC atau tempat semuanya bermula - 8

Metadata

Selain pertanyaan, sambungan ke pangkalan data (iaitu, contoh kelas Sambungan) menyediakan akses kepada metadata - data tentang cara pangkalan data kami dikonfigurasikan dan disusun. Tetapi pertama-tama, mari kita sebutkan beberapa perkara penting: URL untuk menyambung ke pangkalan data kami: "jdbc:h2:mem:test". test ialah nama pangkalan data kami. Untuk API JDBC, ini ialah direktori. Dan nama itu akan menggunakan huruf besar, iaitu, UJIAN. Skema lalai untuk H2 ialah PUBLIC. Sekarang, mari kita tulis ujian yang menunjukkan semua jadual pengguna. Mengapa adat? Kerana pangkalan data mengandungi bukan sahaja jadual pengguna (yang kami cipta sendiri menggunakan ekspresi jadual), tetapi juga jadual sistem. Mereka adalah perlu untuk menyimpan maklumat sistem tentang struktur pangkalan data. Setiap pangkalan data boleh menyimpan jadual sistem sedemikian secara berbeza. Contohnya, dalam H2 ia disimpan dalam skema " INFORMATION_SCHEMA ". Menariknya, SKEMA MAKLUMAT ialah pendekatan biasa, tetapi Oracle menggunakan laluan yang berbeza. Anda boleh membaca lebih lanjut di sini: " INFORMATION_SCHEMA dan Oracle ". Mari tulis ujian yang menerima metadata pada jadual pengguna:
@Test
public void shoudGetMetadata() throws SQLException {
	// У нас URL = "jdbc:h2:mem:test", где test - название БД
	// Название БД = catalog
	DatabaseMetaData metaData = connection.getMetaData();
	ResultSet result = metaData.getTables("TEST", "PUBLIC", "%", null);
	List<String> tables = new ArrayList<>();
	while(result.next()) {
		tables.add(result.getString(2) + "." + result.getString(3));
	}
	assertTrue(tables.contains("PUBLIC.CUSTOMERS"));
}
JDBC or с чего всё начинается - 9

Kolam sambungan

Kumpulan sambungan dalam spesifikasi JDBC mempunyai bahagian yang dipanggil "Pengumpulan Sambungan Bab 11". Ia juga menyediakan justifikasi utama untuk keperluan untuk kumpulan sambungan. Setiap Coonection ialah sambungan fizikal kepada pangkalan data. Penciptaan dan penutupannya adalah kerja yang agak "mahal". JDBC hanya menyediakan API penggabungan sambungan. Oleh itu, pilihan pelaksanaan tetap milik kita. Sebagai contoh, pelaksanaan sedemikian termasuk HikariCP . Sehubungan itu, kami perlu menambah kumpulan kepada pergantungan projek kami:
dependencies {
    implementation 'com.h2database:h2:1.4.197'
    implementation 'com.zaxxer:HikariCP:3.3.1'
    testImplementation 'junit:junit:4.12'
}
Sekarang kita perlu menggunakan kolam ini. Untuk melakukan ini, anda perlu memulakan sumber data, juga dikenali sebagai Sumber Data:
private DataSource getDatasource() {
	HikariConfig config = new HikariConfig();
	config.setUsername("sa");
	config.setPassword("sa");
	config.setJdbcUrl("jdbc:h2:mem:test");
	DataSource ds = new HikariDataSource(config);
	return ds;
}
Dan mari tulis ujian untuk menerima sambungan daripada kolam:
@Test
public void shouldGetConnectionFromDataSource() throws SQLException {
	DataSource datasource = getDatasource();
	try (Connection con = datasource.getConnection()) {
		assertTrue(con.isValid(1));
	}
}
JDBC or с чего всё начинается - 10

Transaksi

Salah satu perkara yang paling menarik tentang JDBC ialah transaksi. Dalam spesifikasi JDBC, mereka diberikan bab "BAB 10 Transaksi". Pertama sekali, adalah wajar memahami apa itu transaksi. Transaksi ialah sekumpulan operasi berurutan yang digabungkan secara logik pada data, diproses atau dibatalkan secara keseluruhan. Bilakah transaksi bermula apabila menggunakan JDBC? Seperti yang dinyatakan dalam spesifikasi, ini dikendalikan secara langsung oleh Pemacu JDBC. Tetapi biasanya, urus niaga baharu bermula apabila penyata SQL semasa memerlukan urus niaga dan transaksi itu belum lagi dibuat. Bilakah urus niaga tamat? Ini dikawal oleh atribut autokomit. Jika autokomit didayakan, transaksi akan selesai selepas pernyataan SQL "selesai". Maksud "selesai" bergantung pada jenis ungkapan SQL:
  • Bahasa Manipulasi Data, juga dikenali sebagai DML (Sisipkan, Kemas Kini, Padam)
    Urus niaga selesai sebaik sahaja tindakan selesai
  • Pilih Penyata
    Transaksi selesai apabila ResultSet ditutup ( ResultSet#close )
  • CallableStatement dan ungkapan yang mengembalikan berbilang hasil
    Apabila semua ResultSets yang berkaitan telah ditutup dan semua output telah diterima (termasuk bilangan kemas kini)
Beginilah kelakuan API JDBC. Seperti biasa, mari tulis ujian untuk ini:
@Test
public void shouldCommitTransaction() throws SQLException {
	connection.setAutoCommit(false);
	String query = "INSERT INTO customers VALUES (1, 'Max', 20)";
	connection.createStatement().executeUpdate(query);
	connection.commit();
	Statement statement = connection.createStatement();
 	statement.execute("SELECT * FROM customers");
	ResultSet resultSet = statement.getResultSet();
	int count = 0;
	while(resultSet.next()) {
		count++;
	}
	assertEquals(2, count);
}
Mudah sahaja. Tetapi ini adalah benar selagi kita hanya mempunyai satu transaksi. Apa yang perlu dilakukan apabila terdapat beberapa daripadanya? Mereka perlu diasingkan antara satu sama lain. Oleh itu, mari kita bincangkan tentang tahap pengasingan transaksi dan cara JDBC menanganinya.
JDBC or с чего всё начинается - 11

Tahap penebat

Mari buka subseksyen "10.2 Tahap Pengasingan Transaksi" spesifikasi JDBC. Di sini, sebelum melangkah lebih jauh, saya ingin mengingati perkara seperti ACID. ACID menerangkan keperluan untuk sistem transaksi.
  • Atomicity:
    Tiada transaksi akan sebahagiannya komited kepada sistem. Sama ada semua sub-operasinya akan dilakukan, atau tiada satu pun akan dilakukan.
  • Ketekalan:
    Setiap transaksi yang berjaya, mengikut definisi, hanya merekodkan hasil yang sah.
  • Pengasingan:
    Semasa urus niaga sedang berjalan, urus niaga serentak tidak boleh menjejaskan keputusannya.
  • Ketahanan:
    Jika transaksi berjaya diselesaikan, perubahan yang dibuat padanya tidak akan dibuat asal kerana sebarang kegagalan.
Apabila bercakap tentang tahap pengasingan transaksi, kita bercakap tentang keperluan "Pengasingan". Pengasingan adalah keperluan yang mahal, jadi dalam pangkalan data sebenar terdapat mod yang tidak sepenuhnya mengasingkan urus niaga (Tahap pengasingan Baca Berulang dan lebih rendah). Wikipedia mempunyai penjelasan yang sangat baik tentang masalah yang boleh timbul apabila bekerja dengan transaksi. Perlu membaca lebih lanjut di sini: " Masalah akses selari menggunakan transaksi ." Sebelum kami menulis ujian kami, mari kita ubah sedikit Skrip Binaan Gradle kami: tambahkan blok dengan sifat, iaitu, dengan tetapan projek kami:
ext {
    h2Version = '1.3.176' // 1.4.177
    hikariVersion = '3.3.1'
    junitVersion = '4.12'
}
Seterusnya, kami menggunakan ini dalam versi:
dependencies {
    implementation "com.h2database:h2:${h2Version}"
    implementation "com.zaxxer:HikariCP:${hikariVersion}"
    testImplementation "junit:junit:${junitVersion}"
}
Anda mungkin perasan bahawa versi h2 telah menjadi lebih rendah. Kita tengok kenapa nanti. Jadi bagaimana anda menggunakan tahap pengasingan? Mari lihat contoh praktikal kecil dengan segera:
@Test
public void shouldGetReadUncommited() throws SQLException {
	Connection first = getNewConnection();
	assertTrue(first.getMetaData().supportsTransactionIsolationLevel(Connection.TRANSACTION_READ_UNCOMMITTED));
	first.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
	first.setAutoCommit(false);
	// Транзакиця на подключение. Поэтому первая транзакция с ReadUncommited вносит изменения
	String insertQuery = "INSERT INTO customers VALUES (5, 'Max', 15)";
	first.createStatement().executeUpdate(insertQuery);
	// Вторая транзакция пытается их увидеть
	int rowCount = 0;
	JdbcRowSet jdbcRs = new JdbcRowSetImpl(getNewConnection());
	jdbcRs.setCommand("SELECT * FROM customers");
	jdbcRs.execute();
	while (jdbcRs.next()) {
		rowCount++;
	}
	assertEquals(2, rowCount);
}
Menariknya, ujian ini mungkin gagal pada vendor yang tidak menyokong TRANSACTION_READ_UNCOMMITTED (contohnya, sqlite atau HSQL). Dan tahap transaksi mungkin tidak berfungsi. Ingat kami menunjukkan versi pemacu Pangkalan Data H2? Jika kami menaikkannya kepada h2Version = '1.4.177' dan lebih tinggi, maka READ UNCOMMITTED akan berhenti berfungsi, walaupun kami tidak menukar kod. Ini sekali lagi membuktikan bahawa pilihan vendor dan versi pemacu bukan hanya surat, ia sebenarnya akan menentukan bagaimana permintaan anda akan dilaksanakan. Anda boleh membaca tentang cara membetulkan tingkah laku ini dalam versi 1.4.177 dan cara ia tidak berfungsi dalam versi yang lebih tinggi di sini: " Sokongan BACA tahap pengasingan TIDAK KOMITED dalam mod MVStore ".
JDBC or с чего всё начинается - 12

Pokoknya

Seperti yang dapat kita lihat, JDBC ialah alat yang berkuasa di tangan Java untuk bekerja dengan pangkalan data. Saya harap ulasan ringkas ini akan membantu memberi anda titik permulaan atau membantu menyegarkan ingatan anda. Nah, untuk snek, beberapa bahan tambahan: #Viacheslav
Komen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION