文章目录

  • 前言
    • 医院信息管理系统
    • 摘要
    • 1.概述
      • 运行环境
      • 2. 1需求分析
        • 2.1.1基本分类需求分析
        • 2.1.2 主要关系流程分析
        • 2.2可行性分析
      • 3.1概念结构设计
        • 3.1.1 抽象出系统的实体
        • 3.2 设计分E-R图
      • 设计分E-R图
      • 3.3.1 全局E-R图
      • 4.1逻辑结构设计
      • 5.1数据库物理设计与实施
      • 6.数据操作要求及实现
        • 6.1.1 数据查询、更新操作
      • 6.1.2实现药品的入库、出库管理;
      • 6.1.3实现科室、医生、病人的管理;
        • (1) 逻辑增删改
        • 6.1.4实现处方的登记管理
        • 6.1.5实现收费管理;
      • 6.2 视图
      • 6.3 触发器
      • 6.4 存储过程
      • 7.基准测试
      • 8.总结
      • 9.参考文献
    • 写在最后

一节复一节,千枝攒万叶。我自不开花,免撩蜂与蝶。
皓首犹贪学,谦虚德益丰。潜神无朕际,悟物不言中。

前言

我将其开源.但希望你能从中学习到数据库设计思想.
诚然,我不是一名DBA,我仅仅读过半本高性能MySQL(第3版)和一本数据库系统概论(第5版),一本java开发手册(华山版).我从中掌握了一些知识将他们运用在了课程设计中.也许我的数据库课程设计对于这个项目结构来说不是最好,最优秀的.
但是凭借这几本书的经验,我觉得还是有可取之处的.在本次数据库系统设计中我时刻希望以一名优秀的DBA标准要求自己.
不为别的.只希望做一次,就要做好!
由于做之前就萌生了开源的想法.我就完全将mysql表设计思想,避免约束加锁,避免触发器,存储过程…等问题全部考虑到了.
所以本次课程设计不仅有逻辑操作思想,还有学校以教学为目的,对于触发器,存储过程的枷锁要求.
我也因此希望能够做全面:存储引擎的考虑,表设计,采用方案的对比,索引优化,数据库在windows下压力测试和linux下时延响应时间的测试.
这几个方面都囊括其中.
希望共同学习,共同进步.
可以加入我的qq群:287048847 一起交流数据库设计和Java的开发!这里的人都充满激情!

想要更深一步了解mysql数据库,请移步此处MySQL高性能摘要及性能优化实战—更适合开发人员


提示:以下是本篇文章正文内容,下面案例可供参考

医院信息管理系统

摘要

随着人们生活水平的不断提高,人们更重视医疗设施,医院的业务也不断增加,而对于医院来讲,信息管理系统属于其重要组成部分,确保系统高效、稳定且安全的运行是医院应关注和解决的问题,为使信息系统稳定、安全,高可用,工作人员需管理好信息系统,重视数据库安全,进而使信息数据将自身作用与价值充分发挥出来。医疗关系民脂民生,人民健康.设计人员应当格外小心谨慎,做好零失误.

1.概述

依据数据库课程设计要求,我将以DBA标准,参照mysql高性能,java开发手册,数据库系统概论等编写设计本系统.由于考虑诸多因素,对数据库的了解结合我目前的经验水平,我将使用java连接mysql数据库.shell脚本,jmeter测试工具进行测试.本系统使用mysql的原因是其在Linux下比sql server更成熟,同时它具有更高的灵活性.选用java作为数据库连接,因为我对它相较其他语言足够熟悉,同时它也足够强大.shell和jmeter都能很好的辅助我进行基准测试.以DBA的要求,应当多使用逻辑外键,少触发器,存储过程和外键级联操作.但我会将两种方案一并给出.具体设计方案详见下文.

运行环境

mysql-connector-java-8.0.22.jar
Window10
IntelliJ IDEA 2021.2.1
apache-jmeter-5.4.1
linux-centos7
spring配bean连接池

