เพื่อให้สอดคล้องกับโครงสร้างตารางแบบ 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 )