Java根据指定date类型字段获取该字段前七天的数量变化

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

@Override
public List<Integer> getLast7DayCount(String columnName) {
    Calendar calendar = Calendar.getInstance();
    // 设置开始时间为六天前的00:00:00
    calendar.set(Calendar.HOUR_OF_DAY, 0);
    calendar.set(Calendar.MINUTE, 0);
    calendar.set(Calendar.SECOND, 0);
    calendar.set(Calendar.MILLISECOND, 0);
    calendar.add(Calendar.DAY_OF_YEAR, -6); // 六天前
    Date startDate = calendar.getTime(); // 获取六天前的开始时间

    // 设置结束时间为今天的23:59:59
    calendar = Calendar.getInstance(); // 重新获取当前时间
    calendar.set(Calendar.HOUR_OF_DAY, 23);
    calendar.set(Calendar.MINUTE, 59);
    calendar.set(Calendar.SECOND, 59);
    calendar.set(Calendar.MILLISECOND, 999); // 包括到999毫秒
    Date endDate = calendar.getTime(); // 获取今天的结束时间

    System.out.println("Start Date: " + startDate);
    System.out.println("End Date: " + endDate);

    // 从开始时间到结束时间查询用户
    List<User> usersInLast7Days = UserMapper.findUsersByTimeRange(columnName, startDate, endDate);

    // 统计每天的新增数量
    List<Integer> newCounts = new ArrayList<>();

    // 重新设置 calendar 以计算每一天
    calendar.setTime(startDate);
    for (int i = 0; i < 7; i++) {
        // 计算当天的开始和结束时间
        long startOfDay = calendar.getTimeInMillis(); // 当天 00:00:00
        long endOfDay = startOfDay + 24 * 60 * 60 * 1000; // +24小时,确保到下一个零点
        
        // 计算当天新增用户数量
        int count = (int) usersInLast7Days.stream()
                .filter(user -> {
                    try {
                        // 构造 getter 方法名
                        String methodName = "get" + capitalize(columnName);
                        Method method = user.getClass().getMethod(methodName);
                        // 获取字段值并进行时间比较
                        Date dateValue = (Date) method.invoke(user);
                        return dateValue != null && (dateValue.getTime() >= startOfDay) && (dateValue.getTime() < endOfDay);
                    } catch (Exception e) {
                        e.printStackTrace();
                        return false; // 如果发生异常,默认过滤掉该记录
                    }
                })
                .count();

        newCounts.add(count);

        // 打印对应日期和新增用户数量
        System.out.printf("Date: %s, New Immit: %d%n", calendar.getTime(), count);

        // 前移 calendar 到下一天
        calendar.add(Calendar.DAY_OF_YEAR, 1);
    }

    return newCounts;
}

// 辅助方法:首字母大写
private String capitalize(String str) {
    if (str == null || str.isEmpty()) {
        return str;
    }
    return str.substring(0, 1).toUpperCase() + str.substring(1);
}

代码讲解

  1. 反射调用法:在 filter 方法中,通过调用 user.getClass().getMethod(methodName) 获取动态生成的 getter 方法。通过反射使用 invoke 方法调用该 getter。

  2. 首字母大写转换: capitalize 方法将传入的字符串的首字母变为大写,以符合 Java 的 getter 方法命名规则(如 createTime 的 getter 是 getCreateTime)。

  3. 异常处理:在反射调用过程中可能会抛出异常,因此需要使用 try-catch 块来捕获并处理。例如,方法未找到、反射失败等情况。

使用

您可以将 getLast7DayCount("createTime") 作为调用,系统将根据字段名动态调用指定的 getter 方法,从而实现查询指定 date 字段前七天的增量。

确保 createTime 是 User 类中的一个字段,并且有相应的 getter 方法供反射访问。

2. Mapper 接口

import org.apache.ibatis.annotations.Param;
import java.util.Date;
import java.util.List;

public interface UserMapper {
    List<User> findUsersByTimeRange(@Param("columnName") String columnName, @Param("startDate") Date startDate, @Param("endDate") Date endDate);
}

2. Mapper XML 文件

接下来,在 Mapper XML 文件中,您需要使用 <choose><when> 和 <otherwise> 标签来动态构造 SQL 查询。以下是一个示例,假设您只需要处理 createTime 和 destroyTime 两个字段:

<mapper namespace="com.yourpackage.UserMapper">

    <select id="findUsersByTimeRange" resultType="com.modules.usermanage.po.User">
        SELECT * FROM userinfo 
        WHERE 
        <choose>
            <when test="columnName == 'createTime'">
                createTime >= #{startDate} AND createTime &lt;= #{endDate}
            </when>
            <when test="columnName == 'destroyTime'">
                destroyTime >= #{startDate} AND destroyTime &lt;= #{endDate}
            </when>
            <otherwise>
                -- 处理未定义的字段名情况
                1 = 0 -- 这将永远返回空结果
            </otherwise>
        </choose>
    </select>

</mapper>

代码解释

  1. 动态 SQL:使用 <choose> 标签来根据 columnName 的值选择不同的 SQL 片段。每个 <when> 标签对应一个可能的字段名,并定义相应的 SQL 条件。

  2. 默认情况处理:使用 <otherwise> 来处理未定义字段的情况。这里的 1 = 0 语句将确保查询不会返回任何结果,避免 SQL 错误。

  3. 字段名:在 columnName 传入的值必须与数据库中的字段名一致(如 createTime 或 destroyTime)。如果需要支持更多字段,可以继续添加更多的 <when> 标签。

 

使用示例

当您调用 findUsersByTimeRange("createTime", startDate, endDate) 时,MyBatis 将根据 columnName 的值动态构造 SQL 查询,并返回符合条件的用户列表。

注意事项

  • 确保传入的 columnName 仅包含安全的字段名,避免 SQL 注入风险。通常,您可以通过在程序中进行验证来确保字段名的安全性。
  • 如果需要查询的字段较多,可能需要考虑其他方式来简化代码,如使用 SQL 生成器或 ORM 框架。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

打'更人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值