规模化生猪养殖场管理系统是当前畜牧业数字化转型的典型应用场景。随着养殖场规模扩大,传统人工记录方式已无法满足生产管理需求。我在参与某大型养殖企业信息化改造时发现,他们每天需要处理超过2000头生猪的饲料投喂、免疫接种、生长监测等数据,纸质台账经常出现遗漏和错误。
基于SpringBoot的养殖管理系统能有效解决以下痛点:
这个毕设项目特别适合计算机相关专业学生选择,因为它:
后端框架选择SpringBoot而非SSM的原因:
前端方案建议:
数据库设计要点:
sql复制CREATE TABLE `swine` (
`id` int NOT NULL AUTO_INCREMENT,
`ear_tag` varchar(20) COMMENT '耳标号',
`pen_id` int COMMENT '栏舍编号',
`breed` varchar(50) COMMENT '品种',
`birth_date` date COMMENT '出生日期',
`father_id` int COMMENT '父代ID',
`mother_id` int COMMENT '母代ID',
`status` tinyint COMMENT '状态(1:在养 2:出栏 3:死亡)',
PRIMARY KEY (`id`),
UNIQUE KEY `idx_ear_tag` (`ear_tag`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
java复制// 日增重计算算法
public BigDecimal calculateDailyGain(Swine swine, Date startDate, Date endDate) {
List<WeightRecord> records = weightRecordRepo.findBySwineAndRecordDateBetween(
swine, startDate, endDate);
if(records.size() < 2) return BigDecimal.ZERO;
BigDecimal startWeight = records.get(0).getWeight();
BigDecimal endWeight = records.get(records.size()-1).getWeight();
long days = ChronoUnit.DAYS.between(
startDate.toInstant(), endDate.toInstant());
return endWeight.subtract(startWeight)
.divide(new BigDecimal(days), 2, RoundingMode.HALF_UP);
}
养殖场通常按批次管理生猪,核心数据结构:
java复制@Entity
public class Batch {
@Id @GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
@Column(unique=true)
private String batchNo; // 批次号规则:年份+序号 如2023001
@Temporal(TemporalType.DATE)
private Date inDate; // 入栏日期
private Integer source; // 来源(1:自繁 2:外购)
@OneToMany(mappedBy="batch")
private List<Swine> swines;
// 省略getter/setter
}
批次操作特别注意:
基于不同生长阶段的营养需求动态计算:
java复制public FeedFormula calculateFormula(Swine swine) {
int daysOld = getDaysOld(swine);
GrowthPhase phase = phaseService.determinePhase(daysOld);
FeedFormula formula = new FeedFormula();
formula.setCorn(phase.getBaseCorn() * adjustByWeight(swine));
formula.setSoybeanMeal(phase.getBaseSoybean() * adjustByWeight(swine));
// 其他原料计算...
return formula;
}
private double adjustByWeight(Swine swine) {
// 根据体重偏离标准值的百分比调整系数
double standardWeight = growthCurve.getStandardWeight(swine.getDaysOld());
return swine.getWeight() / standardWeight;
}
场区工作人员常用功能移动化实现:
java复制// 错误做法:一次性加载所有实体
List<Swine> swines = swineRepo.findByBatch(batch);
// 正确做法:使用流式处理
try(Stream<Swine> stream = swineRepo.streamByBatch(batch)) {
stream.forEach(swine -> {
// 处理单条记录
exportWriter.write(convertToCsv(swine));
});
}
java复制@Cacheable(value = "growthCurve", key = "#batchId")
public GrowthCurve calculateCurve(Long batchId) {
// 复杂计算过程...
}
java复制@PostMapping("/swines")
public ResponseEntity<?> createSwine(@Valid @RequestBody Swine swine) {
if(swineRepo.existsByEarTag(swine.getEarTag())) {
throw new BusinessException("耳标号"+swine.getEarTag()+"已存在");
}
// ...其他逻辑
}
java复制public void checkVaccineConflict(VaccinePlan newPlan) {
List<VaccinePlan> existing = planRepo.findBySwineAndDateBetween(
newPlan.getSwine(),
newPlan.getDate().minusDays(7),
newPlan.getDate().plusDays(7));
if(!existing.isEmpty()) {
throw new VaccineConflictException("7天内已安排其他疫苗");
}
}
sql复制-- 料肉比分析SQL示例
SELECT
batch_no,
SUM(feed_amount) / SUM(sale_weight) AS fcr
FROM
batch_feed_records
JOIN
batch_sales ON batch_feed_records.batch_id = batch_sales.batch_id
GROUP BY
batch_no
ORDER BY
fcr ASC;
java复制@Bean
public CommandLineRunner initTestData(SwineRepository repo) {
return args -> {
Faker faker = new Faker();
for(int i=0; i<100; i++) {
Swine swine = new Swine();
swine.setEarTag("2023"+String.format("%04d", i));
swine.setBreed(faker.options().option("长白","大白","杜洛克"));
// ...其他字段
repo.save(swine);
}
};
}
这个项目我在实际开发中遇到最棘手的问题是批次混养时的免疫计划冲突检测,最终通过引入"免疫禁忌期"概念解决了问题。建议在开发时多与养殖场技术员沟通,了解真实工作流程,比如他们实际使用的耳标编号规则就和教科书上的标准有很大差异。