本项目是基于Mybatis+JUL+Lombok+Maven的图书管理系统(带单元测试)
成果示范


项目需求:
设计数据库
建立数据库(book_manage)
字符集要修改,否则可能出现乱码

创建表
学生表(student):

书籍表(book)

书籍借阅信息(borrow)

设置外键
注意,外键设置在borrow表,可以理解为一个二维表。

设置删除外键的触发器
注意,触发器设置在book和student表。
被设计触发器的表并不是外键表,而是进行操作的表。
我设计一个书籍信息表,设计一个学生表,设计一个学生借书表,外键存在于学生借书表(理解为二维表),触发器存在于学生表和书籍信息表(理解为一维表)。

student表中触发器的命令是:
1
| DELETE FROM borrow where sid = old.sid
|
可以看到触发器中是delete,触发器本身的触发条件的定义也是delete,二者本身其实毫无关系。该语句联系到外部的”删除”,可以解释为
1 2
| 在删除学生表中的信息之前,要删除借阅表中进行约束的外键,因为进行的是删除操作,所以要去old表中寻找sid (从借阅表中删除你删除的sid对应的那行外键)
|
另一侧book表同理

进行测试
我们写一个学生,写一本书,写一个借阅关系。

发现删除学生或者书后,borrow对应的借阅行也随之删除。触发器设置成功。
下面我们实现需求1:在线录入书籍信息,学生信息。
创建Maven项目

pom.xml中写入依赖
(Mybatis+jdbc+JUnit+Lombok)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| <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>
|
配置后进行Maven加载

测试

项目运行成功。
IDEA连接数据库


测试Insert功能
Mybatis配置文件mybatis-config.xml
在默认的文件夹中创建mybatis文件mybatis-config.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <?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> <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_manage"/> <property name="username" value="root"/> <property name="password" value="123456"/> </dataSource> </environment> </environments> </configuration>
|
报错1:显示dtd注册
解决方法:在设置中添加"http://mybatis.org/dtd/mybatis-3-config.dtd"
到默认dtd中

定义实体类(Lombok)
student
1 2 3 4 5 6 7 8 9 10 11 12 13
| package book.manage.entity;
import lombok.Data;
@Data public class Student { int sid; final String name; final String sex; final int grade; }
|
Book
1 2 3 4 5 6 7 8 9 10 11 12 13
| package book.manage.entity;
import lombok.Data;
@Data public class Book { int bid; final String title; final String desc; final double price; }
|
我们发现数据库中的enum,在实体类中我们定义的是String
数据库中的decimal,我们定义的是double
由此可见并不需要完全对应,只要能让数值进行大致对应即可。
配置mybatis.xml中的mapper
在mybatis-config.xml中进行配置mapper
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <?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> <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_manage"/> <property name="username" value="root"/> <property name="password" value="123456"/> </dataSource> </environment> </environments> <mappers> <mapper class="book.manage.mapper.BookMapper"/> </mappers> </configuration>
|
问题1:我记得有一个作用整个包,就小写的是什么来着?
答:是mybatis-config.xml中可以对实体类整个包进行默认读取,mapper.xml中可以直接使用别名以来连接接口方法和实体类进行映射关系的构造。
问题2:使用接口注解是什么实现流程?使用mapper.xml是什么操作流程?
①接口注解:用resources方法读取mybatis配置文件,可以知道mapper接口文件的位置,然后opensession相当于打开了一次会话,读取mapper相当于打开了一个映射关系合集。
②mapper配置文件:使用简单的IO方法读取mybatis配置文件。配置文件读取了mapper.xml映射规则将接口和实体类进行连接。Main调用接口,接口调用实体类按照之前设定的关系进行连接。
创建接口(用注解代替mapper.xml)
1 2 3 4 5 6 7 8 9 10 11
| package book.manage.mapper;
import book.manage.entity.Student; import org.apache.ibatis.annotations.Insert; import org.apache.ibatis.annotations.Select;
public interface BookMapper { @Insert("insert into student(name,sex,grade) value(#{name},#{sex},#{grade})") int addStudent(Student student); }
|
Main进行测试
SqlSessionfactorybuilder(读取mybatis.xml)→factory
factory.opensession()→sqlssion
sqlssion.getmapper(mapper)→mapper
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| package book.manage;
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 org.apache.ibatis.session.defaults.DefaultSqlSessionFactory;
import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException;
public class Main { public static void main(String[] args) throws IOException { SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsReader("mybatis-config.xml")); try(SqlSession session = factory.openSession(true)){ BookMapper mapper = session.getMapper(BookMapper.class);
System.out.println(mapper.addStudent(new Student("小明","男",2019))); } } }
|
报错2:传入数据时候,由于lombok的构造参数,默认输入的是sid,
解决办法:①删除Student中的@AllArgsConstructor
,再插入时就会与接口编写的sql语句进行对应②在接口中形参设置为Student student
③给实体类的变量加上final(final加了就会去找没有sid的构造函数,因为数据库字段非空,sid可以自增)
报错3:进行Insert操作的测试时,没有读取到mybatis-comfig.xml文件

