Tags:

Cách lưu dữ liệu dạng file vào MySQL sử dụng JDBC

Trong cơ sở dữ liệu MySQL dữ liệu dạng file được lưu dưới dạng BLOB (Binary Large Object). Vì vậy nếu chúng ta phải sử dụng kiểu dữ liệu BLOB cho các cột được dùng để lưu trữ file. 

Giả sử có table Person trong đó có cột photo dùng để lưu ảnh của một người cụ thể.

CREATE TABLE `person` (
  `person_id` int(11) NOT NULL AUTO_INCREMENT,
  `first_name` varchar(45) DEFAULT NULL,
  `last_name` varchar(45) DEFAULT NULL,
  `photo` mediumblob,
  PRIMARY KEY (`person_id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1

Ở trên mình sử dụng mediumblob cho cột photo, cũng là một dạng BLOB nhưng có kích thước tối đa là 16MB. Ngoài ra còn có các kiều BLOB khác với các kích thước tối đa khác nhau.

  • TINYBLOB: 255 bytes
  • BLOB: 65,535 bytes (64 KB)
  • MEDIUMBLOB: 16,777,215 bytes (16 MB)
  • LONGBLOB: 4 GB

Vậy có nghĩa là cột photo của chúng ta chỉ có thể lưu trữ một file ảnh có kích thước tối đa là 16MB.

Thêm dữ liệu dạng file trong JDBC

Để thêm dữ liệu dạng file trong JDBC chúng ta có thể sử dụng hàm setBlob() để truyền một tập tin dưới dạng InputStream.

void setBlob(int parameterIndex, InputStream inputStream)

Giờ đây chúng ta có thể sử dụng JDBC để kết nối đến database và thực thi lệnh INSERT dữ liệu thông qua connection object.

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class Main {

    public static void main(String[] args) {
        String url = "jdbc:mysql://localhost:3306/contactdb";
        String user = "root";
        String password = "secret";

        String filePath = "D:/Photos/Tom.png";

        try (Connection conn = DriverManager.getConnection(url, user, password)) {

            String sql = "INSERT INTO person (first_name, last_name, photo) values (?, ?, ?)";
            PreparedStatement statement = conn.prepareStatement(sql);
            statement.setString(1, "Tom");
            statement.setString(2, "Eagar");
            InputStream inputStream = new FileInputStream(new File(filePath));

            statement.setBlob(3, inputStream);

            int row = statement.executeUpdate();
            if (row > 0) {
                System.out.println("A contact was inserted with photo image.");
            }
        } catch (IOException | SQLException e) {
            e.printStackTrace();
        }
    }
}

Thêm dữ liệu dạng file trong Mysql

Ngoài việc sử dụng setBlob() method của JDBCthì chúng ta có thể sử dụng cú pháp của MySQL cung cấp

 

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class Main {

    public static void main(String[] args) {
        String url = "jdbc:mysql://localhost:3306/contactdb";
        String user = "root";
        String password = "secret";

        String filePath = "D:/Photos/Tom.png";

        try (Connection conn = DriverManager.getConnection(url, user, password)) {

            String sql = "INSERT INTO person (photo) values (LOAD_FILE(?))";
            PreparedStatement statement = conn.prepareStatement(sql);

            statement.setString(1, filePath);

            int row = statement.executeUpdate();
            if (row > 0) {
                System.out.println("A contact was inserted with photo image.");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

Cách này thường ít được sử dụng vì nó yêu cầu file được thêm vào phải nằm trên cùng máy đang chạy database.

Giới hạn packet size trong MySQL 

Mặc định thì MySQL sẽ đặt một giới hạn dung lượng dữ liệu có thể gửi đến database trong một câu truy vấn. Giá trị mặc định này thường là 1MB được đặt thông qua thuộc tính max_allowed_packet. Nếu chúng ta lưu dữ liệu có kích thước hơn 1MB thì MySQL sẽ ném ra lỗi

com.mysql.jdbc.PacketTooBigException: Packet for query is too large (4384068 > 1048576).
You can change this value on the server by setting the max_allowed_packet' variable.

Bởi vì giới hạn 1 MB là khá nhỏ để lưu các file dưới dạng BLOB, vì vậy chúng ta cần phải chỉnh sửa giá trị này. Có hai cách phổ biến để cấu hình như sau:

  • Từ tệp cấu hình my.ini của MySQL: chúng ta vào chỉnh sửa my.ini và thêm dòng sau vào cuối: max_allowed_packet = 104857600 (10MB). Sau đó restart mysql.
  • Thông qua câu lệnh SQL hãy nhớ restart lại mysql:

    SET GLOBAL max_allowed_packet=104857600;

Ví dụ chương trình sau sẽ thực thi câu lệnh SET GLOBAL max_allowed_packet với JDBC và sau đó mới thực thi lệnh insert ảnh vào database mysql.

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;

public class Main {

    public static void main(String[] args) {
        String url = "jdbc:mysql://localhost:3306/contactdb";
        String user = "root";
        String password = "secret";

        String filePath = "D:/Photos/Tom.png";

        try (Connection conn = DriverManager.getConnection(url, user, password)) {

            String querySetLimit = "SET GLOBAL max_allowed_packet=104857600;";  // 10 MB
            Statement stSetLimit = conn.createStatement();
            stSetLimit.execute(querySetLimit);

            String sql = "INSERT INTO person (first_name, last_name, photo) values (?, ?, ?)";
            PreparedStatement statement = conn.prepareStatement(sql);
            statement.setString(1, "Tom");
            statement.setString(2, "Eagar");
            InputStream inputStream = new FileInputStream(new File(filePath));

            statement.setBlob(3, inputStream);

            int row = statement.executeUpdate();
            if (row > 0) {
                System.out.println("A contact was inserted with photo image.");
            }
        } catch (SQLException ex) {
            ex.printStackTrace();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
}

Nguồn

https://www.codejava.net/java-se/jdbc/insert-file-data-into-mysql-database-using-jdbc

5 1 vote
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x