diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml new file mode 100644 index 0000000..daa58c0 --- /dev/null +++ b/.idea/dataSources.xml @@ -0,0 +1,18 @@ + + + + + postgresql + true + true + org.postgresql.Driver + jdbc:postgresql://127.0.0.1:5432/weblog + + + + + + $ProjectFileDir$ + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml index 3665080..ac138a8 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -5,6 +5,7 @@ + \ No newline at end of file diff --git a/.idea/sqldialects.xml b/.idea/sqldialects.xml new file mode 100644 index 0000000..5ab0b21 --- /dev/null +++ b/.idea/sqldialects.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/sql/createTable.sql b/sql/createTable.sql new file mode 100644 index 0000000..e5c8e1c --- /dev/null +++ b/sql/createTable.sql @@ -0,0 +1,33 @@ +-- 1. 创建一个函数,用于在数据更新时自动修改 update_time 字段 +CREATE OR REPLACE FUNCTION set_update_time() + RETURNS TRIGGER AS +$$ +BEGIN + NEW.update_time = NOW(); + RETURN NEW; +END; +$$ LANGUAGE plpgsql; + +-- 2. 创建表(使用 BOOLEAN 替代 SMALLINT for is_deleted) +CREATE TABLE t_user +( + id BIGSERIAL PRIMARY KEY, + username VARCHAR(60) NOT NULL UNIQUE, + password VARCHAR(60) NOT NULL, + create_time TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(), + -- WITH TIME ZONE 是更严谨的选择 + update_time TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(), + -- 使用 BOOLEAN 逻辑删除,DEFAULT FALSE 对应 '0:未删除' + is_deleted BOOLEAN NOT NULL DEFAULT FALSE +); + +-- 3. 创建触发器,在每次 UPDATE 操作前调用函数 +CREATE TRIGGER set_t_user_update_time + BEFORE UPDATE + ON t_user + FOR EACH ROW +EXECUTE FUNCTION set_update_time(); + +-- 添加注释 +COMMENT ON TABLE t_user IS '用户表(优化版)'; +COMMENT ON COLUMN t_user.is_deleted IS '逻辑删除:FALSE:未删除 TRUE:已删除'; \ No newline at end of file diff --git a/weblog-module-common/build.gradle.kts b/weblog-module-common/build.gradle.kts index 8d502a5..11a2442 100644 --- a/weblog-module-common/build.gradle.kts +++ b/weblog-module-common/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - java + `java-library` } dependencies { @@ -8,6 +8,8 @@ dependencies { implementation("com.google.guava:guava:33.5.0-jre") // commons-lang3 implementation("org.apache.commons:commons-lang3:3.20.0") + // jpa + api("org.springframework.boot:spring-boot-starter-data-jpa") // test testImplementation("org.springframework.boot:spring-boot-starter-test") // jackson @@ -17,4 +19,6 @@ dependencies { implementation("org.springframework.boot:spring-boot-starter-aop") // web implementation("org.springframework.boot:spring-boot-starter-web") + // postgresql + runtimeOnly("org.postgresql:postgresql") } diff --git a/weblog-module-common/src/main/java/com/hanserwei/common/domain/dataobject/User.java b/weblog-module-common/src/main/java/com/hanserwei/common/domain/dataobject/User.java new file mode 100644 index 0000000..2465e0a --- /dev/null +++ b/weblog-module-common/src/main/java/com/hanserwei/common/domain/dataobject/User.java @@ -0,0 +1,82 @@ +package com.hanserwei.common.domain.dataobject; + +import jakarta.persistence.*; // 使用 Jakarta Persistence API (JPA 3.0+) +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +import org.hibernate.annotations.CreationTimestamp; +import org.hibernate.annotations.UpdateTimestamp; + +import java.io.Serial; +import java.io.Serializable; +import java.time.Instant; // 推荐用于 TIMESTAMP WITH TIME ZONE + +/** + * 用户表(t_user 对应实体) + */ +@Entity +@Setter +@Getter +@Builder +@Table(name = "t_user") // 对应数据库中的表名 +public class User implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * ID (BIG SERIAL) + */ + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id") + private Long id; + + /** + * 用户名 (VARCHAR(60) NOT NULL UNIQUE) + */ + @Column(name = "username", length = 60, nullable = false, unique = true) + private String username; + + /** + * 密码 (VARCHAR(60) NOT NULL) + */ + @Column(name = "password", length = 60, nullable = false) + private String password; + + /** + * 创建时间 (TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()) + * 使用 Hibernate 的 @CreationTimestamp 确保创建时自动赋值 + */ + @CreationTimestamp + @Column(name = "create_time", nullable = false, updatable = false) + private Instant createTime; + + /** + * 最后一次更新时间 (TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()) + * 使用 Hibernate 的 @UpdateTimestamp 确保更新时自动赋值 + * 注意:虽然数据库有触发器,但使用此注解可保持 ORM 层的同步性 + */ + @UpdateTimestamp + @Column(name = "update_time", nullable = false) + private Instant updateTime; + + /** + * 逻辑删除:FALSE:未删除 TRUE:已删除 (BOOLEAN NOT NULL DEFAULT FALSE) + */ + @Builder.Default + @Column(name = "is_deleted", nullable = false) + private Boolean isDeleted = false; // 对应数据库默认值 + + public User() { + } + + public User(Long id, String username, String password, Instant createTime, Instant updateTime, Boolean isDeleted) { + this.id = id; + this.username = username; + this.password = password; + this.createTime = createTime; + this.updateTime = updateTime; + this.isDeleted = isDeleted; + } +} diff --git a/weblog-module-common/src/main/java/com/hanserwei/common/domain/repository/UserRepository.java b/weblog-module-common/src/main/java/com/hanserwei/common/domain/repository/UserRepository.java new file mode 100644 index 0000000..1111a54 --- /dev/null +++ b/weblog-module-common/src/main/java/com/hanserwei/common/domain/repository/UserRepository.java @@ -0,0 +1,7 @@ +package com.hanserwei.common.domain.repository; + +import com.hanserwei.common.domain.dataobject.User; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface UserRepository extends JpaRepository { +} diff --git a/weblog-web/build.gradle.kts b/weblog-web/build.gradle.kts index 6805b00..ba11778 100644 --- a/weblog-web/build.gradle.kts +++ b/weblog-web/build.gradle.kts @@ -9,7 +9,6 @@ dependencies { // Spring Boot Web(示例) implementation("org.springframework.boot:spring-boot-starter-web") - // Test testImplementation("org.springframework.boot:spring-boot-starter-test") diff --git a/weblog-web/src/main/java/com/hanserwei/web/WeblogWebApplication.java b/weblog-web/src/main/java/com/hanserwei/web/WeblogWebApplication.java index e10d4e7..c4ff219 100644 --- a/weblog-web/src/main/java/com/hanserwei/web/WeblogWebApplication.java +++ b/weblog-web/src/main/java/com/hanserwei/web/WeblogWebApplication.java @@ -2,10 +2,12 @@ package com.hanserwei.web; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.ComponentScan; +import org.springframework.boot.autoconfigure.domain.EntityScan; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; -@SpringBootApplication -@ComponentScan({"com.hanserwei.*"}) +@SpringBootApplication(scanBasePackages = "com.hanserwei") +@EnableJpaRepositories(basePackages = "com.hanserwei.common.domain.repository") +@EntityScan(basePackages = "com.hanserwei.common.domain.dataobject") public class WeblogWebApplication { public static void main(String[] args) { SpringApplication.run(WeblogWebApplication.class, args); diff --git a/weblog-web/src/test/java/com/hanserwei/web/WeblogWebApplicationTests.java b/weblog-web/src/test/java/com/hanserwei/web/WeblogWebApplicationTests.java index 8f75af4..537e530 100644 --- a/weblog-web/src/test/java/com/hanserwei/web/WeblogWebApplicationTests.java +++ b/weblog-web/src/test/java/com/hanserwei/web/WeblogWebApplicationTests.java @@ -1,13 +1,19 @@ package com.hanserwei.web; +import com.hanserwei.common.domain.dataobject.User; +import com.hanserwei.common.domain.repository.UserRepository; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; -import lombok.extern.slf4j.Slf4j; -@SpringBootTest @Slf4j +@SpringBootTest class WeblogWebApplicationTests { + @Resource + private UserRepository userRepository; + @Test void contextLoads() { } @@ -23,4 +29,15 @@ class WeblogWebApplicationTests { log.info("这是一行带有占位符日志,作者:{}", author); } -} \ No newline at end of file + @Test + void insertTest() { + User user = User.builder() + .username("Hanserwei") + .password("123456") + .build(); + + // 使用jpa插入数据 + User savedUser = userRepository.save(user); // 保存并获取返回的实体 + userRepository.flush(); // 强制同步到数据库 + } +}