当前位置:首页 > 休闲

javaweb订餐系统分页增删改查

做JavaWeb订餐系统,餐系查绕不开分页增删改查。统分很多人一上来就想着把功能堆全,页增结果代码写到后面自己都看不懂。删改我的餐系查做法是先把分页这块硬骨头啃下来,因为菜单展示、统分订单列表、页增用户管理,删改哪个都离不开它。餐系查

分页的统分核心就两个参数:当前页码和每页条数。前端传过来,页增后端拼SQL。删改MySQL用LIMIT,餐系查Oracle得套两层ROWNUM,统分SQL Server又是页增另一套。我习惯在DAO层写个基类,把分页逻辑抽出来。比如这样:

public List<Dish> findDishByPage(int page, int size) {  String sql = "SELECT * FROM dish LIMIT ?, ?"; return jdbcTemplate.query(sql, new Object[]{ (page-1)*size, size}, new DishRowMapper()); }

别小看这个(page-1)*size,新手最容易在这里翻车。有次帮学弟调代码,他传进来的page从0开始算,结果第一页永远少一条数据。查了半天才发现前端分页插件默认从1开始。

增删改查里,查是最简单的,也是最容易写烂的。我见过一个订餐系统的菜品查询,把分类、价格区间、是否辣、是否推荐全塞进一个方法里,if-else写了八十多行。后来我改成动态拼SQL,用MyBatis的<if>标签,清爽多了。删和改要注意事务,特别是订单模块。用户下单要同时写订单表和订单详情表,还得扣库存。这三个操作必须在一个事务里,不然库存扣了订单没生成,或者订单生成了库存没动,都得出事。

增删改查的“增”在订餐系统里有个坑:菜品图片上传。很多人只存个文件名到数据库,结果部署到服务器上图片路径全挂。我的做法是把图片存到项目外的绝对路径,数据库只存相对路径,前端通过配置的虚拟路径访问。这样换服务器迁移数据时,图片不会丢。

分页查询的返回结果别只给个List。前端需要知道总条数、总页数,不然分页组件没法渲染。我一般封装一个PageResult类:

public class PageResult<T> {  private List<T> data; private long total; private int page; private int size; // getter/setter省略 }

总条数用SELECT COUNT(*)单独查一次。有人想用SQL_CALC_FOUND_ROWS,MySQL 8.0已经废弃了,别踩这个坑。还有个细节:分页查询的排序字段一定要固定,比如按id倒序。不然翻到第二页可能看到第一页出现过的数据,因为MySQL不保证默认排序稳定。

删数据我倾向于软删除。订餐系统的订单、菜品,物理删了以后对账都找不到记录。加个is_deleted字段,查询时带上WHERE is_deleted=0。唯一索引要注意,比如菜品名称不能重复,软删除后名称还占着,得把唯一索引改成(name, is_deleted)联合索引。

改数据最怕并发。两个管理员同时改同一个菜品价格,后提交的覆盖先提交的。乐观锁加个version字段,更新时带上WHERE version=#{ version},影响行数为0就提示用户刷新重试。订餐系统里库存扣减也用这招,比悲观锁轻量。

最后说个真实案例。之前接手一个订餐系统,分页查询每页20条,但前端传的size参数没做上限校验。有人传了size=100000,数据库直接卡死。后来我在Controller层加了@Max(100)注解,问题解决。分页参数校验这种小事,不注意就是生产事故。

代码写多了就明白,增删改查看着简单,每个环节都有暗坑。分页不是拼个LIMIT就完事,增删改也不是调个Mapper方法就收工。把边界情况想清楚,比多写两百行代码管用。

分享到: