基于SSH框架的药品信息管理系统 - 源码深度解析

JavaJavaScriptSSH框架HTMLCSSMySQLJSP+Servlet
2026-02-196 浏览

文章摘要

本项目是一款基于SSH(Struts2 + Spring + Hibernate)集成框架开发的药品信息管理系统,旨在为医院药房、药品流通企业及医疗机构提供一体化的药品数据管理解决方案。系统核心解决了传统人工记录或信息孤岛导致的药品信息更新不及时、库存数据不准确、查询效率低下等管理痛点,通过数字化手...

在医药行业信息化快速发展的背景下,传统依赖人工台账和Excel表格的药品管理模式日益暴露出数据孤岛、更新滞后、差错率高等痛点。一款基于SSH(Struts2 + Spring + Hibernate)集成框架的药品信息管理系统应运而生,该系统被命名为“医药物联数据中枢”,旨在为医院药房、药品流通企业及医疗机构提供一体化的药品数据管理解决方案。系统通过数字化手段将药品的入库、出库、库存、有效期及基础信息进行集中化、规范化管理,显著提升了工作效率并降低了人为差错风险。

系统采用经典的三层架构设计。表现层使用Struts2框架处理用户交互,通过Action类接收前端请求并调用业务逻辑;业务层基于Spring框架的IoC容器进行Bean管理,利用声明式事务管理确保药品库存变更等核心操作的数据一致性;持久层则依托Hibernate实现对象关系映射(ORM),将药品、库存、供应商等实体类与数据库表映射,简化了数据持久化操作。

在数据库设计方面,系统选用MySQL作为数据存储引擎,通过五张核心表构建了完整的业务数据模型。其中tb_medicine(药品表)作为系统的核心数据载体,其结构设计体现了严谨的业务逻辑:

CREATE TABLE `tb_medicine` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增主键',
  `medNo` varchar(255) NOT NULL COMMENT '药品编号',
  `name` varchar(255) NOT NULL COMMENT '名字',
  `factoryAdd` varchar(255) DEFAULT NULL COMMENT '厂家地址',
  `description` longtext DEFAULT NULL COMMENT '描述',
  `price` double NOT NULL COMMENT '价格',
  `medCount` int(11) DEFAULT NULL COMMENT '药品数量',
  `reqCount` int(11) DEFAULT NULL COMMENT '需求数量',
  `photoPath` varchar(255) DEFAULT NULL COMMENT '图片路径',
  `categoryId` int(11) DEFAULT NULL COMMENT '分类ID',
  PRIMARY KEY (`id`),
  UNIQUE KEY `medNo` (`medNo`),
  KEY `FKCB73D4EB5CE1611D` (`categoryId`),
  CONSTRAINT `FKCB73D4EB5CE1611D` FOREIGN KEY (`categoryId`) REFERENCES `tb_category` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='药品表'

该表设计中的medNo字段设置了唯一索引,确保药品编号的唯一性;categoryId外键关联分类表,建立了药品与分类的层级关系;medCountreqCount分别记录实际库存和需求数量,为库存预警功能提供数据支撑。

销售明细表tb_selldetail的设计同样体现了业务完整性:

CREATE TABLE `tb_selldetail` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增主键',
  `sellName` varchar(255) NOT NULL COMMENT '销售名称',
  `sellPrice` double NOT NULL COMMENT '销售价格',
  `sellCount` int(11) NOT NULL COMMENT '销售数量',
  `sellTime` datetime NOT NULL COMMENT '销售时间',
  `medid` int(11) DEFAULT NULL COMMENT '药品ID',
  `userid` int(11) DEFAULT NULL COMMENT '用户ID',
  PRIMARY KEY (`id`),
  KEY `FK56C63894DD16E7A7` (`medid`),
  KEY `FK56C63894822F277` (`userid`),
  CONSTRAINT `FK56C63894822F277` FOREIGN KEY (`userid`) REFERENCES `tb_user` (`id`),
  CONSTRAINT `FK56C63894DD16E7A7` FOREIGN KEY (`medid`) REFERENCES `tb_medicine` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='销售明细表'

该表通过mediduserid两个外键分别关联药品表和用户表,完整记录了每笔销售业务的详细信息,为销售统计和业绩分析提供了数据基础。

在实体模型设计上,系统采用面向对象的方式封装业务数据。药品实体类Medicine的Hibernate映射配置如下:

