图书管理系统项目笔记
所用技术:Mybatis+JUL+Lombok+Maven
分布图片:
项目需求:(顺序不重要)
- 在线录入学生信息和书籍信息
- 查询书籍信息列表
- 查询学生信息列表
- 查询借阅信息列表
- 完整的日志系统
1.前置准备
1.1数据库的设置
这是数据库百度云链接
链接:https://pan.baidu.com/s/158mqzAqlbcB_6ckA1qUOXw
提取码:97br
数据库名称为book-manage下面分别有book,student,borrow三张表
CREATE TABLE `student` (
`sid` int NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`sex` enum('男','女') NOT NULL,
`grade` int NOT NULL,
PRIMARY KEY (`sid`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb3;
CREATE TABLE `book` (
`bid` int NOT NULL AUTO_INCREMENT,
`title` varchar(255) DEFAULT NULL,
`desc` varchar(255) DEFAULT NULL,
`price` decimal(10,2) DEFAULT NULL,
PRIMARY KEY (`bid`)
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8mb3;
CREATE TABLE `borrow` (
`id` int NOT NULL AUTO_INCREMENT,
`sid` int DEFAULT NULL,
`bid` int DEFAULT NULL,
`time` datetime NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `unique_sid_bid` (`sid`,`bid`),
KEY `f_bid` (`bid`),
CONSTRAINT `f_bid` FOREIGN KEY (`bid`) REFERENCES `book` (`bid`) ON DELETE RESTRICT ON UPDATE RESTRICT,
CONSTRAINT `f_sid` FOREIGN KEY (`sid`) REFERENCES `student` (`sid`)
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb3;
注意book和student表中触发器的语句要写(别忘了)
1.2依赖的导入
在pom.xml中导入依赖
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</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.27</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
</dependency>
</dependencies>
1.3数据库链接配置的书写
在resources文件里创建xml配置类书写配置文件,我的是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 default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
//url username password 这都是你自己设置的,我可不知道
<property name="url" value="jdbc:mysql://localhost:3306/book_manage"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
//mapper映射类的书写,自己设置的接口
<mappers>
<mapper class="book.manage.mapper.BookMapper"/>
</mappers>
</configuration>
1.4.配置项书写
映射器:创建mapper文件夹并创建BookMpper接口
public interface BookMapper {
}
配置项:创建entity文件书写配置类Student,Book,Borrow(这里提一下为什么要加@NoArgsConstructor无参构造,因为后面要识别的时候@data的构造会与我们设置的构造冲突,mybatis不知道选那个,所以就干脆直接无参构造把@data的给取消)
@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;
}
}
@Data
@NoArgsConstructor
public class Book {
int bid;
String title;
String desc;
double price;
public Book(String title, String desc, double price) {
this.title = title;
this.desc = desc;
this.price = price;
}
}
@Data
public class Borrow {
int id;
Student student;
Book book;
}
配置类:简单解释一下dosqlWork,首先是自动提交表单,然后直接给我们创建一个消费的mapper,就是我们直接可以使用mapper,后面就知道怎么用了。(其中用到了lam表达式,多去了解一下,以后常用)
public class SqlUtil {
private SqlUtil(){}
private static SqlSessionFactory factory;
static {
try {
factory=new SqlSessionFactoryBuilder().build(Resources.getResourceAsReader("mybatis-config.xml"));
}catch (IOException e){
e.printStackTrace();
}
}
public static void doSqlWork(Consumer<BookMapper> consumer){
try (SqlSession sqlSession =factory.openSession(true)){
BookMapper bookMapper=sqlSession.getMapper(BookMapper.class);
consumer.accept(bookMapper);
}
}
}
2.功能实现
主要是在Main类中实现,自己创建单独的类也可以,不过我就在Main中写了。
主要思路。首先在BookMapper里面书写Sql语句的方法,然后通过dosqlWork(1.4里介绍了)产出mapper,直接调用相关方法就可以了。
2.1功能列表的实现
主要框架都是套路,都这么写这就cv就可以。
try (Scanner scanner = new Scanner(System.in)) {
//图书界面的基本功能
while (true) {
System.out.println("========================");
System.out.println("1:录入学生信息");
System.out.println("2:录入书籍信息");
System.out.println("3:增加借阅信息");
System.out.println("4:增加借阅信息");
System.out.println("5:查询学生信息");
System.out.println("6:查询书籍信息");
System.out.println("输入你要执行的操作(输入其他任意数字退出)");
int input;
try {
input = scanner.nextInt();
} catch (Exception e) {
return;
}
scanner.nextLine();
//输入数字后对应到选择的功能
switch (input) {
case 1:
break;
case 2:
break;
case 3:
break;
case 4:
break;
case 5:
break;
case 6:
break;
default:
return;
}
}
}
}
2.2在线录入学生信息和书籍信息
BookMapper方法书写:
@Insert("insert into student(name,sex,grade) values(#{name},#{sex},#{grade})")
int addStudent(Student student);
//注意`desc`是关键字`是键盘坐上esc下面的那个符号
@Insert("insert into book(title,`desc`,price) values(#{title},#{desc},#{price})")
int addBook(Book book);
Main中方法:
private static void addStudent(Scanner scanner) {
System.out.println("请输入学生的名字:");
String name = scanner.nextLine();
System.out.println("请输入学生性别:");
String sex = scanner.nextLine();
System.out.println("请输入学生的年纪:");
String grade = scanner.nextLine();
//转为int类型
int g = Integer.parseInt(grade);
Student student = new Student(name, sex, g);
//1,4的配置类
SqlUtil.doSqlWork(mapper -> {
int i = mapper.addStudent(student);
if (i > 0) {System.out.println("学生信息录入成功");
log.info("新添加了一条学生信息"+student);
}
else System.out.println("学生信息录入失败,请重试");
});
}
private static void addBook(Scanner scanner) {
System.out.println("请输入书籍的标题:");
String title = scanner.nextLine();
System.out.println("请输入书籍介绍:");
String desc = scanner.nextLine();
System.out.println("请输入书籍价格:");
String price = scanner.nextLine();
double p = Double.parseDouble(price);
Book book = new Book(title, desc, p);
SqlUtil.doSqlWork(mapper -> {
int i = mapper.addBook(book);
if (i > 0) {System.out.println("书籍信息录入成功");
log.info("新添加了一条书籍信息"+book);
}
else System.out.println("书籍信息录入失败,请重试");
});
}
写完了别忘记在Switch中相应位置的增加这些方法
可能你现在还有一写疑惑,这个log.info是什么意思,还有resources里面logging.properties文件又是干什么的,不急,下面开始来解释
2.3完整的日志系统
logging.properties配置日志文件的设置
handlers=java.util.logging.FileHandler
.level=INFO
java.util.logging.FileHandler.pattern=C:\\Users\\Administrator\\Desktop\\console.log
java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter
java.util.logging.FileHandler.append=true
这份配置将java.util.logging
框架设置为使用FileHandler
将级别为INFO
及以上的日志消息记录到名为"console.log"的文件中,该文件位于"Administrator"用户的桌面上的"C:"驱动器中。日志消息将使用SimpleFormatter
进行格式化,并且每次应用程序运行时都会追加新的日志记录到现有的"console.log"文件中。
C:\Users\Administrator\Desktop\console.log自己爱选择哪里就哪里
log.info
2.4添加借阅信息
借阅信息需要图书的id与学生id,即谁借了什么书,这与这里为什么有@Param(),是因为当有两个或者两个以上的参数的时候,
Mybatis会无法识别,必须用@Param()指定是哪一个参数,指定如下。
在main中实现功能
private static void addBorrow(Scanner scanner){
System.out.println("请输入书籍号:");
String a =scanner.nextLine();
int bid =Integer.parseInt(a);
System.out.println("请输入学号:");
String b=scanner.nextLine();
int sid =Integer.parseInt(b);
SqlUtil.doSqlWork(mapper->mapper.addBorrow(sid,bid));
}
2.5展示借阅信息(最难的部分)
在做展示功能前首先思考,展示功能的样子,展示功能无非就是xxx学生借阅了xxxx书籍,所以在设计类的时候我们需要Student和Book类。
@Data
public class Borrow {
int id;
Student student;
Book book;
}
其次就是BookMapper怎么写:
记住我们数据库中有对应xxx学生借xxx书的只有borrow的表,而且表中存放的是Student和Book的id,所以如果我们要想获取到xxx学生和xxx书,就只能通过sid和bid去找到对应的人和书然后再映射会Student和Book。
首先先通过id查询到Student和Book
@Select("select * from student where sid =#{sid}")
Student getStudentBySid(int sid);
@Select("select * from book where bid =#{bid}")
Book getBookByBid(int bid);
然后就要展示所有xxx借了xxx,所以先用List列表存储多条借阅信息然后再逐条便利,然后写好对于的映射
注:
@Result(column = "sid", property = "student", one = @One(select = "getStudentBySid"))
:这段配置表示查询结果中的 “sid” 列将会映射到对象的 “student” 属性。这里使用了@One
注解来表示这是一个一对一关系,并且通过select
属性指定了获取关联对象的方法 “getStudentBySid”。@Result(column = "bid", property = "book", one = @One(select = "getBookByBid"))
:这段配置类似于上面的配置,将查询结果中的 “bid” 列映射到对象的 “book” 属性,并且也使用了@One
注解指定获取关联对象的方法 “getBookByBid”。
@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();
然后我们只要去Main中书写方法便可以
private static void showBorrow(){
SqlUtil.doSqlWork(mapper->{
mapper.getBorrowList().forEach(borrow -> {
System.out.println(borrow.getStudent().getName()+"->"+borrow.getBook().getTitle());
});
});
}
2.6展示学生和书籍信息
这个功能就比较简单了,首先在BookMapper查询所有数据库的书籍和学生
@Select("select * from student")
List<Student> getStudentList();
@Select("select * from book")
List<Book> getBookList();
然后main写方法
private static void showStudent(){
SqlUtil.doSqlWork(mapper->{
mapper.getStudentList().forEach(student -> {
System.out.println(student.getSid()+","+student.getName()+" "+student.getSex()+" "+student.getSex()+" "+student.getGrade()+"级");
});
});
}
private static void showBook(){
SqlUtil.doSqlWork(mapper->{
mapper.getBookList().forEach(book -> {
System.out.println(book.getBid()+","+book.getTitle()+"["+book.getPrice()+"]"+book.getDesc()+")");
});
});
}
最后不要忘记在switch——case里面对应方法添加上对应方法。