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(); // 强制同步到数据库
+ }
+}