From 9dab03231f481b5667832ef2924fd5557bcf374f Mon Sep 17 00:00:00 2001 From: yuejiajun <1530620364@qq.com> Date: Tue, 30 Sep 2025 12:24:05 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=EF=BC=8C=E6=97=B6=E9=97=B4?= =?UTF-8?q?=E9=97=AE=E9=A2=98=E8=A7=A3=E5=86=B3=E4=BA=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../demo/common/base/BaseListener.java | 4 ++ .../{ => startup}/defaults/StartupOutput.java | 2 +- .../executor/StartupOutputExecutor.java | 2 +- .../startup}/output/ApiDocOutput.java | 2 +- .../{ => base/startup}/output/H2Output.java | 2 +- .../config/{ => database}/CacheConfig.java | 2 +- .../initializer}/DatabaseInitializer.java | 3 +- .../real}/H2DataSourceConfig.java | 2 +- .../real}/SqliteDataSourceConfig.java | 2 +- .../orm/handler/SqliteDateTypeHandler.java | 69 +++++++++++++++++++ .../config/orm/listener/FlexListener.java | 56 +++++++++++++++ .../demo/common/domain/BaseEntity.java | 18 ++++- .../common/typography/BaseServiceImpl.java | 4 +- .../demo/parser/entity/FileRecordEntity.java | 3 +- .../demo/parser/entity/MapperRuleEntity.java | 3 +- .../demo/parser/entity/ParseRuleEntity.java | 3 +- 16 files changed, 161 insertions(+), 16 deletions(-) create mode 100644 src/main/java/com/example/demo/common/base/BaseListener.java rename src/main/java/com/example/demo/common/base/{ => startup}/defaults/StartupOutput.java (93%) rename src/main/java/com/example/demo/common/{ => base/startup}/executor/StartupOutputExecutor.java (97%) rename src/main/java/com/example/demo/common/{ => base/startup}/output/ApiDocOutput.java (96%) rename src/main/java/com/example/demo/common/{ => base/startup}/output/H2Output.java (98%) rename src/main/java/com/example/demo/common/config/{ => database}/CacheConfig.java (98%) rename src/main/java/com/example/demo/common/config/{ => database/initializer}/DatabaseInitializer.java (93%) rename src/main/java/com/example/demo/common/config/{ => database/real}/H2DataSourceConfig.java (97%) rename src/main/java/com/example/demo/common/config/{ => database/real}/SqliteDataSourceConfig.java (97%) create mode 100644 src/main/java/com/example/demo/common/config/orm/handler/SqliteDateTypeHandler.java create mode 100644 src/main/java/com/example/demo/common/config/orm/listener/FlexListener.java diff --git a/src/main/java/com/example/demo/common/base/BaseListener.java b/src/main/java/com/example/demo/common/base/BaseListener.java new file mode 100644 index 0000000..1815619 --- /dev/null +++ b/src/main/java/com/example/demo/common/base/BaseListener.java @@ -0,0 +1,4 @@ +package com.example.demo.common.base; + +public interface BaseListener { +} diff --git a/src/main/java/com/example/demo/common/base/defaults/StartupOutput.java b/src/main/java/com/example/demo/common/base/startup/defaults/StartupOutput.java similarity index 93% rename from src/main/java/com/example/demo/common/base/defaults/StartupOutput.java rename to src/main/java/com/example/demo/common/base/startup/defaults/StartupOutput.java index f9db7c0..5db5cb5 100644 --- a/src/main/java/com/example/demo/common/base/defaults/StartupOutput.java +++ b/src/main/java/com/example/demo/common/base/startup/defaults/StartupOutput.java @@ -1,4 +1,4 @@ -package com.example.demo.common.base.defaults; +package com.example.demo.common.base.startup.defaults; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; diff --git a/src/main/java/com/example/demo/common/executor/StartupOutputExecutor.java b/src/main/java/com/example/demo/common/base/startup/executor/StartupOutputExecutor.java similarity index 97% rename from src/main/java/com/example/demo/common/executor/StartupOutputExecutor.java rename to src/main/java/com/example/demo/common/base/startup/executor/StartupOutputExecutor.java index 6df8732..92f19c4 100644 --- a/src/main/java/com/example/demo/common/executor/StartupOutputExecutor.java +++ b/src/main/java/com/example/demo/common/base/startup/executor/StartupOutputExecutor.java @@ -1,4 +1,4 @@ -package com.example.demo.common.executor; +package com.example.demo.common.base.startup.executor; import com.example.demo.common.base.BaseStartupOutput; import lombok.extern.slf4j.Slf4j; diff --git a/src/main/java/com/example/demo/common/output/ApiDocOutput.java b/src/main/java/com/example/demo/common/base/startup/output/ApiDocOutput.java similarity index 96% rename from src/main/java/com/example/demo/common/output/ApiDocOutput.java rename to src/main/java/com/example/demo/common/base/startup/output/ApiDocOutput.java index 6e071ed..cb8495e 100644 --- a/src/main/java/com/example/demo/common/output/ApiDocOutput.java +++ b/src/main/java/com/example/demo/common/base/startup/output/ApiDocOutput.java @@ -1,4 +1,4 @@ -package com.example.demo.common.output; +package com.example.demo.common.base.startup.output; import com.example.demo.common.base.BaseStartupOutput; import lombok.extern.slf4j.Slf4j; diff --git a/src/main/java/com/example/demo/common/output/H2Output.java b/src/main/java/com/example/demo/common/base/startup/output/H2Output.java similarity index 98% rename from src/main/java/com/example/demo/common/output/H2Output.java rename to src/main/java/com/example/demo/common/base/startup/output/H2Output.java index 786bbea..169dd85 100644 --- a/src/main/java/com/example/demo/common/output/H2Output.java +++ b/src/main/java/com/example/demo/common/base/startup/output/H2Output.java @@ -1,4 +1,4 @@ -package com.example.demo.common.output; +package com.example.demo.common.base.startup.output; import com.example.demo.common.base.BaseStartupOutput; import lombok.extern.slf4j.Slf4j; diff --git a/src/main/java/com/example/demo/common/config/CacheConfig.java b/src/main/java/com/example/demo/common/config/database/CacheConfig.java similarity index 98% rename from src/main/java/com/example/demo/common/config/CacheConfig.java rename to src/main/java/com/example/demo/common/config/database/CacheConfig.java index 1525388..e81a830 100644 --- a/src/main/java/com/example/demo/common/config/CacheConfig.java +++ b/src/main/java/com/example/demo/common/config/database/CacheConfig.java @@ -1,4 +1,4 @@ -package com.example.demo.common.config; +package com.example.demo.common.config.database; import com.example.demo.common.constant.GlobalConstants; import org.springframework.context.annotation.Bean; diff --git a/src/main/java/com/example/demo/common/config/DatabaseInitializer.java b/src/main/java/com/example/demo/common/config/database/initializer/DatabaseInitializer.java similarity index 93% rename from src/main/java/com/example/demo/common/config/DatabaseInitializer.java rename to src/main/java/com/example/demo/common/config/database/initializer/DatabaseInitializer.java index e07ca86..1851082 100644 --- a/src/main/java/com/example/demo/common/config/DatabaseInitializer.java +++ b/src/main/java/com/example/demo/common/config/database/initializer/DatabaseInitializer.java @@ -1,10 +1,9 @@ -package com.example.demo.common.config; +package com.example.demo.common.config.database.initializer; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.core.io.ClassPathResource; import org.springframework.jdbc.datasource.init.ScriptUtils; import org.springframework.stereotype.Component; diff --git a/src/main/java/com/example/demo/common/config/H2DataSourceConfig.java b/src/main/java/com/example/demo/common/config/database/real/H2DataSourceConfig.java similarity index 97% rename from src/main/java/com/example/demo/common/config/H2DataSourceConfig.java rename to src/main/java/com/example/demo/common/config/database/real/H2DataSourceConfig.java index 3f1116e..da90cbd 100644 --- a/src/main/java/com/example/demo/common/config/H2DataSourceConfig.java +++ b/src/main/java/com/example/demo/common/config/database/real/H2DataSourceConfig.java @@ -1,4 +1,4 @@ -package com.example.demo.common.config; +package com.example.demo.common.config.database.real; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties; diff --git a/src/main/java/com/example/demo/common/config/SqliteDataSourceConfig.java b/src/main/java/com/example/demo/common/config/database/real/SqliteDataSourceConfig.java similarity index 97% rename from src/main/java/com/example/demo/common/config/SqliteDataSourceConfig.java rename to src/main/java/com/example/demo/common/config/database/real/SqliteDataSourceConfig.java index 45dbda6..16d4c1b 100644 --- a/src/main/java/com/example/demo/common/config/SqliteDataSourceConfig.java +++ b/src/main/java/com/example/demo/common/config/database/real/SqliteDataSourceConfig.java @@ -1,4 +1,4 @@ -package com.example.demo.common.config; +package com.example.demo.common.config.database.real; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties; diff --git a/src/main/java/com/example/demo/common/config/orm/handler/SqliteDateTypeHandler.java b/src/main/java/com/example/demo/common/config/orm/handler/SqliteDateTypeHandler.java new file mode 100644 index 0000000..d6a6e68 --- /dev/null +++ b/src/main/java/com/example/demo/common/config/orm/handler/SqliteDateTypeHandler.java @@ -0,0 +1,69 @@ +package com.example.demo.common.config.orm.handler; + +import org.apache.ibatis.type.JdbcType; +import org.apache.ibatis.type.TypeHandler; + +import java.sql.*; +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * SQLite 日期类型处理器 + * 将 Java Date 对象转换为 SQLite 支持的日期字符串格式 + * + * @author 岳佳君 (2025年09月24日 17:40:34) + * @version 1.0.0 + */ +public class SqliteDateTypeHandler implements TypeHandler { + + private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + + @Override + public void setParameter(PreparedStatement ps, int i, Date parameter, JdbcType jdbcType) throws SQLException { + if (parameter == null) { + ps.setNull(i, Types.VARCHAR); + } else { + // 将 Date 转换为 SQLite 支持的日期字符串格式 + String dateString = DATE_FORMAT.format(parameter); + ps.setString(i, dateString); + } + } + + @Override + public Date getResult(ResultSet rs, String columnName) throws SQLException { + String dateString = rs.getString(columnName); + return parseDate(dateString); + } + + @Override + public Date getResult(ResultSet rs, int columnIndex) throws SQLException { + String dateString = rs.getString(columnIndex); + return parseDate(dateString); + } + + @Override + public Date getResult(CallableStatement cs, int columnIndex) throws SQLException { + String dateString = cs.getString(columnIndex); + return parseDate(dateString); + } + + /** + * 解析日期字符串为 Date 对象 + * + * @param dateString 日期字符串 + * @return Date 对象 + */ + private Date parseDate(String dateString) { + if (dateString == null || dateString.trim().isEmpty()) { + return null; + } + + try { + // 尝试解析 yyyy-MM-dd HH:mm:ss 格式 + return DATE_FORMAT.parse(dateString); + } catch (Exception e) { + // 如果解析失败,尝试其他格式或返回当前时间 + return new Date(); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/example/demo/common/config/orm/listener/FlexListener.java b/src/main/java/com/example/demo/common/config/orm/listener/FlexListener.java new file mode 100644 index 0000000..900bdbf --- /dev/null +++ b/src/main/java/com/example/demo/common/config/orm/listener/FlexListener.java @@ -0,0 +1,56 @@ +package com.example.demo.common.config.orm.listener; + +import com.mybatisflex.annotation.InsertListener; +import com.mybatisflex.annotation.UpdateListener; +import com.example.demo.common.domain.BaseEntity; +import lombok.extern.slf4j.Slf4j; + +import java.util.Date; + +/** + * 时间戳监听器 + * 用于在插入和更新操作时自动设置创建时间和更新时间 + * + * @author 岳佳君 (2025年09月24日 17:40:34) + * @version 1.0.0 + */ +@Slf4j +public class FlexListener implements InsertListener, UpdateListener { + + /** + * 插入前监听 + * 设置创建时间和更新时间 + * + * @param entity 实体对象 + */ + @Override + public void onInsert(Object entity) { + log.info("--------------------------------- onInsert"); + if (entity instanceof BaseEntity baseEntity) { + Date now = new Date(); + + // 设置创建时间(如果为空) + if (baseEntity.getCreatedTime() == null) { + baseEntity.setCreatedTime(now); + } + + // 设置更新时间 + baseEntity.setUpdatedTime(now); + } + } + + /** + * 更新前监听 + * 设置更新时间 + * + * @param entity 实体对象 + */ + @Override + public void onUpdate(Object entity) { + log.info("--------------------------------- onUpdate"); + if (entity instanceof BaseEntity baseEntity) { + // 设置更新时间 + baseEntity.setUpdatedTime(new Date()); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/example/demo/common/domain/BaseEntity.java b/src/main/java/com/example/demo/common/domain/BaseEntity.java index c5baa73..d28aaee 100644 --- a/src/main/java/com/example/demo/common/domain/BaseEntity.java +++ b/src/main/java/com/example/demo/common/domain/BaseEntity.java @@ -1,8 +1,11 @@ package com.example.demo.common.domain; +import com.example.demo.common.config.orm.handler.SqliteDateTypeHandler; +import com.example.demo.common.config.orm.listener.FlexListener; import com.mybatisflex.annotation.Column; import com.mybatisflex.annotation.Id; import com.mybatisflex.annotation.KeyType; +import com.mybatisflex.annotation.Table; import com.mybatisflex.core.keygen.KeyGenerators; import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; @@ -30,6 +33,7 @@ import java.util.Date; @Accessors(chain=true) @NoArgsConstructor @AllArgsConstructor +@Table(value = "demo", onInsert = FlexListener.class, onUpdate = FlexListener.class) public class BaseEntity implements Serializable { @Serial @@ -74,8 +78,13 @@ public class BaseEntity implements Serializable { *
* Column(onInsertValue = "now()") * Column(onInsertValue = "CURRENT_TIMESTAMP") + * Column(onInsertValue = "datetime('now', 'localtime')") */ - @Column(onInsertValue = "CURRENT_TIMESTAMP") +// @Column(onInsertValue = "datetime('now', 'localtime')") + /** + * 创建时间 + */ + @com.mybatisflex.annotation.Column(typeHandler = SqliteDateTypeHandler.class) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") @Schema(description = "创建时间") @@ -93,8 +102,13 @@ public class BaseEntity implements Serializable { *
* Column(onUpdateValue = "now()", onInsertValue = "now()") * Column(onUpdateValue = "CURRENT_TIMESTAMP", onInsertValue = "CURRENT_TIMESTAMP") + * Column(onUpdateValue = "datetime('now', 'localtime')", onInsertValue = "datetime('now', 'localtime')") */ - @Column(onUpdateValue = "CURRENT_TIMESTAMP", onInsertValue = "CURRENT_TIMESTAMP") +// @Column(onUpdateValue = "datetime('now', 'localtime')", onInsertValue = "datetime('now', 'localtime')") + /** + * 更新时间 + */ + @com.mybatisflex.annotation.Column(typeHandler = SqliteDateTypeHandler.class) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") @Schema(description = "更新时间") diff --git a/src/main/java/com/example/demo/common/typography/BaseServiceImpl.java b/src/main/java/com/example/demo/common/typography/BaseServiceImpl.java index 2025d53..7421621 100644 --- a/src/main/java/com/example/demo/common/typography/BaseServiceImpl.java +++ b/src/main/java/com/example/demo/common/typography/BaseServiceImpl.java @@ -72,7 +72,7 @@ public abstract class BaseServiceImpl< BeanUtil.copyProperties(dto, entity); // 强制新增,将ID置为空 entity.setId(null); - // 新增数据 + // 新增数据(时间戳由监听器自动设置) save(entity); // 仅返回数据ID @SuppressWarnings("all") @@ -93,7 +93,7 @@ public abstract class BaseServiceImpl< public Boolean update(DTO dto) { Entity entity = createEntity(); BeanUtil.copyProperties(dto, entity); - // 更新数据 + // 更新数据(时间戳由监听器自动设置) return updateById(entity); } diff --git a/src/main/java/com/example/demo/parser/entity/FileRecordEntity.java b/src/main/java/com/example/demo/parser/entity/FileRecordEntity.java index 67f1f54..d437ed5 100644 --- a/src/main/java/com/example/demo/parser/entity/FileRecordEntity.java +++ b/src/main/java/com/example/demo/parser/entity/FileRecordEntity.java @@ -1,6 +1,7 @@ package com.example.demo.parser.entity; import com.example.demo.common.domain.BaseEntity; +import com.example.demo.common.config.orm.listener.FlexListener; import com.mybatisflex.annotation.Table; import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; @@ -25,7 +26,7 @@ import java.util.Date; @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode(callSuper = true) -@Table("file_record") +@Table(value = "file_record", onInsert = FlexListener.class, onUpdate = FlexListener.class) public class FileRecordEntity extends BaseEntity { @Serial diff --git a/src/main/java/com/example/demo/parser/entity/MapperRuleEntity.java b/src/main/java/com/example/demo/parser/entity/MapperRuleEntity.java index 7df3f5e..4077c5e 100644 --- a/src/main/java/com/example/demo/parser/entity/MapperRuleEntity.java +++ b/src/main/java/com/example/demo/parser/entity/MapperRuleEntity.java @@ -1,6 +1,7 @@ package com.example.demo.parser.entity; import com.example.demo.common.domain.BaseEntity; +import com.example.demo.common.config.orm.listener.FlexListener; import com.mybatisflex.annotation.Table; import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; @@ -24,7 +25,7 @@ import java.io.Serial; @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode(callSuper = true) -@Table("mapper_rule") +@Table(value = "mapper_rule", onInsert = FlexListener.class, onUpdate = FlexListener.class) public class MapperRuleEntity extends BaseEntity { @Serial diff --git a/src/main/java/com/example/demo/parser/entity/ParseRuleEntity.java b/src/main/java/com/example/demo/parser/entity/ParseRuleEntity.java index 620f8ab..9bdcf26 100644 --- a/src/main/java/com/example/demo/parser/entity/ParseRuleEntity.java +++ b/src/main/java/com/example/demo/parser/entity/ParseRuleEntity.java @@ -1,6 +1,7 @@ package com.example.demo.parser.entity; import com.example.demo.common.domain.BaseEntity; +import com.example.demo.common.config.orm.listener.FlexListener; import com.mybatisflex.annotation.Table; import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; @@ -24,7 +25,7 @@ import java.io.Serial; @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode(callSuper = true) -@Table("parse_rule") +@Table(value = "parse_rule", onInsert = FlexListener.class, onUpdate = FlexListener.class) public class ParseRuleEntity extends BaseEntity { @Serial