我有两节课。
民意调查.java
public class Poll {
@Id
@Column(name = "poll_id")
String pollId;
String question;
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm")
String endDateTime;
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "poll_id_fk", referencedColumnName = "poll_id")
List<Choice> choices;
}
和
选择.java
public class Choice {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "choice_id")
Long choiceId;
String text;
Integer votes;
}
当我创建新的民意调查时, choice_id 会从之前创建的最后一个 choice_id 的编号开始递增。创建新民意调查时,如何使 choice_id 重置其值?
我尝试更改 GenerationType 策略,但这似乎没有任何影响。我期待这样的结果:
[
{
"pollId": "MvWRj",
"question": "poll 2?",
"endDateTime": "2023-07-09 19:50",
"choices": [
{
**"choiceId": 1,**
"text": "choice 1",
"votes": 1
},
{
**"choiceId": 2,**
"text": "choice 2",
"votes": 0
}
]
},
{
"pollId": "V838D",
"question": "poll 1?",
"endDateTime": "2023-07-09 19:50",
"choices": [
{
**"choiceId": 1,**
"text": "choice 1",
"votes": 1
},
{
**"choiceId": 2,**
"text": "choice 2",
"votes": 0
}
]
}
]
而我得到的结果如下:
[
{
"pollId": "MvWRj",
"question": "poll 2?",
"endDateTime": "2023-07-09 19:50",
"choices": [
{
**"choiceId": 3,**
"text": "choice 1",
"votes": 1
},
{
**"choiceId": 4,**
"text": "choice 2",
"votes": 0
}
]
},
{
"pollId": "V838D",
"question": "poll 1?",
"endDateTime": "2023-07-09 19:50",
"choices": [
{
**"choiceId": 1,**
"text": "choice 1",
"votes": 1
},
{
**"choiceId": 2,**
"text": "choice 2",
"votes": 0
}
]
}
]
关系数据库就是这样工作的。每个记录的 Id 必须是唯一的,以区分它们。但是,如果只想存储与您的民意调查相关的集合,您可以尝试这种设置字段的方式。
@Lob
@Column
private List<Choice> choices = new ArrayList<>();
不需要让类选择一个实体,也不需要有 Id,因为你已经索引了集合。
为了实现您正在寻找的行为(其中
choiceId
会针对每个新的 Poll
进行重置),您将需要对当前的实现进行一些更改。主要问题是 @GeneratedValue(strategy = GenerationType.AUTO)
类中的 Choice
为所有 Choice
实体中的每个 Poll
实体生成唯一标识符,从而导致不同民意调查中的 ID 不断增加。
以下是您可以考虑的一些方法:
您可以手动管理
choiceId
而不是使用 @GeneratedValue
。此方法要求您在创建或向投票添加选项时,为每个 choiceId
相对于其 Choice
设置 Poll
。然而,这可能会变得复杂且容易出错,尤其是对于并发事务。
考虑使用包含
pollId
和每个选项的附加标识符的复合键。这样,choiceId
只能在每个Poll
的范围内是唯一的。组合键可以使用 JPA 中的 @Embeddable
或 @EmbeddedId
来实现。
复合键类示例:
@Embeddable
public class ChoiceId implements Serializable {
private String pollId;
private Long choiceNumber; // This resets for each Poll
// getters, setters, hashCode, equals
}
在您的
Choice
课程中,您将使用 ChoiceId
作为主键。
如果您的数据库支持,您可以使用特定于数据库的功能,该功能允许根据条件重置序列号(例如创建新的
Poll
)。这是特定于数据库的,可能无法跨不同的数据库系统移植。
在
Poll
实体中添加一个计数器,用于跟踪选择的数量。每次添加新选择时,都会增加此计数器并将其用作 choiceId
。这可确保 choiceId
每次民意调查都是唯一的,但会针对每个新民意调查重置。
在服务层或业务逻辑层处理
choiceId
生成,您可以在其中更好地控制 ID 生成逻辑。这将涉及根据特定民意调查的现有选择计算下一个choiceId
。
每种方法在复杂性、易于实施性和可维护性方面都有其权衡。最佳方法取决于您的具体要求和应用程序运行的环境。
例如,如果您想让事情保持简单并避免修改数据库架构,则手动 ID 管理或在业务逻辑层处理它可能是可行的方法。另一方面,如果您需要一个更强大且可扩展的解决方案,那么考虑组合键或数据库级解决方案可能更合适。