Entity One-to-Many 排序设置

本文介绍了使用Java实现的新闻及评论实体类的ORM映射方法,并详细解释了数据库表结构的设计思路。通过实体类与数据库表之间的映射,实现了高效的数据交互。
/**
 * 评论实体类,对应 TCOMMENT 表。
 * @author William
 */
@Entity
@Table(name = "TCOMMENT")
public class Comment {

	/**
	 * 标识ID字段为主键,主键生成策略为:自动。
	 */
	@Id @GeneratedValue
	private Long id;
	private String nickname;
	private String content;
	private Integer note;
	/**
	 * 发表日期,对应 posted_date 字段,字段类型为TIMESTAMP。
	 */
	@Column(name = "posted_date")
	@Temporal(TemporalType.TIMESTAMP)
	private Date postedDate;
	
	// Constructors, setters, getters
}

 

/**
 * 新闻实体类,对应 News表。
 * @author William
 */
@Entity
@NamedQuery(name = "findAllNews", query = "SELECT n FROM News n")
public class News {

	/**
	 * 标识ID字段为主键,主键生成策略为:自动。
	 */
	@Id @GeneratedValue
	private Long id;
	/**
	 * content新闻内容,该字段必填。
	 */
	@Column(nullable = false)
	private String content;
	/**
	 * comments评论,与之进行一对多关联。<br/>
	 * FetchType.EAGER 获取新闻时立即相关评论。<br/>
	 * CascadeType.ALL 支持所有级联操作。<br/>
	 * OrderBy 获取评论列表时,按照postedDate(发表日期)降序排列。
	 */
	@OneToMany(fetch = FetchType.EAGER, cascade = {CascadeType.ALL})
	@JoinTable(name = "NEWS_COMMENT", joinColumns = @JoinColumn(name = "NEWS_ID"),
		inverseJoinColumns = @JoinColumn(name = "COMMENT_ID"))
	@OrderBy("postedDate DESC")
	private List<Comment> comments;
	
	// Constructors, setters, getters
}

 

CREATE TABLE TCOMMENT (
	ID BIGINT,
	NICKNAME VARCHAR(50),
	CONTENT VARCHAR(500),
	NOTE INT,
	POSTED_DATE TIMESTAMP,
	PRIMARY KEY (ID)
);

CREATE TABLE NEWS (
	ID BIGINT,
	CONTENT VARCHAR(500),
	PRIMARY KEY (ID)
);

CREATE TABLE NEWS_COMMENT (
	NEWS_ID BIGINT,
	COMMENT_ID BIGINT,
	PRIMARY KEY (NEWS_ID, COMMENT_ID),
	FOREIGN KEY (NEWS_ID) REFERENCES NEWS(ID),
	FOREIGN KEY (COMMENT_ID) REFERENCES TCOMMENT(ID)
);

 

// Data/ApplicationDbContext.cs using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; using UserManagementSystem.Web.Models; namespace UserManagementSystem.Web.Data { public class ApplicationDbContext : IdentityDbContext<ApplicationUser> { // ✅ Identity 默认表(Users, Roles, UserRoles, etc.) public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { } // =================================== // 🔹 自定义业务实体 DbSet // =================================== /// <summary> /// 【人】自然人信息 /// </summary> public DbSet<Person> Persons { get; set; } /// <summary> /// 【照片】人员关联的照片 /// </summary> public DbSet<PersonPhoto> PersonPhotos { get; set; } /// <summary> /// 【单位】例如乡镇、村委等组织机构(你在 RegisterViewModel 中用了 Cmb) /// </summary> public DbSet<Cmb> Cmbs { get; set; } /// <summary> /// 【团队】如工作小组、服务队等 /// </summary> public DbSet<Team> Teams { get; set; } /// <summary> /// 【分组】用于对 Team 进行分类管理(例如:按区域、职能划分) /// </summary> public DbSet<Group> Groups { get; set; } // =================================== // 🛠️ 配置关系(OnModelCreating) // =================================== protected override void OnModelCreating(ModelBuilder builder) { base.OnModelCreating(builder); // 必须调用基类,否则 Identity 表会出错 // -------------------------------------------------- // 1. Person - PersonPhoto: 一对多 // -------------------------------------------------- builder.Entity<Person>() .HasMany(p => p.Photos) .WithOne(ph => ph.Person) .HasForeignKey(ph => ph.PersonId) .OnDelete(DeleteBehavior.Cascade); // 删除 Person 时,自动删除所有照片 // -------------------------------------------------- // 2. Cmb 排序索引(你用了 OrderBy(c => c.SortOrder)) // -------------------------------------------------- builder.Entity<Cmb>() .HasIndex(c => c.SortOrder); // -------------------------------------------------- // 3. 可选:为常用查询添加索引 // -------------------------------------------------- builder.Entity<Person>() .HasIndex(p => p.IdCardNumber) .IsUnique() .HasFilter("[IdCardNumber] IS NOT NULL"); // 身份证唯一(允许 null) builder.Entity<Person>() .HasIndex(p => new { p.HouseholdId, p.Name }); // 户内按姓名查快 // -------------------------------------------------- // 4. 设置默认值(EF Core 9 支持) // -------------------------------------------------- builder.Entity<Person>() .Property(p => p.CreatedAt) .HasDefaultValueSql("GETUTCDATE()"); builder.Entity<Person>() .Property(p => p.UpdatedAt) .HasDefaultValueSql("GETUTCDATE()"); // -------------------------------------------------- // 5. Team - Group: 多个 Team 属于一个 Group(可选) // 每个 Team 可以属于一个 Group,也可以不属于任何 Group(GroupId 可为空) // -------------------------------------------------- builder.Entity<Team>() .HasOne<Group>() // Team 拥有一个 Group .WithMany(g => g.Teams) // Group 包含多个 Team .HasForeignKey(t => t.GroupId) // 外键是 Team.GroupId .OnDelete(DeleteBehavior.SetNull); // 删除 Group 后,Team 的 GroupId 设为 null // -------------------------------------------------- // 6. 可以为 Group 和 Team 添加索引提升性能 // -------------------------------------------------- builder.Entity<Group>() .HasIndex(g => g.Name) .IsUnique(); // 组名唯一 builder.Entity<Team>() .HasIndex(t => t.Name); // 团队名称索引 builder.Entity<Team>() .HasIndex(t => t.GroupId); // 外键索引,提高连接查询效率 } // =================================== // ⚙️ 可选:重写 SaveChanges 以自动更新时间戳 // =================================== public override int SaveChanges() { UpdateTimestamps(); return base.SaveChanges(); } public override int SaveChanges(bool acceptAllChangesOnSuccess) { UpdateTimestamps(); return base.SaveChanges(acceptAllChangesOnSuccess); } public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default) { UpdateTimestamps(); return await base.SaveChangesAsync(cancellationToken); } public override async Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default) { UpdateTimestamps(); return await base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken); } private void UpdateTimestamps() { var entries = ChangeTracker.Entries() .Where(e => e.Entity is Person && (e.State == EntityState.Added || e.State == EntityState.Modified)); foreach (var entry in entries) { if (entry.State == EntityState.Added) { entry.Property("CreatedAt").CurrentValue = DateTime.UtcNow; } entry.Property("UpdatedAt").CurrentValue = DateTime.UtcNow; } } } } 是没有配置Household,帮我配置一下,我的层级结构是Cmb → Group → Team → Household → Person
最新发布
10-08
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值