数据库课设总结

题目要求:某大学图书馆希望建立一个数据库系统来管理图书借阅情况。图书馆用户有学生和教师两大类。每个用户都可以借阅多本图书,每本图书也可供借阅的用户数由图书馆藏量决定。学生用户的借阅数量不能超过去5本,教师用户按不同职称借阅量有所不同,副教授以上可以借阅10本,讲师可以借阅8本,助教可以借阅6本。图书借阅有一定期限,最长为三个月,超期需要缴纳罚款。图书需要分类管理,方便用户借阅。

ER图:

流程图:

 

 

# 1.idea关联数据库(我个人使用的是mysql),有以下几个方面:

服务器名称:localhost

密码:设置的初始密码

端口号:一般默认都是3306

用户是:root

数据库:当前要操作的数据库名称

以下这些是固定的:

db.setUseSSL(false);

db.setCharacterEncoding("utf-8");

db.setServerTimezone("Asia/Shanghai");

具体如下:

public class DBUtil {
    //由于mysql DataSource对象只需要一份,所以,一个static就够了
    private static final DataSource dataSource;
    static{
        MysqlDataSource db = new MysqlDataSource();
        db.setServerName("localhost");
        //db.setServerName("192.168.1.129");
        db.setPort(3306);
        db.setUser("root");
        db.setPassword("123456");
        db.setDatabaseName("lib_0403");
        //db.setDatabaseName("hsp_db02");
        //以下这些是固定的
        db.setUseSSL(false);
        db.setCharacterEncoding("utf-8");
        db.setServerTimezone("Asia/Shanghai");

        dataSource = db;
        //如果没有这句话,第一条private就会报错,因为被final修饰了,必须赋值一次,并且之后的赋值都无效
    }
    public static Connection connection() throws SQLException{
        return dataSource.getConnection();
    }
}

#2.我们还需要一个model封装一些表属性,这样我们在使用时,比较方便

封装属性需要事先定义我们可能用到的元组,如何使用equals方法获取他们的哈希值,我这里理解的是得到这些数据的返回值。

#3.commands包中是我的一些命令

因为我的借书命令是跟着老师写的,他写代码时,使用了Main,但是距离我们课设的题目要求还差很多,我自己必须有一个主类去调用这些方法。

代码块:①登陆方法

   try (Connection c = DBUtil.connection()) {
        String sql = "select rid,crid from readers where name = ? and password = ? ";
        try (PreparedStatement ps = c.prepareStatement(sql)) {
            ps.setString(1, r.name);
            ps.setString(2, r.password);
            try (ResultSet rs = ps.executeQuery()) {
                if (!rs.next()) {
                    System.out.println("登陆失败,再试试吧~");
                   return;
                }
                r.rid = rs.getInt("rid");
                r.crid = rs.getInt("crid");
            }
        }
    }
System.out.println("欢迎登陆西安工程大学图书管理系统~");

②借书

System.out.println("请输入书名:");
        book.name = scanner.next();
        try (Connection c = DBUtil.connection()) {
            String sql = "select bid,count from books where name =?";
            try (PreparedStatement ps = c.prepareStatement(sql)) {
                ps.setString(1, book.name);
                try (ResultSet rs = ps.executeQuery()) {
                    if (!rs.next()) {
                        System.out.println("查无此书");
                        return;
                    }
                    book.bid = rs.getInt("bid");
                    book.count = rs.getInt("count");
                    //判断图书馆藏书是否有余量
                    if (book.count == 0) {
                        System.out.println("书籍已经被借空了");
                        return;
                    }
                }
            }
        }
        //借书操作   更改Books表
        try (Connection c = DBUtil.connection()) {
            String sql = "update books set count = count -1 where bid =?";
            try (PreparedStatement ps = c.prepareStatement(sql)) {
                //建立连接  准备要执行的语句 执行语句
                ps.setInt(1, book.bid);
                ps.executeUpdate();
            }
        }
        //更改records表
        try (Connection c = DBUtil.connection()) {
            String sql = "insert into records (rid,bid,borrowed_at,return_book) values (?,?,?,?)";
            try (PreparedStatement ps = c.prepareStatement(sql)) {
                //建立连接  准备要执行的语句 执行语句
                Date date = new Date();
                ps.setInt(1, r.rid);
                ps.setInt(2, book.bid);
                ps.setTimestamp(3, new Timestamp(new Date().getTime()));
                changeTime now = new changeTime();
                String s = now.change();
                ps.setString(4, s);
                ps.executeUpdate();
            }
        }
        System.out.println("借书成功~");
    }
}

