Skip to content

Book Management System 1

Based on Mybatis, JUL, Lombok, and Maven, with unit tests included.

Project Requirements:

  • Online entry of student information and book information
  • Query book information list
  • Query student information list
  • Query borrowing information list
  • Complete logging system

1 Overview

大致框架

Screenshot 2024-04-28 at 11.39.29

Student

Screenshot 2024-04-28 at 11.41.17

Screenshot 2024-04-28 at 11.42.17

Screenshot 2024-04-28 at 11.42.34

book

Screenshot 2024-04-28 at 11.51.42

Screenshot 2024-04-28 at 14.19.00

borrow:

Screenshot 2024-04-28 at 11.48.57

Screenshot 2024-04-28 at 11.50.13

Screenshot 2024-04-28 at 11.50.24

Three tables need auto increment.

添加触发器, 删了学生信息之前, 要把借阅表里的相关信息先删了.

如果显示报错关于外健, 可以先添加触发器, 在添加外健.

pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>BookManagment</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.30</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>5.8.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.33</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.7</version>
        </dependency>
    </dependencies>
</project>

mybatis-config.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <settings>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
        <setting name="cacheEnabled" value="true"/>
        <setting name="logImpl" value="JDK_LOGGING" />
    </settings>
    <!-- 需要在environments的上方 -->
    <typeAliases>
        <package name="org.example.entity"/>
    </typeAliases>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/book_management"/>
                <property name="username" value="root"/>
                <property name="password" value="Eve123456"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper class="book.manage.mapper.BookMapper"/>
    </mappers>
</configuration>

Main.java:

package book.manage;

import book.manage.entity.Book;
import book.manage.entity.Student;
import book.manage.mapper.BookMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.util.Scanner;

// Press Shift twice to open the Search Everywhere dialog and type `show whitespaces`,
// then press Enter. You can now see whitespace characters in your code.
public class Main {
    public static void main(String[] args) throws IOException {
        try(Scanner scanner = new Scanner(System.in)){
            while(true){
                System.out.println("==========================");
                System.out.println("1. Insert a student information");
                System.out.println("2. Insert a book information");
                System.out.println(("Please insert the operation you want(input any other number to exit):"));
                int input;
                try {
                    input = scanner.nextInt();
                    switch (input){
                        case 1:
                            break;
                        case 2:
                            break;
                        default:
                            return;
                    }
                } catch (Exception e){
                    return;
                }

            }
        }

//        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
//        try (SqlSession sqlSession = factory.openSession(true)) {
//            BookMapper mapper =sqlSession.getMapper(BookMapper.class);
//            System.out.println(mapper.addStudent(new Student("Tom","male",1)));
//            System.out.println(mapper.addBook(new Book("Java","Java is a programming language",99.9)));
//        }

    }
}

Book.java:

package book.manage.entity;

import lombok.Data;

@Data
public class Book {
    int bid;
    final String title;
    final String desc;
    final double price;
    // 为什么要用final
    // 因为数据库中的字段是not null, 所以必须要有值

}

Student.java:

package book.manage.entity;

import lombok.Data;

// @Data 注解里面只包含@RequiredArgsConstructor, @Getter, @Setter, @EqualsAndHashCode, @ToString这些注解
// 要求构造的参数必须是final的
@Data
public class Student {
    int sid;
    final String name;
    final String sex;
    final int grade;

}

BookMapper.java:

package book.manage.mapper;

import book.manage.entity.Book;
import book.manage.entity.Student;
import org.apache.ibatis.annotations.Insert;

public interface BookMapper {
    // 不用sid, 因为数据库字段为nut null, sid可以自增
    @Insert("insert into student(name, sex, grade) values (#{name}, #{sex}, #{grade})")
    int addStudent(Student student);

    @Insert("insert into book(title, `desc`, price) values (#{title}, #{desc}, #{price})")
    int addBook(Book student);
    //``是为了避免关键字冲突
}

SqlUtil.java:

package book.manage.sql;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;

public class SqlUtil {
    private SqlUtil() {
    }
    private static SqlSessionFactory factory;