2. 1需求分析

2.1.1基本分类需求分析

1. 控制中心

 人员管理:实现对员工,病人的增删改;
 药品管理:实现对药品的入库,出库操作和处方药的登记以及药品类型,药品信息的登记
 收费管理:对药品营收的统计;

2. 查询
 员工,病人的基本信息查询;
 药品信息的查询;
 收费情况的查询;

2.1.2 主要关系流程分析

病人看病,先挂号等待分配科室.然后医师给患者看病开票据.病人拿票凭去前台充值,接着去药房拿药.药师根据患者的票凭刷卡取药,完成药品交付和收费流程.

2.2可行性分析

该系统主要包括基本数据维护、基本业务、数据库管理和信息查询四部分。
1、基本数据维护部份应包括提供管理员添加、修改并维护基本的数据途径。例如添加修改医院和办理病人入住与搬出或者换病房,管理医院里的基本设备。
2、数据库管理部分是对这个数据库的管理,包括医生,病人详细信息等。
3、该系统的技术可行性分析:在系统维护中包括医生和病人信息检索,数据库信息维护。
4、系统技术的可行性分析:
基于jvm和mysql下本系统可以运行于windows和Linux操作系统当中,可以为系统提供一个稳定的运行环境。该系统应该说有开发的必要性。
该系统主要由两大部分组成即管理维护和查询。

3.1概念结构设计

3.1.1 抽象出系统的实体

涉及的目标对象:患者,科室,医师,药师,前台收银,药品,挂号单,处方信息.

3.2 设计分E-R图

设计分E-R图



3.3.1 全局E-R图

4.1逻辑结构设计

病人病史(身份证号、姓名、性别、年龄、病例);
药品存放记录(药品编号、药品名、进价、售价、药品数量、生产日期、有效期,存储位置);
挂号(挂号编号、病人编号、性别、挂号科室、医生编号);
收费(收费员编号,收费员姓名,病人编号,药品编号,数量,金额);
医生(医生员工号,医生姓名,医生性别,医生年龄,科室,电话);
处方(医生员工号,药品编号,数量);
支付(支付编号,收费编号,价格);

5.1数据库物理设计与实施

挂号


医师信息


病人信息


药品信息


缴费信息


取药票单


处方信息


支付凭据

6.数据操作要求及实现

6.1.1 数据查询、更新操作

select * from register where register.is_delete=0;

select * from doctor where doctor.is_delete=0;

select * from patient where patient.is_delete=0;

SELECT * FROM drugs WHERE is_delete=0;

select * from charge WHERE is_delete=0;

select * from PGM WHERE is_delete=0;

select * from recipel WHERE is_delete=0;

select * from pay WHERE is_delete=0;

6.1.2实现药品的入库、出库管理;

1.INSERT INTO drugs(drug_id, drug_name, drug_price, drug_quantity, drug_storage, drug_date, usefull_life)  2.VALUES ('1000237', '长生不老丹', 9999.00, '821', 'C-8-291', '2021-09-01', '2022-09-01');  3.  4.SELECT * FROM drugs WHERE drug_name = '长生不老丹' AND is_delete=0;  

1.UPDATE drugs SET drug_name = '聪明草' WHERE drug_id = '1000237';  2.  3.UPDATE drugs SET IS_DELETE=1 WHERE drug_name='聪明草';  


对应的java后端实现