③还书

while (flag) {
        try (Connection c = DBUtil.connection()) {
            String sql = "update records set finsih = 'yes' , return_book = ? where rid = ? and bid =?";
            try (PreparedStatement ps = c.prepareStatement(sql)) {
                ps.setString(1, time);
                ps.setInt(2, re1.rid);
                ps.setInt(3, re1.bid);
                ps.executeUpdate();
            }
        }
//修改Book表
            try (Connection c = DBUtil.connection()) {
                String sql = "update books set count = count + ?, total = total + ? where bid = ?";
                try (PreparedStatement ps = c.prepareStatement(sql)) {
                    ps.setInt(1, count);
                    ps.setInt(2, count);
                    ps.setInt(3, b1.bid);
                    ps.executeUpdate();
                }
            }
            System.out.println("还书成功~");
            break;
        }

 ④上架(1)insert上架

try (Connection c = DBUtil.connection()) {
    String sql = "insert into books (name, count, total,cbid) values (?, ?, ?,?)";
    try (PreparedStatement ps = c.prepareStatement(sql)) {
        ps.setString(1, name);
        ps.setInt(2, count);
        ps.setInt(3, count);
        ps.setInt(4, cbnum);
        ps.executeUpdate();
    }

(2)update上架

try (Connection c = DBUtil.connection()) {
    String sql = "update books set count = count + ?, total = total + ? where bid = ?";
    try (PreparedStatement ps = c.prepareStatement(sql)) {
        //这里输入的是每个通配符
        ps.setInt(1,count);
        ps.setInt(2,count);
        ps.setInt(3,b2.bid);
                ps.executeUpdate();
            }
        }
    }

 

⑤下架

(1)update下架

try (Connection c = DBUtil.connection()) {
    String sql = "update books set count = count - ?, total = total - ? where bid = ?";
    // TODO: 存在一个 BUG,书籍的存量可能会出现负数
    try (PreparedStatement ps = c.prepareStatement(sql)) {
        ps.setInt(1, count);
        ps.setInt(2, count);
        ps.setInt(3, bid);
        ps.executeUpdate();
    }
}

(2)delete下架