    static {
        try{
            factory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public SqlSession getSqlSession() {
        return factory.openSession(true);
    }
    // 这个SqlUtil类是为了获取SqlSession对象
    // 为什么要用单例模式
    // 因为SqlSessionFactory是一个重量级对象,不需要每次都创建一个新的对象
    // 所以用单例模式
    // 为什么要用static
    // 因为这个类只有一个对象,所以用static
    // 单例模式是什么?
    // 单例模式是一种创建型设计模式,让你能够保证一个类只有一个实例,并提供一个访问该实例的全局节点。
    // 为什么要用单例模式
    // 1. 由于单例模式在内存中只有一个实例,减少了内存的开销,特别是频繁创建和销毁实例。
    // 2. 避免对资源的多重占用(比如写文件操作)。
    // 3. 由于单例模式只生成一个实例,所以减少了系统的性能开销,当一个对象的产生需要比较多的资源时,如读取配置、产生其他依赖对象时,
    // 则可以通过在应用启动时直接产生一个单例对象,然后用永久驻留内存的方式来解决。

}

Screenshot 2024-04-28 at 18.16.35

2 Entry of student information and book information

2.1 Entry Student information

SqlUtil.java:

package book.manage.sql;

import book.manage.mapper.BookMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.util.function.Consumer;

public class SqlUtil {
    private SqlUtil() {
    }
    private static SqlSessionFactory factory;

    static {
        try{
            factory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public SqlSession getSqlSession() {
        return factory.openSession(true);
    }
    // 这个SqlUtil类是为了获取SqlSession对象
    // 为什么要用单例模式
    // 因为SqlSessionFactory是一个重量级对象,不需要每次都创建一个新的对象
    // 所以用单例模式
    // 为什么要用static
    // 因为这个类只有一个对象,所以用static
    // 单例模式是什么?
    // 单例模式是一种创建型设计模式,让你能够保证一个类只有一个实例,并提供一个访问该实例的全局节点。
    // 为什么要用单例模式
    // 1. 由于单例模式在内存中只有一个实例,减少了内存的开销,特别是频繁创建和销毁实例。
    // 2. 避免对资源的多重占用(比如写文件操作)。
    // 3. 由于单例模式只生成一个实例,所以减少了系统的性能开销,当一个对象的产生需要比较多的资源时,如读取配置、产生其他依赖对象时,
    // 则可以通过在应用启动时直接产生一个单例对象,然后用永久驻留内存的方式来解决。

    public static void doSqlWork(Consumer<BookMapper> consumer){
        try(SqlSession session = factory.openSession(true)){
            BookMapper bookMapper = session.getMapper(BookMapper.class);
            consumer.accept(bookMapper);
        }
    }

}

Main.java:

package book.manage;

import book.manage.entity.Book;
import book.manage.entity.Student;
import book.manage.mapper.BookMapper;
import book.manage.sql.SqlUtil;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.util.Scanner;

// Press Shift twice to open the Search Everywhere dialog and type `show whitespaces`,
// then press Enter. You can now see whitespace characters in your code.
public class Main {
    public static void main(String[] args) throws IOException {
        try(Scanner scanner = new Scanner(System.in)){
            while(true){
                System.out.println("==========================");
                System.out.println("1. Insert a student information");
                System.out.println("2. Insert a book information");
                System.out.println(("Please insert the operation you want(input any other number to exit):"));
                int input;
                try {
                    input = scanner.nextInt();
                    switch (input){
                        case 1:
                            addStudent(scanner);
                            break;
                        case 2:
                            break;
                        default:
                            return;
                    }
                } catch (Exception e){
                    return;
                }

            }
        }

    }

    private static void addStudent(Scanner scanner){
        System.out.print("Please input the student's name:");
        String name = scanner.nextLine();
        System.out.print("Please input the student's sex:");
        String sex = scanner.nextLine();
        System.out.print("Please input the student's grade:");
        String grade = scanner.nextLine();
        int g = Integer.parseInt(grade);
        Student student = new Student(name, sex, g);
        SqlUtil.doSqlWork(mapper -> {
                int i = mapper.addStudent(student);
                if ( i > 0) {
                    System.out.println("Insert successfully");
                }else{
                    System.out.println("Insert failed");
                }
            }
        );
    }
}

2.2 Entry Book information

Main.java:

package book.manage;

import book.manage.entity.Book;
import book.manage.entity.Student;
import book.manage.mapper.BookMapper;
import book.manage.sql.SqlUtil;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.util.Scanner;

// Press Shift twice to open the Search Everywhere dialog and type `show whitespaces`,
// then press Enter. You can now see whitespace characters in your code.
public class Main {
    public static void main(String[] args) throws IOException {
        try(Scanner scanner = new Scanner(System.in)){
            while(true){
                System.out.println("==========================");
                System.out.println("1. Insert a student information");
                System.out.println("2. Insert a book information");
                System.out.println(("Please insert the operation you want(input any other number to exit):"));
                int input;
                try {
                    input = scanner.nextInt();
                    switch (input){
                        case 1:
                            addStudent(scanner);
                            break;
                        case 2:
                            addBook(scanner);
                            break;
                        default:
                            return;
                    }
                } catch (Exception e){
                    return;
                }

            }
        }

    }

    private static void addBook(Scanner scanner){
        System.out.print("Please input the book's name:");
        String name = scanner.nextLine();
        System.out.print("Please input the books's desc:");
        String desc = scanner.nextLine();
        System.out.print("Please input the book's price:");
        String price = scanner.nextLine();
        double p = Integer.parseInt(price);
        Book book = new Book(name, desc, p);
        SqlUtil.doSqlWork(mapper -> {
                    int i = mapper.addBook(book);
                    if ( i > 0) {
                        System.out.println("Insert successfully");
                    }else{
                        System.out.println("Insert failed");
                    }
                }
        );
    }

    private static void addStudent(Scanner scanner){
        System.out.print("Please input the student's name:");
        String name = scanner.nextLine();
        System.out.print("Please input the student's sex:");
        String sex = scanner.nextLine();
        System.out.print("Please input the student's grade:");
        String grade = scanner.nextLine();
        int g = Integer.parseInt(grade);
        Student student = new Student(name, sex, g);
        SqlUtil.doSqlWork(mapper -> {
                int i = mapper.addStudent(student);
                if ( i > 0) {
                    System.out.println("Insert successfully");
                }else{
                    System.out.println("Insert failed");
                }
            }
        );
    }
}

BookMapper.java:

package book.manage.mapper;

import book.manage.entity.Book;
import book.manage.entity.Student;
import org.apache.ibatis.annotations.Insert;

public interface BookMapper {
    // 不用sid, 因为数据库字段为nut null, sid可以自增
    @Insert("insert into student(name, sex, grade) values (#{name}, #{sex}, #{grade})")
    int addStudent(Student student);

    @Insert("insert into book(title, `desc`, price) values (#{title}, #{desc}, #{price})")
    int addBook(Book student);
    //``是为了避免关键字冲突
}

Screenshot 2024-04-28 at 21.19.25

Log

mybatis-config.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <settings>
        <setting name="logImpl" value="NO_LOGGING" />
    </settings>
    <!-- 需要在environments的上方 -->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/book_management"/>
                <property name="username" value="root"/>
                <property name="password" value="Eve123456"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper class="book.manage.mapper.BookMapper"/>
    </mappers>
</configuration>

logging.properties:

handlers = java.util.logging.FileHandler
# handlers 是一个列表,可以添加多个handler,这样日志就会同时输出到多个地方
# ConsoleHandler 是输出到控制台
# FileHandler 是输出到文件

.level = ALL
# .level 是日志级别,ALL 是最低级别,表示所有日志都会输出


java.util.logging.FileHandler.pattern = console.log
# java.util.logging.FileHandler.pattern 是日志文件的路径

java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter
# java.util.logging.FileHandler.formatter 是日志格式,java.util.logging.SimpleFormatter 是简单的日志格式

java.util.logging.FileHandler.append = true
# java.util.logging.FileHandler.append 是一个布尔值,表示是否追加到文件,true 表示追加,false 表示覆盖

Main.java:

package book.manage;

import book.manage.entity.Book;
import book.manage.entity.Student;
import book.manage.mapper.BookMapper;
import book.manage.sql.SqlUtil;
import lombok.extern.java.Log;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.util.Scanner;
import java.util.logging.LogManager;

// Press Shift twice to open the Search Everywhere dialog and type `show whitespaces`,
// then press Enter. You can now see whitespace characters in your code.

@Log
public class Main {
    public static void main(String[] args) {
        try(Scanner scanner = new Scanner(System.in)){
            LogManager manager = LogManager.getLogManager();
            manager.readConfiguration(Resources.getResourceAsStream("logging.properties"));

            while(true){
                System.out.println("==========================");
                System.out.println("1. Insert a student information");
                System.out.println("2. Insert a book information");
                System.out.println(("Please insert the operation you want(input any other number to exit):"));
                int input;
                try {
                    input = scanner.nextInt();
                }catch (Exception e) {
                    return;
                }
                scanner.nextLine();
                switch (input){
                    case 1:
                        addStudent(scanner);
                        break;
                    case 2:
                        addBook(scanner);
                        break;
                    default:
                        return;
                }
            }
        }catch (IOException e){
            log.severe(e.getMessage());
        }

    }

    private static void addBook(Scanner scanner){
        System.out.print("Please input the book's name:");
        String name = scanner.nextLine();
        System.out.print("Please input the books's desc:");
        String desc = scanner.nextLine();
        System.out.print("Please input the book's price:");
        String price = scanner.nextLine();
        double p = Integer.parseInt(price);
        Book book = new Book(name, desc, p);
        SqlUtil.doSqlWork(mapper -> {
                    int i = mapper.addBook(book);
                    if ( i > 0) {
                        System.out.println("Insert successfully");
                        log.info("Insert a new book record" + book);
                    }else{
                        System.out.println("Insert failed");
                    }
                }
        );
    }

    private static void addStudent(Scanner scanner){
        System.out.print("Please input the student's name:");
        String name = scanner.nextLine();
        System.out.print("Please input the student's sex:");
        String sex = scanner.nextLine();
        System.out.print("Please input the student's grade:");
        String grade = scanner.nextLine();
        int g = Integer.parseInt(grade);
        Student student = new Student(name, sex, g);
        SqlUtil.doSqlWork(mapper -> {
                int i = mapper.addStudent(student);
                if ( i > 0) {
                    System.out.println("Insert successfully");
                    log.info("Insert a new student record" + student);
                }else{
                    System.out.println("Insert failed");
                }
            }
        );
    }
}

Screenshot 2024-04-29 at 00.04.50

3 Borrow

Main.java:

package book.manage;

import book.manage.entity.Book;
import book.manage.entity.Student;
import book.manage.mapper.BookMapper;
import book.manage.sql.SqlUtil;
import lombok.extern.java.Log;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.util.Scanner;
import java.util.logging.LogManager;

// Press Shift twice to open the Search Everywhere dialog and type `show whitespaces`,
// then press Enter. You can now see whitespace characters in your code.

@Log
public class Main {
    public static void main(String[] args) {
        try(Scanner scanner = new Scanner(System.in)){
            LogManager manager = LogManager.getLogManager();
            manager.readConfiguration(Resources.getResourceAsStream("logging.properties"));

            while(true){
                System.out.println("==========================");
                System.out.println("1. Insert a student information");
                System.out.println("2. Insert a book information");
                System.out.println("3. Insert book borrow information");
                System.out.println(("Please insert the operation you want(input any other number to exit):"));
                int input;
                try {
                    input = scanner.nextInt();
                }catch (Exception e) {
                    return;
                }
                scanner.nextLine();
                switch (input){
                    case 1:
                        addStudent(scanner);
                        break;
                    case 2:
                        addBook(scanner);
                        break;
                    case 3:
                        addBorrow(scanner);
                        break;
                    default:
                        return;
                }
            }
        }catch (IOException e){
            log.severe(e.getMessage());
        }

    }

    private static void addBook(Scanner scanner){
        System.out.print("Please input the book's name:");
        String name = scanner.nextLine();
        System.out.print("Please input the books's desc:");
        String desc = scanner.nextLine();
        System.out.print("Please input the book's price:");
        String price = scanner.nextLine();
        double p = Integer.parseInt(price);
        Book book = new Book(name, desc, p);
        SqlUtil.doSqlWork(mapper -> {
                    int i = mapper.addBook(book);
                    if ( i > 0) {
                        System.out.println("Insert successfully");
                        log.info("Insert a new book record" + book);
                    }else{
                        System.out.println("Insert failed");
                    }
                }
        );
    }

    private static void addStudent(Scanner scanner){
        System.out.print("Please input the student's name:");
        String name = scanner.nextLine();
        System.out.print("Please input the student's sex:");
        String sex = scanner.nextLine();
        System.out.print("Please input the student's grade:");
        String grade = scanner.nextLine();
        int g = Integer.parseInt(grade);
        Student student = new Student(name, sex, g);
        SqlUtil.doSqlWork(mapper -> {
                int i = mapper.addStudent(student);
                if ( i > 0) {
                    System.out.println("Insert successfully");
                    log.info("Insert a new student record" + student);
                }else{
                    System.out.println("Insert failed");
                }
            }
        );
    }
    private static void addBorrow(Scanner scanner){
        System.out.print("Please input the book's id:");
        String a = scanner.nextLine();
        int bid = Integer.parseInt(a);

        System.out.print("Please input the student's id:");
        String b = scanner.nextLine();
        int sid = Integer.parseInt(b);

        SqlUtil.doSqlWork(mapper -> {
                    int i = mapper.addBorrow(sid, bid);
                    if ( i > 0) {
                        System.out.println("Insert successfully");
                        log.info("Insert a new borrow record" + sid + " " + bid);
                    }else{
                        System.out.println("Insert failed");
                    }
                }
        );
    }
}

BookMapper:

package book.manage.mapper;

import book.manage.entity.Book;
import book.manage.entity.Student;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Param;

public interface BookMapper {
    // 不用sid, 因为数据库字段为nut null, sid可以自增
    @Insert("insert into student(name, sex, grade) values (#{name}, #{sex}, #{grade})")
    int addStudent(Student student);

    @Insert("insert into book(title, `desc`, price) values (#{title}, #{desc}, #{price})")
    int addBook(Book student);
    //``是为了避免关键字冲突

    @Insert("insert into borrow(sid, bid) values (#{sid}, #{bid})")
    int addBorrow(@Param("sid") int sid, @Param("bid") int bid);
}

Screenshot 2024-04-29 at 00.37.47

4 show

4.1 Show Borrow

Book.java:

package book.manage.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

// NoArgsConstructor注解会生成一个无参构造函数
// 无参构造函数是必须的,因为mybatis会通过反射调用这个构造函数
// AllArgsConstructor注解会生成一个包含所有参数的构造函数
// 构造函数是什么
// 构造函数是一种特殊的方法,用于初始化对象
// 构造函数的作用是什么
@Data
@NoArgsConstructor
public class Book {
    int bid;
    String title;
    String desc;
    double price;
    // 为什么要用final
    // 因为数据库中的字段是not null, 所以必须要有值

    public Book(String title, String desc, double price) {
        this.title = title;
        this.desc = desc;
        this.price = price;
    }
}

Borrow.java:

package book.manage.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
public class Borrow {
    int id;
    Student student;
    Book book;

    public Borrow(Student student, Book book) {
        this.student = student;
        this.book = book;
    }
}

Student.java:

package book.manage.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

// @Data 注解里面只包含@RequiredArgsConstructor, @Getter, @Setter, @EqualsAndHashCode, @ToString这些注解
// 要求构造的参数必须是final的
@Data
@NoArgsConstructor
public class Student {
    int sid;
    String name;
    String sex;
    int grade;

    public Student(String name, String sex, int grade) {
        this.name = name;
        this.sex = sex;
        this.grade = grade;
    }
}

BookMapper.java:

package book.manage.mapper;

import book.manage.entity.Book;
import book.manage.entity.Borrow;
import book.manage.entity.Student;
import org.apache.ibatis.annotations.*;

import java.util.List;

public interface BookMapper {
    // 不用sid, 因为数据库字段为nut null, sid可以自增
    @Insert("insert into student(name, sex, grade) values (#{name}, #{sex}, #{grade})")
    int addStudent(Student student);

    @Insert("insert into book(title, `desc`, price) values (#{title}, #{desc}, #{price})")
    int addBook(Book book);
    //``是为了避免关键字冲突

    @Insert("insert into borrow(sid, bid) values (#{sid}, #{bid})")
    int addBorrow(@Param("sid") int sid, @Param("bid") int bid);

    @Results({
            @Result(column = "id", property = "id", id = true),
            @Result(column = "sid", property = "student", one = @One(select = "getStudentBySid")),
            @Result(column = "bid", property = "book", one = @One(select = "getBookByBid"))
    })
    @Select("select * from borrow")
    List<Borrow> getBorrowList();
    // 这里的@Results注解是为了将查询结果映射到Borrow对象上
    // @Result注解是为了将查询结果的列名映射到对象的属性上
    // column是数据库的列名,property是对象的属性名
    // property = "id"表示将查询结果的id列映射到Borrow对象的id属性上
    // id = true表示这个属性是主键
    // property = "student"表示将查询结果的sid列映射到Borrow对象的student属性上
    // @One表示这个属性是一个对象,select表示这个对象的查询方法

    @Results({
            @Result(column = "sid", property = "sid", id = true),
            @Result(column = "name", property = "name"),
            @Result(column = "sex", property = "sex"),
            @Result(column = "grade", property = "grade")
    })
    @Select("select * from student where sid = #{sid}")
    Student getStudentBySid(int sid);

    @Select("select * from book where bid = #{bid}")
    Book getBookByBid(int bid);

}

MainTest.java:

package com.test;

import book.manage.sql.SqlUtil;
import org.junit.jupiter.api.Test;

public class MainTest {
    @Test
    public void test1() {
        SqlUtil.doSqlWork(mapper -> {
            mapper.getBorrowList().forEach(System.out::println);
        });
    }

}

Screenshot 2024-04-29 at 12.53.33

Main.java:

package book.manage;

import book.manage.entity.Book;
import book.manage.entity.Student;
import book.manage.mapper.BookMapper;
import book.manage.sql.SqlUtil;
import lombok.extern.java.Log;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.util.Scanner;
import java.util.logging.LogManager;

// Press Shift twice to open the Search Everywhere dialog and type `show whitespaces`,
// then press Enter. You can now see whitespace characters in your code.

@Log
public class Main {
    public static void main(String[] args) {
        try(Scanner scanner = new Scanner(System.in)){
            LogManager manager = LogManager.getLogManager();
            manager.readConfiguration(Resources.getResourceAsStream("logging.properties"));

            while(true){
                System.out.println("==========================");
                System.out.println("1. Insert a student information");
                System.out.println("2. Insert a book information");
                System.out.println("3. Insert book borrow information");
                System.out.println("4. Show borrow information");
                System.out.println(("Please insert the operation you want(input any other number to exit):"));
                int input;
                try {
                    input = scanner.nextInt();
                }catch (Exception e) {
                    return;
                }
                scanner.nextLine();
                switch (input){
                    case 1:
                        addStudent(scanner);
                        break;
                    case 2:
                        addBook(scanner);
                        break;
                    case 3:
                        addBorrow(scanner);
                        break;
                    case 4:
                        showBorrow();
                        break;
                    default:
                        return;
                }
            }
        }catch (IOException e){
            log.severe(e.getMessage());
        }

    }

    private static void addBook(Scanner scanner){
        System.out.print("Please input the book's name:");
        String name = scanner.nextLine();
        System.out.print("Please input the books's desc:");
        String desc = scanner.nextLine();
        System.out.print("Please input the book's price:");
        String price = scanner.nextLine();
        double p = Integer.parseInt(price);
        Book book = new Book(name, desc, p);
        SqlUtil.doSqlWork(mapper -> {
                    int i = mapper.addBook(book);
                    if ( i > 0) {
                        System.out.println("Insert successfully");
                        log.info("Insert a new book record" + book);
                    }else{
                        System.out.println("Insert failed");
                    }
                }
        );
    }

    private static void addStudent(Scanner scanner){
        System.out.print("Please input the student's name:");
        String name = scanner.nextLine();
        System.out.print("Please input the student's sex:");
        String sex = scanner.nextLine();
        System.out.print("Please input the student's grade:");
        String grade = scanner.nextLine();
        int g = Integer.parseInt(grade);
        Student student = new Student(name, sex, g);
        SqlUtil.doSqlWork(mapper -> {
                int i = mapper.addStudent(student);
                if ( i > 0) {
                    System.out.println("Insert successfully");
                    log.info("Insert a new student record" + student);
                }else{
                    System.out.println("Insert failed");
                }
            }
        );
    }
    private static void addBorrow(Scanner scanner){
        System.out.print("Please input the book's id:");
        String a = scanner.nextLine();
        int bid = Integer.parseInt(a);

        System.out.print("Please input the student's id:");
        String b = scanner.nextLine();
        int sid = Integer.parseInt(b);

        SqlUtil.doSqlWork(mapper -> {
                    int i = mapper.addBorrow(sid, bid);
                    if ( i > 0) {
                        System.out.println("Insert successfully");
                        log.info("Insert a new borrow record" + sid + " " + bid);
                    }else{
                        System.out.println("Insert failed");
                    }
                }
        );
    }

    private static void showBorrow(){
        SqlUtil.doSqlWork(mapper -> {
            mapper.getBorrowList().forEach(borrow -> {
                System.out.println(borrow.getStudent().getName() + " borrow " + borrow.getBook().getTitle());
            });
        });

    }
}

Screenshot 2024-04-29 at 14.37.27

4.2 Show student & book

BookMapper.java:

package book.manage.mapper;

import book.manage.entity.Book;
import book.manage.entity.Borrow;
import book.manage.entity.Student;
import org.apache.ibatis.annotations.*;

import java.util.List;

public interface BookMapper {
    // 不用sid, 因为数据库字段为nut null, sid可以自增
    @Insert("insert into student(name, sex, grade) values (#{name}, #{sex}, #{grade})")
    int addStudent(Student student);

    @Insert("insert into book(title, `desc`, price) values (#{title}, #{desc}, #{price})")
    int addBook(Book book);
    //``是为了避免关键字冲突

    @Insert("insert into borrow(sid, bid) values (#{sid}, #{bid})")
    int addBorrow(@Param("sid") int sid, @Param("bid") int bid);

    @Results({
            @Result(column = "id", property = "id", id = true),
            @Result(column = "sid", property = "student", one = @One(select = "getStudentBySid")),
            @Result(column = "bid", property = "book", one = @One(select = "getBookByBid"))
    })
    @Select("select * from borrow")
    List<Borrow> getBorrowList();
    // 这里的@Results注解是为了将查询结果映射到Borrow对象上
    // @Result注解是为了将查询结果的列名映射到对象的属性上
    // column是数据库的列名,property是对象的属性名
    // property = "id"表示将查询结果的id列映射到Borrow对象的id属性上
    // id = true表示这个属性是主键
    // property = "student"表示将查询结果的sid列映射到Borrow对象的student属性上
    // @One表示这个属性是一个对象,select表示这个对象的查询方法

    @Select("select * from student")
    List<Student> getStudentList();
    @Select("select * from book")
    List<Book> getBookList();
    @Select("select * from student where sid = #{sid}")
    Student getStudentBySid(int sid);

    @Select("select * from book where bid = #{bid}")
    Book getBookByBid(int bid);



}

MainTest.java:

package com.test;

import book.manage.sql.SqlUtil;
import org.junit.jupiter.api.Test;

public class MainTest {
    @Test
    public void test1() {
        SqlUtil.doSqlWork(mapper -> {
            mapper.getBorrowList().forEach(System.out::println);
        });
    }

    @Test
    public void test2() {
        SqlUtil.doSqlWork(mapper -> {
            mapper.getBookList().forEach(System.out::println);
        });
    }

    @Test
    public void test3() {
        SqlUtil.doSqlWork(mapper -> {
            mapper.getStudentList().forEach(System.out::println);
        });
    }

}

Screenshot 2024-04-29 at 15.10.57

Main.java:

package book.manage;

import book.manage.entity.Book;
import book.manage.entity.Student;
import book.manage.mapper.BookMapper;
import book.manage.sql.SqlUtil;
import lombok.extern.java.Log;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.util.Scanner;
import java.util.logging.LogManager;

// Press Shift twice to open the Search Everywhere dialog and type `show whitespaces`,
// then press Enter. You can now see whitespace characters in your code.

@Log
public class Main {
    public static void main(String[] args) {
        try(Scanner scanner = new Scanner(System.in)){
            LogManager manager = LogManager.getLogManager();
            manager.readConfiguration(Resources.getResourceAsStream("logging.properties"));

            while(true){
                System.out.println("==========================");
                System.out.println("1. Insert a student information");
                System.out.println("2. Insert a book information");
                System.out.println("3. Insert book borrow information");
                System.out.println("4. Show borrow information");
                System.out.println("5. Show book information");
                System.out.println("6. Show student information");
                System.out.println(("Please insert the operation you want(input any other number to exit):"));
                int input;
                try {
                    input = scanner.nextInt();
                }catch (Exception e) {
                    return;
                }
                scanner.nextLine();
                switch (input){
                    case 1:
                        addStudent(scanner);
                        break;
                    case 2:
                        addBook(scanner);
                        break;
                    case 3:
                        addBorrow(scanner);
                        break;
                    case 4:
                        showBorrow();
                        break;
                    case 5:
                        showBook();
                        break;
                    case 6:
                        showStudent();
                        break;
                    default:
                        return;
                }
            }
        }catch (IOException e){
            log.severe(e.getMessage());
        }

    }

    private static void addBook(Scanner scanner){
        System.out.print("Please input the book's name:");
        String name = scanner.nextLine();
        System.out.print("Please input the books's desc:");
        String desc = scanner.nextLine();
        System.out.print("Please input the book's price:");
        String price = scanner.nextLine();
        double p = Integer.parseInt(price);
        Book book = new Book(name, desc, p);
        SqlUtil.doSqlWork(mapper -> {
                    int i = mapper.addBook(book);
                    if ( i > 0) {
                        System.out.println("Insert successfully");
                        log.info("Insert a new book record" + book);
                    }else{
                        System.out.println("Insert failed");
                    }
                }
        );
    }

    private static void addStudent(Scanner scanner){
        System.out.print("Please input the student's name:");
        String name = scanner.nextLine();
        System.out.print("Please input the student's sex:");
        String sex = scanner.nextLine();
        System.out.print("Please input the student's grade:");
        String grade = scanner.nextLine();
        int g = Integer.parseInt(grade);
        Student student = new Student(name, sex, g);
        SqlUtil.doSqlWork(mapper -> {
                int i = mapper.addStudent(student);
                if ( i > 0) {
                    System.out.println("Insert successfully");
                    log.info("Insert a new student record" + student);
                }else{
                    System.out.println("Insert failed");
                }
            }
        );
    }
    private static void addBorrow(Scanner scanner){
        System.out.print("Please input the book's id:");
        String a = scanner.nextLine();
        int bid = Integer.parseInt(a);

        System.out.print("Please input the student's id:");
        String b = scanner.nextLine();
        int sid = Integer.parseInt(b);

        SqlUtil.doSqlWork(mapper -> {
                    int i = mapper.addBorrow(sid, bid);
                    if ( i > 0) {
                        System.out.println("Insert successfully");
                        log.info("Insert a new borrow record" + sid + " " + bid);
                    }else{
                        System.out.println("Insert failed");
                    }
                }
        );
    }

    private static void showBorrow(){
        SqlUtil.doSqlWork(mapper -> {
            mapper.getBorrowList().forEach(borrow -> {
                System.out.println(borrow.getStudent().getName() + " borrow " + borrow.getBook().getTitle());
            });
        });
    }

    private static void showBook(){
        SqlUtil.doSqlWork(mapper -> {
            mapper.getBookList().forEach(book ->{
                    System.out.println(book.getBid() + "." + book.getTitle() + " " + book.getDesc() + " " + book.getPrice());
            });
        });
    }

    private static void showStudent(){
        SqlUtil.doSqlWork(mapper -> {
            mapper.getStudentList().forEach(student -> {
                System.out.println(student.getSid() + "." + student.getName() + " " + student.getSex() + " " + student.getGrade());
            });
        });
    }
}

5

打包, 添加依赖插件

pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>BookManagment</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.30</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>5.8.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.33</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.7</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <configuration>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                    <archive>
                        <manifest>
                            <addClasspath>true</addClasspath>
                            <mainClass>book.manage.Main</mainClass>
                        </manifest>
                    </archive>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
            </plugin>
        </plugins>
    </build>
</project>

Screenshot 2024-04-29 at 15.54.01

Screenshot 2024-04-29 at 15.55.55

Screenshot 2024-04-29 at 15.56.19

Screenshot 2024-04-29 at 16.05.23