@Entity
@Table(name = "tb_medicine")
public class Medicine implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    
    @Column(name = "medNo", unique = true, nullable = false)
    private String medicineNumber;
    
    @Column(nullable = false)
    private String name;
    
    private String factoryAdd;
    
    @Lob
    private String description;
    
    @Column(nullable = false)
    private Double price;
    
    private Integer medCount;
    
    private Integer reqCount;
    
    private String photoPath;
    
    @ManyToOne
    @JoinColumn(name = "categoryId")
    private Category category;
    
    // 省略getter/setter方法
}

对应的DAO层实现采用Hibernate Template进行数据访问,基础CRUD操作封装在MedicineDao类中:

@Repository
public class MedicineDao extends HibernateDaoSupport {
    
    @Autowired
    public void setSessionFactory0(SessionFactory sessionFactory) {
        super.setSessionFactory(sessionFactory);
    }
    
    public void save(Medicine medicine) {
        getHibernateTemplate().save(medicine);
    }
    
    public void update(Medicine medicine) {
        getHibernateTemplate().update(medicine);
    }
    
    public void delete(Integer id) {
        Medicine medicine = getHibernateTemplate().get(Medicine.class, id);
        if (medicine != null) {
            getHibernateTemplate().delete(medicine);
        }
    }
    
    public Medicine findById(Integer id) {
        return getHibernateTemplate().get(Medicine.class, id);
    }
    
    public List<Medicine> findAll() {
        return (List<Medicine>) getHibernateTemplate().find("from Medicine");
    }
}

业务逻辑层通过Spring的声明式事务管理确保数据一致性,MedicineService类封装了复杂的业务规则:

@Service
@Transactional
public class MedicineService {
    
    @Autowired
    private MedicineDao medicineDao;
    
    @Transactional(readOnly = true)
    public List<Medicine> getMedicinesByCategory(Integer categoryId) {
        String hql = "from Medicine m where m.category.id = ?";
        return medicineDao.find(hql, categoryId);
    }
    
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void updateStock(Integer medicineId, Integer quantity) {
        Medicine medicine = medicineDao.findById(medicineId);
        if (medicine != null) {
            Integer currentStock = medicine.getMedCount();
            medicine.setMedCount(currentStock + quantity);
            medicineDao.update(medicine);
        }
    }
    
    public List<Medicine> getLowStockMedicines() {
        String hql = "from Medicine m where m.medCount < m.reqCount";
        return medicineDao.find(hql);
    }
}

表现层通过Struts2 Action处理用户请求,MedicineAction类负责接收前端参数并调用业务逻辑:

public class MedicineAction extends ActionSupport {
    private Medicine medicine;
    private List<Medicine> medicineList;
    private Integer categoryId;
    
    @Autowired
    private MedicineService medicineService;
    
    public String list() {
        medicineList = medicineService.findAll();
        return SUCCESS;
    }
    
    public String save() {
        medicineService.save(medicine);
        return SUCCESS;
    }
    
    public String findByCategory() {
        if (categoryId != null) {
            medicineList = medicineService.getMedicinesByCategory(categoryId);
        }
        return SUCCESS;
    }
    
    // 省略getter/setter方法
}

系统核心功能模块包括药品信息管理、库存管理、销售管理和统计分析。药品信息管理模块提供完整的药品档案维护功能,支持药品信息的增删改查操作。

药品信息管理

库存管理模块实现实时库存监控和预警功能,通过HQL查询实现库存状态分析:

public class InventoryService {
    
    public List<Object[]> getStockStatusReport() {
        String hql = "select m.name, m.medCount, m.reqCount, " +
                    "case when m.medCount < m.reqCount then '缺货' " +
                    "when m.medCount < m.reqCount * 1.2 then '预警' " +
                    "else '正常' end as status " +
                    "from Medicine m";
        return medicineDao.findByHQL(hql);
    }
    
    public List<Medicine> getExpiringMedicines(Date startDate, Date endDate) {
        String hql = "from Medicine m where m.expireDate between ? and ?";
        return medicineDao.find(hql, startDate, endDate);
    }
}

销售管理模块记录每笔销售业务,确保库存数据的实时更新:

销售明细

采购管理模块根据库存预警自动生成采购计划:

采购管理

统计分析模块提供多维度数据展示,包括销售排名和分类统计:

public class StatisticsService {
    
    public List<Object[]> getSalesRanking(Date startDate, Date endDate) {
        String hql = "select sd.medicine.name, sum(sd.sellCount), sum(sd.sellCount * sd.sellPrice) " +
                    "from SellDetail sd where sd.sellTime between ? and ? " +
                    "group by sd.medicine.id, sd.medicine.name " +
                    "order by sum(sd.sellCount) desc";
        return sellDetailDao.find(hql, startDate, endDate);
    }
    
