Thứ Sáu, 21 tháng 4, 2023

MySql : Ví dụ viết một thủ tục procedure

 Một thủ tục trong MySql có cú pháp như sau :

DELIMITER {custom delimiter}
CREATE PROCEDURE {procedureName}([optional parameters])
BEGIN
// procedure body...
// procedure body...
END
{custom delimiter}

Ví dụ
Ta có bảng customer như sau :


Table "customer"
Column | Type | Modifiers
------------+-------------+-----------
id | integer | not null
address | varchar(64) |
first_name | varchar(32) |
last_name | varchar(32) |
email | varchar(64) |
Indexes:
"customer_pkey" PRIMARY KEY, btree (id)

Ta muốn tạo một bảng temp_customer có cấu trúc giống hệt bảng customer; và bảng này có dữ liệu lấy từ bảng customer :

DROP TABLE IF EXISTS temp_customer;
CREATE TABLE temp_customer
(
id binary(16) not null primary key,
address varchar(64),
first_name varchar(32),
last_name varchar(32),
email varchar(64)
);

 

Ta định nghĩa một thủ tục như sau :

DROP PROCEDURE IF EXISTS ADD_TEMP_CUSTOMER;
DELIMITER $$
CREATE PROCEDURE ADD_TEMP_CUSTOMER()
BEGIN
DECLARE retrieved_address varchar(64);
DECLARE retrieved_first_name varchar(32);
DECLARE retrieved_last_name varchar(32);
DECLARE retrieved_email varchar(64);
DECLARE new_id binary(16);
DECLARE num_row int;
DECLARE finished INTEGER DEFAULT 0;

DECLARE customer_cursor CURSOR FOR
SELECT address, first_name, last_name, email FROM customer;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished = 1;

OPEN customer_cursor;
insert_loop:
LOOP
FETCH customer_cursor INTO retrieved_address, retrieved_first_name, retrieved_last_name, retrieved_email;
IF finished THEN
LEAVE insert_loop;
END IF;

SET @temp_count = (SELECT count(*) FROM temp_customer);
SELECT count(*) into num_row FROM temp_customer;

IF num_row = 0 THEN
SET new_id = UUID_TO_BIN(UUID());
INSERT IGNORE INTO temp_customer(id, address, first_name, last_name, email)
VALUES (new_id, retrieved_address, retrieved_first_name, retrieved_last_name, retrieved_email);
END IF;

END LOOP;
CLOSE customer_cursor;
END $$
DELIMITER ;

CALL ADD_TEMP_CUSTOMER();
DROP PROCEDURE IF EXISTS ADD_TEMP_CUSTOMER;

Giải thích : thủ tục này sẽ dùng một cursor để đọc hết bảng customer và lấy thông tin từ đây điền vào bảng temp_customer


Chú ý để có thể thực thi thủ tục, user phải có quyền thực thi nó, ta có thể gán quyền ấy như sau :

GRANT CREATE ROUTINE, ALTER ROUTINE, EXECUTE ON *.* TO 'toan'@'127.0.0.1';
FLUSH PRIVILEGES;

Hoặc có thể gán mọi quyền như sau :

GRANT ALL PRIVILEGES ON *.* TO 'toan'@'127.0.0.1' WITH GRANT OPTION;
FLUSH PRIVILEGES;

 

Giới thiệu dùng thư viện JGit

 Thư viện JGit của Eclipse cho phép tương tác với một hệ thống Git quản lý mã nguồn. Ta thêm dependency của JGit vào tập tin pom.xml để xài thư viện này như sau :

		<dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit</artifactId>
<version>6.5.0.202303070854-r</version>
</dependency>

Trong ví dụ dưới đây có dùng thư viện commons-io nên ta cũng thêm thư viện này vào tập tin pom.xml như sau :

		<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.11.0</version>
</dependency>

Dưới đây là một ví dụ xài thư viện JGit :


import org.apache.commons.io.FileUtils;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.PushCommand;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.transport.RefSpec;
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;

