feat(user): add user entity and repository with JPA integration
This commit is contained in:
18
.idea/dataSources.xml
generated
Normal file
18
.idea/dataSources.xml
generated
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
|
||||||
|
<data-source source="LOCAL" name="weblog@127.0.0.1" uuid="bb8330e4-9a89-4978-ad63-ad6402096c16">
|
||||||
|
<driver-ref>postgresql</driver-ref>
|
||||||
|
<synchronize>true</synchronize>
|
||||||
|
<imported>true</imported>
|
||||||
|
<jdbc-driver>org.postgresql.Driver</jdbc-driver>
|
||||||
|
<jdbc-url>jdbc:postgresql://127.0.0.1:5432/weblog</jdbc-url>
|
||||||
|
<jdbc-additional-properties>
|
||||||
|
<property name="com.intellij.clouds.kubernetes.db.host.port" />
|
||||||
|
<property name="com.intellij.clouds.kubernetes.db.enabled" value="false" />
|
||||||
|
<property name="com.intellij.clouds.kubernetes.db.container.port" />
|
||||||
|
</jdbc-additional-properties>
|
||||||
|
<working-dir>$ProjectFileDir$</working-dir>
|
||||||
|
</data-source>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
1
.idea/modules.xml
generated
1
.idea/modules.xml
generated
@@ -5,6 +5,7 @@
|
|||||||
<module fileurl="file://$PROJECT_DIR$/weblog-springboot.iml" filepath="$PROJECT_DIR$/weblog-springboot.iml" />
|
<module fileurl="file://$PROJECT_DIR$/weblog-springboot.iml" filepath="$PROJECT_DIR$/weblog-springboot.iml" />
|
||||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/weblog-module-common/weblog-springboot.weblog-module-common.main.iml" filepath="$PROJECT_DIR$/.idea/modules/weblog-module-common/weblog-springboot.weblog-module-common.main.iml" />
|
<module fileurl="file://$PROJECT_DIR$/.idea/modules/weblog-module-common/weblog-springboot.weblog-module-common.main.iml" filepath="$PROJECT_DIR$/.idea/modules/weblog-module-common/weblog-springboot.weblog-module-common.main.iml" />
|
||||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/weblog-web/weblog-springboot.weblog-web.main.iml" filepath="$PROJECT_DIR$/.idea/modules/weblog-web/weblog-springboot.weblog-web.main.iml" />
|
<module fileurl="file://$PROJECT_DIR$/.idea/modules/weblog-web/weblog-springboot.weblog-web.main.iml" filepath="$PROJECT_DIR$/.idea/modules/weblog-web/weblog-springboot.weblog-web.main.iml" />
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/modules/weblog-web/weblog-springboot.weblog-web.test.iml" filepath="$PROJECT_DIR$/.idea/modules/weblog-web/weblog-springboot.weblog-web.test.iml" />
|
||||||
</modules>
|
</modules>
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
7
.idea/sqldialects.xml
generated
Normal file
7
.idea/sqldialects.xml
generated
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="SqlDialectMappings">
|
||||||
|
<file url="file://$PROJECT_DIR$/sql/createTable.sql" dialect="PostgreSQL" />
|
||||||
|
<file url="PROJECT" dialect="PostgreSQL" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
33
sql/createTable.sql
Normal file
33
sql/createTable.sql
Normal file
@@ -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:已删除';
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
plugins {
|
plugins {
|
||||||
java
|
`java-library`
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
@@ -8,6 +8,8 @@ dependencies {
|
|||||||
implementation("com.google.guava:guava:33.5.0-jre")
|
implementation("com.google.guava:guava:33.5.0-jre")
|
||||||
// commons-lang3
|
// commons-lang3
|
||||||
implementation("org.apache.commons:commons-lang3:3.20.0")
|
implementation("org.apache.commons:commons-lang3:3.20.0")
|
||||||
|
// jpa
|
||||||
|
api("org.springframework.boot:spring-boot-starter-data-jpa")
|
||||||
// test
|
// test
|
||||||
testImplementation("org.springframework.boot:spring-boot-starter-test")
|
testImplementation("org.springframework.boot:spring-boot-starter-test")
|
||||||
// jackson
|
// jackson
|
||||||
@@ -17,4 +19,6 @@ dependencies {
|
|||||||
implementation("org.springframework.boot:spring-boot-starter-aop")
|
implementation("org.springframework.boot:spring-boot-starter-aop")
|
||||||
// web
|
// web
|
||||||
implementation("org.springframework.boot:spring-boot-starter-web")
|
implementation("org.springframework.boot:spring-boot-starter-web")
|
||||||
|
// postgresql
|
||||||
|
runtimeOnly("org.postgresql:postgresql")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<User, Long> {
|
||||||
|
}
|
||||||
@@ -9,7 +9,6 @@ dependencies {
|
|||||||
// Spring Boot Web(示例)
|
// Spring Boot Web(示例)
|
||||||
implementation("org.springframework.boot:spring-boot-starter-web")
|
implementation("org.springframework.boot:spring-boot-starter-web")
|
||||||
|
|
||||||
|
|
||||||
// Test
|
// Test
|
||||||
testImplementation("org.springframework.boot:spring-boot-starter-test")
|
testImplementation("org.springframework.boot:spring-boot-starter-test")
|
||||||
|
|
||||||
|
|||||||
@@ -2,10 +2,12 @@ package com.hanserwei.web;
|
|||||||
|
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
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
|
@SpringBootApplication(scanBasePackages = "com.hanserwei")
|
||||||
@ComponentScan({"com.hanserwei.*"})
|
@EnableJpaRepositories(basePackages = "com.hanserwei.common.domain.repository")
|
||||||
|
@EntityScan(basePackages = "com.hanserwei.common.domain.dataobject")
|
||||||
public class WeblogWebApplication {
|
public class WeblogWebApplication {
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
SpringApplication.run(WeblogWebApplication.class, args);
|
SpringApplication.run(WeblogWebApplication.class, args);
|
||||||
|
|||||||
@@ -1,13 +1,19 @@
|
|||||||
package com.hanserwei.web;
|
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.junit.jupiter.api.Test;
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
|
|
||||||
@SpringBootTest
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
|
@SpringBootTest
|
||||||
class WeblogWebApplicationTests {
|
class WeblogWebApplicationTests {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private UserRepository userRepository;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void contextLoads() {
|
void contextLoads() {
|
||||||
}
|
}
|
||||||
@@ -23,4 +29,15 @@ class WeblogWebApplicationTests {
|
|||||||
log.info("这是一行带有占位符日志,作者:{}", author);
|
log.info("这是一行带有占位符日志,作者:{}", author);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void insertTest() {
|
||||||
|
User user = User.builder()
|
||||||
|
.username("Hanserwei")
|
||||||
|
.password("123456")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// 使用jpa插入数据
|
||||||
|
User savedUser = userRepository.save(user); // 保存并获取返回的实体
|
||||||
|
userRepository.flush(); // 强制同步到数据库
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user