我目前正在使用PostgreSQL数据库,Spring和Hibernate。我有一个表属性correlation_id是唯一的。每次我添加一个新元素之前,我必须检查db中是否已存在任何具有新correlation_id的项目。
对于这种情况,我已经实现了递归函数,它将生成一个新的correlation_id并检查它是否存在于db中。这意味着这个函数每次都会对db进行一次调用,所以有时它只能是一个调用,但有时候我可以是五个,十个甚至更多。此示例在示例一中显示。
例1:
private String generateId() {
String myId = StaticFunction.generateMyId();
MyMessages doesExist = MyServiceDaoImpl.checkDoesItExistInDB(myId);
if(doesExist != null) {
generateId();
}
return myId;
}
在第二个例子中,我假设我只能创建一个对db的调用并检索所有项目并将它们放入集合中。然后我可以通过流来搜索特定项目也使用递归函数。 例2:
private String generateId(List<MyMessages> messages) {
String myId = StaticFunction.generateMyId();
MyMessages myMessage = messages.stream().filter(m ->
m.getCorrelationId.equals(myId)).findFirst().orElse(null);
if (MyMessages != null) {
generateId(messages);
}
return myId;
}
我的问题是什么是使这件事情做对的最佳方法?你有其他解决方案吗?上述例子有哪些优点和缺点?
答案 0 :(得分:1)
如果你不能像评论中所建议的那样使用db generated id,你可以使用UUID生成器来创建PK。碰撞的概率非常低,不值得在db中检查。
要在Java中生成UUID,请查看http://docs.oracle.com/javase/7/docs/api/java/util/UUID.html
答案 1 :(得分:0)
案例1没有任何问题,当列被索引时,DB可以非常有效地进行查找。但是 - 你需要进行数据库访问。
第二种情况看起来更快(在内存中迭代将比任何数据库访问快得多),但它有缺点:你必须将所有消息(或至少它们的相关id)保留在内存中并且当有很多时数据,你是scr ..你将有不好的时间来解决它
同时考虑应用程序的多个实例可以访问数据库的可伸缩性。
因此我建议让数据库生成密钥(您可以使用例如 SERIAL 数据类型),Hibernate在保存对象时返回生成的密钥。如果您需要自定义ID(由您的应用生成),您可以在价值冲突概率较低的地方使用uuid
你也可以使用UPSERT语法(INSERT .... ON CONFLICT(correlation_id) ...)
玩得开心