if (count >= total) {
    try (Connection c = DBUtil.connection()) {
        String sql = "delete from books where bid = ?";
        try (PreparedStatement ps = c.prepareStatement(sql)) {
            ps.setInt(1, bid);
            ps.executeUpdate();
        }
    }

⑥判断逾期,计算罚金

int t = time.compareTo(rebook);
if (t == 1) {
    //等于1说明此时已经超期,当前时间比应该还书的日期大,计算罚款,提示用户输入罚款,用当前时间去覆盖还书时间
    int day = (int) ((date2.getTime() - date1.getTime()) / (1000 * 3600 * 24));
    int amerce = day * 1;
    try (Connection c = DBUtil.connection()) {
        String sql = "update records set amerce = ? , return_book =? where rid =? and bid =?";
        try (PreparedStatement ps = c.prepareStatement(sql)) {
            ps.setInt(1, amerce);
            ps.setString(2, time);
            ps.setInt(3, re1.rid);
            ps.setInt(4, re1.bid);
            ps.executeUpdate();
        }
    }
    System.out.println("您已经欠款" + amerce + "元,请先交罚款");
    System.out.println("请输入您的余额:");
    int money = scanner.nextInt();
    if (money >= amerce) {
        System.out.println("还款成功~");
        flag =true;
    } else {
        System.out.println("余额不足!!!");
    }

⑦限制不同等级读者借书的最大数量

try (Connection c = DBUtil.connection()) {
    String sql = " select count(*) from records  where finsih = 'no' and rid = ? group by rid";
    try (PreparedStatement ps = c.prepareStatement(sql)) {
        ps.setInt(1, r.rid);
        try (ResultSet rs = ps.executeQuery()) {
            if (rs.next()) {
                //查询到了
                count = rs.getInt("count(*)");
            }
        }
    }
    //现在找一下最大值是多少,通过crid找出max
    String sql1 = "select max from classifyreaders where crid = ?";
    try (PreparedStatement ps = c.prepareStatement(sql1)) {
        ps.setInt(1, cr.crid);
        try (ResultSet rs1 = ps.executeQuery()) {
            if (rs1.next()) {
                //找到这个最大值了
                max = rs1.getInt("max");
                System.out.println("您最的最大借书数量:" + max);
            }
            if (max == count) {
                System.out.println("您的借书数量已到最大限度!!!");
                borrow = false;
            }
        }
    }
}

 


一开始,让我苦恼的是,没有Main就不能使用scanner,这些都是自我设限。感谢LH小兄弟,一直陪着我。其实,没有main是完全可以输入的,输出必须在main方法中,由于我后面比较懒惰了,我后面每一个类都是用了Main,直接在类中完成某一个功能。还有一个测试类,通过测试类,测试所有的功能。Java是面向对象的编程,可以有多个Main同时实现。

#4.后期差不多款完成项目的时候,因为测试类只负责登陆,我不知道如何将参数通过main传给另一个类,导致我的代码冗余多,需要重复输入,暑假的时候,我打算用更简洁的方法重新写一遍,同时实现界面。


#5.总结我遇到的一些问题

1.为了使系统功能更全面,在用户借书时,自动显示所有书籍。我一开始想的是显示整个表格,但我没有实现它。我换了一种思路,使用sql语句select,这时又有了新问题,为什么只能显示一行呢?查询到的结果集,如果只需要判定是否存在,就用if(rs.next()),就比如登陆时,只需要判定是否有这个记录。但是,我们现在是需要查看全部的书籍,这时必须用到while(rs.next()),Z核验带个话,就可以获取所有结果集。

2.小组作业,大家在看了我的代码后,提出很多意见,最经典的就是,不能直接退出,这需要用到一个标志位flag,我代码中多次用到了标志位,switch语句中,用户确定退出才能退出。如果下次参加竞赛,我可以做得更好,让功能更全面。

3.一个很困扰我的问题,用户借书时间一个月,我该怎么才能给这个月份单独加一,存入应还书的时间呢?我使用了s.substring(6,7),这个方法截取字符串指定位置的下标的内容,它是左闭右开的区间,现在已经得到了月份,使用Integer.parseInt(s)将它转为Int,此时就可以做加法了,然后使用s.replaceAll(s1,s2),用心的字符串替换旧的字符串。一个月之后的时间就得到了。

4.罚金要系统自动计算,需要当前日期减去应还书日期。首先应该比较大小,把当前的时间转为字符串类型,他有一个自带的比较方法,s.compareTo(s2),如果s大就返回1,返回是1就可以计算天数了。

int day = (int) ((date2.getTime() - date1.getTime()) / (1000 * 3600 * 24));

这条语句用来计算天数。然后我们就完成了罚金的计算。

5.每个角色对应的最大借书数量不同,组员给我的建议是触发器,如果超过数量就拒绝借书,可以尝试一下。新建了一个读者分类表,crid对应不同的max,我们使用select语句,就找出了max,这时还需设置一个标志量borrow。

6.Before start of result set报错,因为Result Set是一个结果集,我们接下来要获取什么信息,决定了是用什么语句。这个错误是由于代码错误。

7.Can not issue data maininpulation statements whith excuteQuery( )这个错误是由于没有正确使用excute语句,不同的情况使用的语句不同。比如说,execute()既能执行修改表中数据,又可以执行创建表,删除表,创建数据库,删除数据库等操作,而excuteUpdate( )针对于修改更新表中的数据,返回int类型的值,存储修改的行数。

8.Model包中封装的数据属性需要和数据库中保持一致,否则会出现SQLException异常。


#6.测试分析

我们经验不足,认为测试就是测试代码的功能,因为程序员编写代码时,他想到的情况都写了,测试时,也测不出别的方面来。就需要测试员,测试条例,应该包括可能执行成功的项目,以及应该失败的项目。

#7.最后,不管多大的项目都需要自己写自己构思。现在看,我觉得我的代码漏洞之处很多,而且过于繁琐,尽管如此,我在写的时候,每一个问题都需要很长时间的构思。尽管很辛苦,但是真正做下来,我感觉收获还是比较大的。真正要写代码,必须先构思,不能一味的借鉴别人,任何问题首先要有思路才能下手,画了流程图,思路顺下来,实现功能其实没有那么难。

  • 4
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值