    public List<Object[]> getCategoryStatistics() {
        String hql = "select c.name, count(m.id), sum(m.medCount) " +
                    "from Category c left join c.medicines m " +
                    "group by c.id, c.name";
        return categoryDao.findByHQL(hql);
    }
}

销售排名

分类统计

系统在用户权限管理方面采用基于角色的访问控制,UserAction处理用户登录和权限验证:

public class UserAction extends ActionSupport {
    private String username;
    private String password;
    private User user;
    
    public String login() {
        User existUser = userService.findByUsernameAndPassword(username, password);
        if (existUser != null) {
            ActionContext.getContext().getSession().put("user", existUser);
            return SUCCESS;
        } else {
            addActionError("用户名或密码错误");
            return INPUT;
        }
    }
    
    public String logout() {
        ActionContext.getContext().getSession().remove("user");
        return SUCCESS;
    }
}

在数据持久化方面,系统通过Hibernate的缓存机制提升查询性能。二级缓存配置在ehcache.xml中定义:

<cache name="com.example.Medicine"
       maxElementsInMemory="1000"
       eternal="false"
       timeToIdleSeconds="300"
       timeToLiveSeconds="600"
       overflowToDisk="false" />

Spring的配置文件applicationContext.xml中集成了Hibernate和事务管理:

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
            <prop key="hibernate.show_sql">true</prop>
            <prop key="hibernate.format_sql">true</prop>
            <prop key="hibernate.cache.use_second_level_cache">true</prop>
            <prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop>
        </props>
    </property>
    <property name="mappingResources">
        <list>
            <value>com/example/Medicine.hbm.xml</value>
            <value>com/example/Category.hbm.xml</value>
        </list>
    </property>
</bean>

<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory"/>
</bean>

<tx:annotation-driven transaction-manager="transactionManager"/>

系统在性能优化方面采取了多项措施。数据库连接池配置使用C3P0:

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
    <property name="driverClass" value="com.mysql.jdbc.Driver"/>
    <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/drug_db?useUnicode=true&amp;characterEncoding=utf8"/>
    <property name="user" value="root"/>
    <property name="password" value="123456"/>
    <property name="maxPoolSize" value="50"/>
    <property name="minPoolSize" value="5"/>
    <property name="initialPoolSize" value="10"/>
    <property name="maxIdleTime" value="300"/>
</bean>

对于未来优化方向,系统可以考虑以下几个方面的改进:引入Redis缓存热点数据提升查询性能,实现药品批次管理和先进先出策略,开发移动端应用支持移动盘点,集成条形码或二维码扫描功能简化操作流程,以及增加数据可视化大屏展示实时经营数据。

在批次管理方面,可以扩展tb_medicine表结构,增加批次相关信息:

ALTER TABLE `tb_medicine` 
ADD COLUMN `batchNo` VARCHAR(50) COMMENT '批次号',
ADD COLUMN `productionDate` DATE COMMENT '生产日期',
ADD COLUMN `expireDate` DATE COMMENT '失效日期',
ADD INDEX `idx_batch_expire` (`batchNo`, `expireDate`);

移动端接口可以通过Spring MVC实现RESTful API:

@RestController
@RequestMapping("/api/medicine")
public class MedicineRestController {
    
    @Autowired
    private MedicineService medicineService;
    
    @GetMapping("/{id}")
    public ResponseEntity<Medicine> getMedicine(@PathVariable Integer id) {
        Medicine medicine = medicineService.findById(id);
        return ResponseEntity.ok(medicine);
    }
    
    @PostMapping("/scan")
    public ResponseEntity<Medicine> scanMedicine(@RequestParam String barcode) {
        Medicine medicine = medicineService.findByBarcode(barcode);
        return ResponseEntity.ok(medicine);
    }
}

数据可视化大屏可以通过ECharts集成展示关键指标:

function initSalesChart() {
    var chart = echarts.init(document.getElementById('sales-chart'));
    $.get('/api/statistics/sales-trend', function(data) {
        chart.setOption({
            title: { text: '销售趋势分析' },
            tooltip: { trigger: 'axis' },
            xAxis: { data: data.dates },
            yAxis: { type: 'value' },
            series: [{ name: '销售额', type: 'line', data: data.amounts }]
        });
    });
}

系统通过严谨的架构设计和完善的功能模块,为医药行业提供了可靠的数字化管理解决方案。基于SSH框架的技术选型确保了系统的稳定性和可维护性,而模块化的设计则为后续功能扩展奠定了良好基础。

本文关键词
SSH框架药品信息管理系统Struts2SpringHibernateMySQL

上下篇

上一篇
没有更多文章
下一篇
没有更多文章