原因:读取resources文件的函数用错
1 2 3 4 5 6
| new SqlSessionFactoryBuilder().build(new FileInputStream("mybatis-config.xml"));
new SqlSessionFactoryBuilder().build(Resources.getResourceAsReader("mybatis-config.xml"));
|
new FileInputStream
读取文件时必须加上详细的文件地址,Resources.getResourceAsReader
可以直接读取resources文件夹里面的文件
结果
生效了一行

数据库结果


插入书籍信息同理
报错:插入数据失败
解决:
①书的描述不能使用”DESC
“作为关键字,DESC
时数据库排序的关键字,把DESC
换成des
成功插入。
②或者给sql语句中的desc加上单引号,变成’desc’,如果是关键字就要加上飘。
主要思路:
①创建实体类
②编写Mapper.java接口
③编写Main
优化sqlsession
用SqlUtil创建sqlsession
将创建sqlsession的过程单独放在一个工具类中,只需要在主函数中对mapper文件进行getmapper即可。此项目再次简化,将创建mapper的过程也放在SqlUtil过程中。
SqlSessionfactorybuilder(读取mybatis.xml)→factory
factory.opensession()→sqlssion
sqlssion.getmapper(mapper)→mapper
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| 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;
|
这样主函数就可以直接创建sqlsession,之间创建不同的mapper,针对mapper很多的情况非常方便。
Main主菜单格式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| package book.manage;
import java.io.IOException; import java.util.Scanner;
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.录入学生信息"); System.out.println("2.录入书籍信息"); System.out.println("输入你想要执行的操作(输入其他任意数字退出):"); int input; try { input = scanner.nextInt(); }catch(Exception e){ return; } switch(input){ case 1: break; case 2: break; default: return; } } } } }
|

