หมวดหมู่: Spring Boot

Spring Security: EntitySpring Security: Entity

เพื่อให้สอดคล้องกับโครงสร้างตารางแบบ Laravel Jetstream + Spatie ที่เราวางแผนไว้ใน Flyway Migration ไฟล์ Entity ใน Spring Boot จะต้องใช้การ Mapping แบบ Many-to-Many โดยมีรายละเอียดดังนี้ครับ


Permission Entity

ตัวนี้จะเก็บสิทธิ์ย่อย ๆ เช่น post-create, user-delete
src/main/java/com/example/demo/entity/Permission.java

package com.example.demo.entity; import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;
import java.util.Set; @Entity
@Table (name = "permissions") @Getter @Setter
public class Permission { @Id @GeneratedValue (strategy = GenerationType.IDENTITY) private Long id; @Column (unique = true, nullable = false) private String name; @Column (name = "guard_name") private String guardName = "web"; @ManyToMany (mappedBy = "permissions") private Set<Role> roles;
}

Role Entity

ตัวนี้จะเชื่อมต่อไปยัง Permission แบบ Many-to-Many (เหมือน role_has_permissions ใน Laravel)
src/main/java/com/example/demo/entity/Role.java

package com.example.demo.entity; import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;
import java.util.Set; @Entity
@Table (name = "roles") @Getter @Setter
public class Role { @Id @GeneratedValue (strategy = GenerationType.IDENTITY) private Long id; @Column (unique = true, nullable = false) private String name; @Column (name = "guard_name") private String guardName = "web"; @ManyToMany (fetch = FetchType.EAGER) @JoinTable (name = "role_has_permissions", joinColumns = @JoinColumn (name = "role_id") , inverseJoinColumns = @JoinColumn (name = "permission_id")) private Set<Permission> permissions;
}

User Entity

ตัวนี้จะเก็บข้อมูลผู้ใช้และเชื่อมกับ Role (เหมือน model_has_roles ใน Laravel)
src/main/java/com/example/demo/entity/User.java

package com.example.demo.entity; import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;
import java.time.LocalDateTime;
import java.util.Set; @Entity
@Table (name = "users") @Getter @Setter
public class User { @Id @GeneratedValue (strategy = GenerationType.IDENTITY) private Long id; @Column (unique = true, nullable = false) private String username; @Column (nullable = false) private String password; @Column (unique = true) private String email; @Column (name = "full_name", columnDefinition = "nvarchar (255) ") private String fullName; @Column (name = "profile_photo_path", columnDefinition = "nvarchar (2048) ") private String profilePhotoPath; @Column (name = "created_at") private LocalDateTime createdAt; @Column (name = "updated_at") private LocalDateTime updatedAt; @ManyToMany (fetch = FetchType.EAGER) @JoinTable (name = "model_has_roles", joinColumns = @JoinColumn (name = "model_id") , inverseJoinColumns = @JoinColumn (name = "role_id")) private Set<Role> roles; @PrePersist protected void onCreate () { createdAt = LocalDateTime.now () ; } @PreUpdate protected void onUpdate () { updatedAt = LocalDateTime.now () ; }
}

ข้อควรทราบเพิ่มเติม

  • เปลี่ยน com.example.demo เป็นชื่อ Package จริงที่คุณตั้งไว้ในโปรเจกต์
  • Lombok: ผมใช้ @Getter และ @Setter จาก Library Lombok เพื่อให้ Code ดูสะอาด (ถ้าโปรเจกต์คุณไม่ได้ลงไว้ ให้ใช้การ Generate Getter/Setter ปกติแทนครับ)
  • Naming Strategy: ใน Java มักใช้ camelCase (เช่น fullName) แต่ใน Database SQL Server ผมตั้งชื่อให้เป็น snake_case (เช่น full_name) ตามสไตล์ Laravel โดยใช้ @Column (name = "...") เป็นตัวเชื่อม
  • FetchType.EAGER: ตั้งค่าไว้ที่ Roles เพื่อให้เวลาโหลด User มาแล้ว สามารถดึงสิทธิ์มาเช็คใน Security Context ได้ทันที (คล้ายกับ $user->load ('roles') ใน Laravel)