public class GitBackUpFile {

public static void main(String[] args) {
File createdFile = new File("example.txt");
try {
Files.write(createdFile.toPath(), "File contents".getBytes());
System.out.println("file path : " + createdFile.getAbsolutePath());
backupInGit(createdFile.getAbsolutePath());
} catch (IOException e) {
throw new RuntimeException(e);
}
}

private static void backupInGit(String sourceFileName) {
String branchName = "branch-local";
String gitDirectoryPath = "/path/to/repo" + File.separator + branchName;
File gitLocalDirectory = new File(gitDirectoryPath);
try {
FileUtils.deleteDirectory(gitLocalDirectory);
} catch (IOException e) {
System.out.println("Error deleting git local directory : " + e.getMessage());
}

if (!gitLocalDirectory.exists() && !gitLocalDirectory.mkdirs()) {
throw new RuntimeException("Error creating local git directory : " + gitDirectoryPath);
}

String branch = "refs/heads/" + branchName;
UsernamePasswordCredentialsProvider credentialsProvider = new UsernamePasswordCredentialsProvider("username", "password");
try (Git git = Git.cloneRepository().setURI("https://github.com/example-eclipse/jgit.git")
.setDirectory(gitLocalDirectory)
.setBranchesToClone(Arrays.asList(branch))
.setBranch(branch)
.setCredentialsProvider(credentialsProvider)
.call()) {

String fileName = "fileToPushIntoGit.txt";
String fileAbsolutePath = gitDirectoryPath + File.separator + fileName;
Files.copy(Paths.get(sourceFileName), Paths.get(fileAbsolutePath), StandardCopyOption.REPLACE_EXISTING);

LocalDateTime timeStamp = LocalDateTime.now();
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd-HH");

git.add().addFilepattern(fileName).call();
git.commit().setMessage("Commit file " + fileName + " at " + timeStamp.format(dateTimeFormatter)).call();

PushCommand pushCommand = git.push();
pushCommand.setRemote("origin").setRefSpecs(new RefSpec(branch + ":" + branch));
pushCommand.setForce(true).setPushAll();
pushCommand.setCredentialsProvider(credentialsProvider);
pushCommand.call();

} catch (GitAPIException | IOException e) {
System.out.println("Error when backing up file to git" + e.getMessage());
}
}
}

Trong ví dụ trên ta tạo một tập tin example.txt và push nó vào một branch của depository git

Để có thể push tập tin này vào Git :
- Trước hết ta tạo một thư mục repository ở local để có thể clone repository từ depos Git về đây.
- Nếu đã có một repos git ở thư mục này từ trước rồi thì ta phải xóa nó đi, rồi tạo mới lại thư mục vì không khi clone sẽ báo lỗi.
- Tiếp theo ta clone về nhánh Git mà ta cần lưu tập tin vừa tạo.
- Sao chép tập tin cần lưu vào repos Git ở local này.
- Commit tập tin này vào repos local.
- Sau đó push nó vào repos ở xa.


Thứ Hai, 3 tháng 4, 2023

Zip file Java với mật khẩu dùng zip4j

 Thư viện java.util.zip của Java không cho phép dùng mật khẩu cho file zip, do đó ta có thể dùng thư viện zip4j

		<dependency>
			<groupId>net.lingala.zip4j</groupId>
			<artifactId>zip4j</artifactId>
			<version>2.11.5</version>
		</dependency>

Ví dụ về dùng thư viện này như sau :

import net.lingala.zip4j.io.outputstream.ZipOutputStream;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.model.enums.EncryptionMethod;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

public class ZipFiles {
    public static void main(String[] args) {
        // zip single file
        zipSingleFile("singleFile.zip", "toan".toCharArray(), "file.txt", "test zip single file");
        Map<String, String> filesMap = new HashMap<>();
        filesMap.put("File1.txt", "test 1");
        filesMap.put("File2.txt", "test 2");
        // many files zip
        zipFiles("manyFiles.zip", "toan".toCharArray(), filesMap);
    }

    private static ZipParameters getZipParameters() {
        ZipParameters zipParameters = new ZipParameters();
        zipParameters.setEncryptFiles(true);
        zipParameters.setEncryptionMethod(EncryptionMethod.AES);
        return zipParameters;
    }

    private static void zipFileEntry(ZipOutputStream zos, String fileName, String fileContent)
            throws IOException {
        ZipParameters zipParameters = getZipParameters();
        zipParameters.setFileNameInZip(fileName);
        zos.putNextEntry(zipParameters);

        byte[] data = fileContent.getBytes(StandardCharsets.UTF_8);
        zos.write(data, 0, data.length);
        zos.closeEntry();
    }

    private static void zipSingleFile(String zipFileName, char[] password, String fileName, String fileContent) {
        File file = new File(zipFileName);
        try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(file), password)) {
            zipFileEntry(zos, fileName, fileContent);
            System.out.println("path : " + file.getAbsolutePath());
        } catch (IOException e) {
            System.out.println("error while zipping file " + zipFileName);
        }
    }

    private static void zipFiles(String zipFileName, char[] password, Map<String, String> filesMap) {
        File file = new File(zipFileName);
        try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(file), password)) {
            for (Map.Entry<String, String> entry : filesMap.entrySet()) {
                zipFileEntry(zos, entry.getKey(), entry.getValue());
            }
            System.out.println("path : " + file.getAbsolutePath());
        } catch (IOException e) {
            System.out.println("error while zipping file " + zipFileName);
        }
    }
}