代码整理一
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
| package book.manage;
import book.manage.entity.Student; import book.manage.sql.SqlUtil;
import java.io.IOException; import java.util.Scanner;
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.录入学生信息"); System.out.println("2.录入书籍信息"); System.out.println("输入你想要执行的操作(输入其他任意数字退出):"); int input; try { input = scanner.nextInt(); }catch(Exception e){ return; } scanner.nextLine(); switch(input){ case 1: addStudent(scanner); break; case 2: break; default: return; } } } } 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 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("录入成功!"); }else{ System.out.println("录入失败,请重试!"); } }); }
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| 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;
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <?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> <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_manage"/> <property name="username" value="root"/> <property name="password" value="123456"/> </dataSource> </environment> </environments> <mappers> <mapper class="book.manage.mapper.BookMapper"/> </mappers> </configuration>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| 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.Select;
public interface BookMapper {
@Insert("insert into student(name,sex,grade) value(#{name},#{sex},#{grade})") int addStudent(Student student);
@Insert("insert into book(title,`desc`,price) value(#{title},#{desc},#{price})") int addBook(Book book);
@Select("select * from student where sid = #{sid}") Student getStudentBySid(int sid);
@Select("select* from book where bid = #{bid}") Book getBookByBid(int bid);
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| package book.manage.entity;
import lombok.Data;
@Data public class Student { int sid; final String name; final String sex; final int grade; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| package book.manage.entity;
import lombok.Data;
@Data public class Book { int bid; final String title; final String desc; final double price; }
|

开始配置日志系统
配置(日志配置)文件
logging.properties
1 2 3 4 5 6 7 8 9 10 11
| #设置输出级别 #不用控制台打印,用文件打印 handlers= java.util.logging.FileHandler .level= All
#命名输出文件 java.util.logging.FileHandler=console.log #设置输出格式为默认 java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter
|
主函数配置日志
1 2 3
| LogManager manager = LogManager.getLogManager(); manager.readConfiguration(Resources.getResourceAsStream("logging.properties"));
|
报错1:不能使用log.info();

解决:在Main类上添加注解@Log

报错2:(.level)附近的日志配置文件书写格式错误

解决:ALL应该全部大写
报错3:输出到文件中的日志都是标签格式的

解决:单词打错,应该是handler,影响了日志文件格式的定义。
让日志追加打印
配置logging.properties
1 2 3 4 5 6 7 8 9 10 11 12
| #设置输出级别 #不用控制台打印,用文件打印 handlers= java.util.logging.FileHandler .level= INFO
#命名输出文件 java.util.logging.FileHandler.pattern=console.log #设置输出格式为默认 java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter #追加打印 java.util.logging.FileHandler.append=true
|

编写学生借书操作
1.编写菜单和提示输入界面



2.分析数据库表的设计
插入bid和sid即可
3.编写mapper
1 2
| @Insert("isnert into borrow(sid,bid) values(#{sid},#{bid})") int addBorrow(int sid,int bid);
|
4.编写Main中对应创建对象的函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| private static void addBorrow(Scanner scanner){ System.out.print("请输入书的编号:"); String a = scanner.nextLine(); int bid = Integer.parseInt(a); System.out.print("请输入学号:"); String b = scanner.nextLine(); int sid = Integer.parseInt(b);
SqlUtil.doSqlWork(mapper -> { int i = mapper.addBorrow(sid,bid); if(i>0){ System.out.println("录入成功!"); log.info("添加一条借阅信息"); } else{ System.out.println("录入失败,请重试!"); } }); }
|
1 2 3 4 5
| case 3: try{addBorrow(scanner);} catch(Exception e){ System.out.println("录入失败!(可能录入重复)"); break;}
|
5.完善main
提问:为什么借阅信息不需要实体类?
解答:后面进行查询就需要实体类了,查询的时候要把数据库中的东西拿出来,放在实体类中,通过实体类进行表达。
报错:sid没有找到,mapper中输入两个数,导致sid和bid没有对应上

解决:加注解表示哪个对用的是哪个

代码整理二
Main
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
| package book.manage;
import book.manage.entity.Book; import book.manage.entity.Student; import book.manage.sql.SqlUtil; import lombok.extern.java.Log; import org.apache.ibatis.annotations.Insert; import org.apache.ibatis.io.Resources;
import java.io.IOException; import java.util.Scanner; import java.util.logging.LogManager;
@Log public class Main { public static void main(String[] args) throws IOException { 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.录入学生信息"); System.out.println("2.录入书籍信息"); System.out.println("3.添加借阅信息"); System.out.print("输入你想要执行的操作(输入其他任意数字退出):"); 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: try{addBorrow(scanner);} catch(Exception e){ System.out.println("录入失败!(可能录入重复)"); break;} default: return; } } } } private static void addBorrow(Scanner scanner){ System.out.print("请输入书的编号:"); String a = scanner.nextLine(); int bid = Integer.parseInt(a); System.out.print("请输入学号:"); String b = scanner.nextLine(); int sid = Integer.parseInt(b);
SqlUtil.doSqlWork(mapper -> { int i = mapper.addBorrow(sid,bid); if(i>0){ System.out.println("录入成功!"); log.info("添加一条借阅信息"); } else{ System.out.println("录入失败,请重试!"); } }); }
private static void addStudent(Scanner scanner){ System.out.print("请输入学生名字:"); String name = scanner.nextLine(); System.out.print("请输入学生的性别(男/女):"); String sex = scanner.nextLine(); System.out.print("请输入学生的年级:"); 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("录入成功!"); log.info("新添加一条学生信息"+student); }else{ System.out.println("录入失败,请重试!"); } }); } private static void addBook(Scanner scanner){ System.out.print("请输入书名:"); String title = scanner.nextLine(); System.out.print("请输入书籍简介:"); String desc = scanner.nextLine(); System.out.print("请输入书的价格"); 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("录入失败,请重试!"); } }); }
}
|
SqlUtil
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| 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;
|
mapper.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| 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; import org.apache.ibatis.annotations.Select;
public interface BookMapper {
@Insert("insert into student(name,sex,grade) value(#{name},#{sex},#{grade})") int addStudent(Student student);
@Insert("insert into book(title,`desc`,price) value(#{title},#{desc},#{price})") int addBook(Book book);
@Select("select* from student where sid = #{sid}") Student getStudentBySid(int sid);
@Select("select* from book where bid = #{bid}") Book getBookByBid(int bid);
@Insert("insert into borrow(sid,bid) values(#{sid},#{bid})") int addBorrow(@Param("sid")int sid,@Param("bid")int bid);
}
|
mybaits.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| <?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"/> <property name="url" value="jdbc:mysql://localhost:3306/book_manage"/> <property name="username" value="root"/> <property name="password" value="123456"/> </dataSource> </environment> </environments> <mappers> <mapper class="book.manage.mapper.BookMapper"/> </mappers> </configuration>
|
logging.properties
1 2 3 4 5 6 7 8 9 10 11 12
| #设置输出级别 #不用控制台打印,用文件打印 handlers= java.util.logging.FileHandler .level= INFO
#命名输出文件 java.util.logging.FileHandler.pattern=console.log #设置输出格式为默认 java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter #追加打印 java.util.logging.FileHandler.append=true
|
Student
1 2 3 4 5 6 7 8 9 10 11 12
| package book.manage.entity;
import lombok.Data;
@Data public class Student { int sid; final String name; final String sex; final int grade; }
|
Book
1 2 3 4 5 6 7 8 9 10 11 12
| package book.manage.entity;
import lombok.Data;
@Data public class Book { int bid; final String title; final String desc; final double price; }
|
查询全部借阅信息
查询操作就需要创建实体类,封装成一个类,不然没办法查。
在接口中定义<List>实体类
前面的插入数据的时候可以用int 进行创建对象
封装一个查询对象
borrow实体类
1 2 3 4 5 6 7 8 9 10 11
| package book.manage.entity;
@Data public class Borrow { int id; Student student; Book book; }
|
使用TestMain进行测试
好处:
①不会真正对数据库进行操作
②不会真正对日志进行改写
TestMain.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| 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); }); } }
|
报错1:“sex”无法与“女”进行对应
解决方法:①给book和student都加上@NoArgsConstructor
,去掉成员属性中的final,加上一个不带主键的构造方法。
②给borrow加上@Data