1.增删改操作  2.package com.vector.hospital_information;  3.  4.import com.vector.config.SpringConfiguration;  5.import org.junit.Test;  6.  7.import org.junit.runner.RunWith;  8.import org.springframework.context.ApplicationContext;  9.import org.springframework.context.annotation.AnnotationConfigApplicationContext;  10.import org.springframework.stereotype.Component;  11.import org.springframework.test.context.ContextConfiguration;  12.import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;  13.  14.import javax.annotation.Resource;  15.import javax.sql.DataSource;  16.import java.sql.Connection;  17.import java.sql.PreparedStatement;  18.import java.sql.SQLException;  19.  20.@RunWith(SpringJUnit4ClassRunner.class)  21.@ContextConfiguration(classes = {SpringConfiguration.class})  22.@Component("Update_test")  23.public class Update_test {  24.    @Resource(name = "dataSource")  25.    DataSource dataSource;  26.    @Resource(name = "Update_test")  27.    Update_test modify;  28.    @Test  29.    /** 30.     * 测试增删改 31.     */  32.    public void TestUpdate() throws SQLException {  33.  34.        /** 35.         * 测试增添数据 36.         */  37.        String sql1 = "INSERT INTO drugs(drug_id,drug_name,drug_price,drug_quantity,drug_storage,drug_date,usefull_life) VALUES (?, ?, ?, ?, ?, ?, ?)";  38.        modify.update(sql1,"1000237", "长生不老丹", 9999.00, "821", "A-8-291", "2021-09-01", "2022-09-01");  39.  40.        /** 41.         * 测试修改数据 42.         */  43.//        String sql2 = "UPDATE drugs SET drug_name = ? WHERE drug_id = ?";  44.//        modify.update(sql2,"聪明草","1000237");  45.//        /**  46.//         * 测试删除数据  47.//         */  48.//        String sql3 = "DELETE FROM drugs WHERE drug_name=?";  49.//        modify.update(sql3,"聪明草");  50.    }  51.    /** 52.     * 王佳慧 53.     * 通用增删改 54.     * @param sql 55.     * @param args 56.     * @throws SQLException 57.     */  58.  59.    //通用的增删改操作  60.    public void update(String sql, Object... args) throws SQLException {//sql当中占位符个数与可变形参的长度一致  61.  62.        Connection conn = null;  63.        PreparedStatement ps = null;  64.        //ApplicationContext app = null;  65.        try {  66.            //app = new AnnotationConfigApplicationContext(SpringConfiguration.class)  67.            //1.获取数据库连接  68.            conn = dataSource.getConnection();  69.            //2.预编译sql语句,返回PreparedStatement实例  70.            ps = conn.prepareStatement(sql);  71.            //3.填充占位符  72.            for (int i = 0; i < args.length; i++) {  73.                ps.setObject(i + 1, args[i]);  74.            }  75.            //4.执行sql语句  76.            ps.execute();  77.            System.out.println("添加记录成功");  78.        } catch (Exception e) {  79.            e.printStackTrace();  80.        } finally {  81.            //5.资源的关闭  82.            conn.close();  83.        }  84.    }  85.  86.}  1.Sql查询  2.package com.vector.hospital_information;  3.  4.import com.vector.config.SpringConfiguration;  5.import com.vector.test.DataSourceTest;  6.import org.junit.Test;  7.import org.junit.runner.RunWith;  8.import org.springframework.stereotype.Component;  9.import org.springframework.test.context.ContextConfiguration;  10.import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;  11.  12.import javax.annotation.Resource;  13.import javax.sql.DataSource;  14.import java.lang.reflect.Field;  15.import java.sql.*;  16.  17.@RunWith(SpringJUnit4ClassRunner.class)  18.@ContextConfiguration(classes = {SpringConfiguration.class})  19.@Component("PreparedStatementQueryTest")  20.public class PreparedStatementQueryTest {  21.  22.    @Resource(name = "dataSource")  23.    DataSource dataSource;  24.    @Resource(name = "PreparedStatementQueryTest")  25.    PreparedStatementQueryTest queryTest ;  26.  27.  28.    @Test  29.    /** 30.     * 测试查询 31.     */  32.    public void TestQuery() throws SQLException {  33.  34.  35.        /** 36.         * 测试查询一条记录 37.         */  38.        String sql = "SELECT * from drugs where drug_name=?";  39.        Drugs drugs = queryTest.getInstance(Drugs.class,sql,"长生不老丹");  40.        System.out.println(drugs);  41.  42.  43.    }  44.    /** 45.     * 王佳慧 46.     * 针对于不同的表的通用查询操作,返回表中的一条记录 47.     * @param clazz 48.     * @param sql 49.     * @param args 50.     * @param  51.     * @return 52.     */  53.    public <T>T getInstance(Class<T> clazz,String sql,Object ...args) throws SQLException {  54.        Connection conn = null;  55.        PreparedStatement ps = null;  56.        ResultSet rs = null;  57.        try {  58.            conn = dataSource.getConnection();//加载数据库  59.            ps = conn.prepareStatement(sql);  60.            for (int i = 0; i < args.length; i++) {  61.                ps.setObject(i + 1, args[i]);  62.            }  63.            //执行,获取结果集  64.            rs = ps.executeQuery();  65.            //获取结果集的元数据  66.            ResultSetMetaData rsmd = rs.getMetaData();  67.            //获取列数  68.            int columuCount = rsmd.getColumnCount();  69.            if (rs.next()) {  70.                T t = clazz.newInstance();  71.                for (int i = 0; i < columuCount; i++) {  72.                    //获取每个列的列值,通过ResultSet  73.                    Object columnValue = rs.getObject(i + 1);  74.                    //获取每个列的列名,通过ResultSetMetaData  75.                    //获取列的列名:getColumnName() ---不推荐使用  76.                    //获取列的别名:getColumnLabel()  77.                    String columnLabel = rsmd.getColumnLabel(i+1);  78.                    //通过反射,将对象指定名columnName的属性值赋值给columnValue  79.                    Field field = clazz.getDeclaredField(columnLabel);  80.                    field.setAccessible(true);  81.                    field.set(t, columnValue);  82.                }  83.                return t;  84.            }  85.        } catch (Exception e) {  86.            e.printStackTrace();  87.        } finally {  88.            conn.close();  89.        }  90.  91.        return null;  92.    }  93.  94.  95.}  


6.1.3实现科室、医生、病人的管理;

(1) 逻辑增删改

1.INSERT INTO register(r_num, r_patient_id, r_sex, r_dept, r_name)  2.VALUES ('222', '411282xxxxxxx1182', '女', '肛肠科', '尘思宇');  3.  4.SELECT * from register where r_patient_id='41128220230304554X WHERE IS_DELETE=0';  5.  6.START TRANSACTION;  7.BEGIN;  8.UPDATE patient SET p_name = '病人1' WHERE p_atient_id = '41128220230304554X AND IS_DELETE=0;  9.UPDATE register SET r_name = '病人1' WHERE r_patient_id = '41128220230304554X' AND;  10.IS_DELETE=0;  11.  12.UPDATE  register SET IS_DELETE=1 WHERE r_num='222';  
Java相关事务提交核心代码1.try {2.            //app = new AnnotationConfigApplicationContext(SpringConfiguration.class)3.            //1.获取数据库连接4.            conn = dataSource.getConnection();5.            conn.setAutoCommit(false);6.            //2.预编译sql语句,返回PreparedStatement实例7.            ps = conn.prepareStatement(sql);8.            //3.填充占位符9.            for (int i = 0; i < args.length; i++) {10.                ps.setObject(i + 1, args[i]);11.            }12.            //4.执行sql语句13.            ps.execute();14.            conn.commit();15.            System.out.println("添加记录成功");16.        } catch (Exception e) {17.            conn.rollback();18.            e.printStackTrace();19.        } finally {20.            //5.资源的关闭21.            conn.close();22.        }23.    }
(2)级联操作1.-- 级联操作  2.alter table patient add  3.    constraint patient_register_dept  4.        foreign key(p_atient_id) references register(r_patient_id) on delete cascade;  5.DELETE FROM patient WHERE p_atient_id='41128220230304554X';

6.1.4实现处方的登记管理

1./**2.         * 测试增添数据3.         */4.        String sql1 = "INSERT INTO recipel(id,doctor_id,drug_id,count,patient_name) VALUES (?,?,?,?,?);";5.        modify.update(sql1,1,"001", "100023", "2盒","病人1");

6.1.5实现收费管理;

6.2 视图

创建视图查询各种药品的库存总数;

1.SELECT drug_name,sum(drug_quantity) FROM drug_view GROUP BY drug_name ;  

6.3 触发器

药品出库操作

1.-- 创建触发器,当药品入库、出库时自动修改库存;  2.# 药品出库操作  3.delimiter $$ -- 自定义结束符号  4.create trigger recipel_update  5.    before insert  6.    on recipel  7.    for EACH ROW  8.BEGIN  9.    SELECT @quantity=drug_quantity into @str  10.    FROM drugs WHERE NEW.drug_id = drugs.drug_id;  11.    IF @quantity <= 0 || NEW.count > @quantity THEN  12.        SIGNAL SQLSTATE '02000' SET MESSAGE_TEXT = 'Warning: 药品数量为零!';  13.    ELSE  14.        UPDATE drugs SET drug_quantity = drug_quantity - NEW.count WHERE drug_id=NEW.drug_id AND IS_dELETE=0;  15.    end if;  16.end  17.$$ -- 自定义触发器结束  18.delimiter ;   

插入前

插入后

药品入库操作

插入前

插入后

6.4 存储过程

创建存储过程统计某段时间内,各科室的就诊人数和输入情况;

 #存储过程drop procedure count_people_date;DELIMITER $$CREATE PROCEDURE count_people_date(#IN @begin_date datetime,  这样写是错误的    IN begin_date datetime,    IN end_date datetime    )BEGIN    SELECT r_dept '科室',count(*) '问诊人数'    FROM register    WHERE update_time BETWEEN begin_date AND end_date AND is_delete=0    GROUP BY r_dept ;end $$DELIMITER ;CALL count_people_date('2021-12-04','2021-12-05');


7.基准测试

压力测试:

时间延迟测试:

8.总结

对于本次课程设计,考虑到做事就要做完美,做一次了,那就给他开源,设计,优化,调试,测试,对比都做一遍.当然在进行数据库操作的时候,难度最大的有
1.触发器 由于我使用了mysql,这与sql service有着高度的隔离.这部分内容是完全不一样的.做迁移时耗费了很大力气.有很多问题摸索了很久,有些问题是stackoverflow,百度,csdn都解决不了的.比如我使用了update触发器,但是在触发器中执行插入操作,总是插不进去!困扰了我很久,寻访各个dba群中大佬,都无能为力.总之,有些是耗费很长时间都无法解决的,很挫败.但虽然挫败,但我也收获了很多,对于基本的sql操作,以及mysql,sql service都有了深刻认识.

2.新思想 同时在设计数据库的过程中,也触发了很多新思想,有了新思想,眼前豁然开朗,逻辑删除思想解决了一对多,牵一发而动全身的难题.也保证了数据的永久存储.

3.Linux下的数据时延测试. 本以为靠两个shell自动化脚本很容易做.但是错误也是频繁发生.但在解决问题的过程中,我了解到了sh -x 脚本调试.这让我捕获了错误.完成了数据采集,以及qbs在时间维度的测试.

9.参考文献

[1]高性能MySQL:第3版/(美)Schwartz,B.(美)Zaitsev,P.,(美)Tkachenko,V.著;宁海元等译.-北京:电子工业出版社,2013.5 书名原文:High Performance MySQL,Third Edition.
[2]数据库系统概论/王珊,萨师煊编著.—5版.—北京:高等教育出版社,2014.9 ISBN 978-7-04-040664-1
[3]java开发手册社区开发者集体智慧的结晶-(华山版)v1.5.0.-杭州:阿里巴巴,2019.06

写在最后

开源连接—–>>>点击此处

时间更新次数
2021-12-10第一次更新,更新优化了部分表和github仓库的表