关于Java Spring Data JPA存储库和我正在使用的SQL Server表,我遇到了一个奇怪的问题,该表具有唯一的标识符字段(PK字段,尽管事实是它与PK无关)问题)。
我遇到的问题是,当我在该表中插入新项目时,UUID会以小写形式返回。当我在表上执行“ findOne”(使用Spring Data 2.0之前的版本)时,即使“ findOne”参数为大写字母,它也以小写形式返回。但是,当我在此表上执行“ findAll”时,ID都以大写形式返回。我希望能够做这样的事情进行测试:
String id = repository.save(...).getField();
List<String> data = repository.findAll().map(d -> d.getField());
assertThat(data.contains(id));
问题在于第一行将返回一个小写ID,第二行将返回一个大写ID列表,因此第三行将失败。
至于将字符串用于UUID,我知道这不是推荐的做法;请参见第4章。但是,当我不这样做时(当我使用UUID类型时),我遇到了一个完全不同的问题,超出了此问题的范围。如果建议的答案是“不要将字符串用于UUID”,那么我可以将其作为一个单独的问题提出来。
表的缩写:
CREATE TABLE [dbo].[TABLE](
[ID] [uniqueidentifier] NOT NULL,
<...>
CONSTRAINT [PK_Customer] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
ALTER TABLE [dbo].[TABLE] ADD CONSTRAINT [DF_TABLE_ID] DEFAULT (newid()) FOR [ID]
GO
以及实体定义:
@Entity
@Table(name = "TABLE")
public class DataEntity {
@Id
@GeneratedValue(generator = "uuid")
@GenericGenerator(name = "uuid", strategy = "uuid2")
@Column(name = "ID", updatable = false, nullable = false, unique = true)
private String id;
<...>
}
答案 0 :(得分:0)
使用生成器,您指定了在应用程序端生成UUID并将其发送到数据库中,并以一种有效的格式存储它们,大多数情况下肯定不包含有关大小写的任何信息,因为它只是一个数字。
我怀疑您在选择中看到的差异可能来自会话缓存,而实际上与您使用的方法没有太大关系:如果在缓存中找到了实体,则返回该实体并将其保存它包含Hibernator生成它的格式的UUID(因此,小写取决于Hibernate中的toString()
方法)。
如果在缓存中找不到该实体,则该实体会从数据库中返回,这很可能取决于您所使用的JDBC驱动程序中的实现细节。
那么如何解决此问题:
简单方法:Use guid
as the generator。它将命中数据库,因此UUID将始终采用数据库提供的格式。如果性能至关重要,那么这可能不是一个可行的选择。 注意:我在当前文档中找不到此生成器,不知道它是否已弃用或什么。
困难的方法:查找或创建一个UUID生成器,该生成器以数据库返回的确切格式创建UUID。
对于生成UUID而言,似乎有令人惊讶的摆动空间,因此,这里是供进一步阅读的链接列表:
Vlad Mihalcea关于UUID:https://vladmihalcea.com/hibernate-and-uuid-identifiers/
一个类似的问题:Different representation of UUID in Java Hibernate and SQL Server
答案 1 :(得分:0)
为什么在比较它们之前不只是将所有字符串都转换为相同的大小写(没关系)?
不过,这似乎并不理想;比较两个36个字符长的字符串将比16字节数字花费更多的时间(并且处理它们将占用更多的空间),并且由于数据库(您希望)将它们存储为二进制,因此转换会产生额外费用效率较低的形式。哦,即使相同数目的字节,字符串比较也会比较慢,因为它不知道它们的长度是固定的,它可能必须一次比较一个字节,而不是使用更宽的比较。