测试结束后给主方法添加
1 2 3 4 5 6 7 8
| private static void showBorrow(Scanner scanner){ SqlUtil.doSqlWork(mapper ->{ mapper.getBorrowList().forEach(borrow -> { System.out.println(borrow.getStudent().getName()+" -> "+borrow.getBook().getTitle()); }); }); }
|
查询全部的书籍和学生信息
编写mapper
1 2 3 4 5
| @Select("select * from student") List<Student> getStudentList();
@Select("select* from book") List<Book> getBookList();
|
在TestMain中测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| @Test public void test1(){ SqlUtil.doSqlWork(mapper -> { mapper.getBorrowList().forEach(System.out::println); }); } @Test public void test2(){ SqlUtil.doSqlWork(mapper -> { mapper.getStudentList().forEach(System.out::println); }); } @Test public void test3(){ SqlUtil.doSqlWork(mapper -> { mapper.getBookList().forEach(System.out::println); }); }
|
报错:在执行插入借阅关系后总是会默认打印出所有的借阅关系?
原因:因为在case3后面并没有执行finally{break;},在没有case4的时候,case3会自动结束,但是如果有了case 4,case 3就不会结束,自动运行case4。
疑问:为什么在查看所有借阅关系
上面要明确对应出每一个人和书籍
原因:因为借阅关系存入的时候存的是学号,但是显示出来的是姓名和书名。所以我们要通过号来查到对象,然后通过对象获取到名字。
项目打包
打包成jar文件
在Maven中配置打包插件 (plugin放在build-plugins标签中)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| <build> <plugins> <plugin> <artifactId>maven-assembly-plugin</artifactId> <version>3.1.0</version> <configuration> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> <archive> <manifest> <addClasspath>true</addClasspath> <mainClass>com.test.Main</mainClass> </manifest> </archive> </configuration> <executions> <execution> <id>make-assembly</id> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
|
JUnit5的插件也要拿过来,因为版本太新,尚未兼容
1 2 3 4 5 6 7 8 9 10
| <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.22.0</version> </plugin> </plugins> </build>
|
执行打包package

运行jar文件
报错:无法加载主类com.test.Main
解决:属于路径错误问题。Main前面应该指定正确的路径,比如如果Main文件是package book.manage;
那么路径就应该写book.manege.Main


关于运行jar包的日志文件生成
windows默认在C:\Users\用户名\

后续相关优化
1.改变日志生成位置
如果想改的话可以改logging.properties文件中的
1 2
| #命名输出文件 java.util.logging.FileHandler.pattern=C\\Users\\64570\\Desktop\\console.log
|
就会默认输出到桌面了。
2.给书籍价格加上小数点
原因:是书籍的数据库表格建立的问题,给price加上小数点就OK了
