我的数据库中有大量数据,我决定迁移到 Hibernate。我的一张桌子(我们称之为“MyItem”)没有任何合适的 ID。它只包含一列“json”。
由于某种原因(与数据量有关),我无法迁移所有 MyItem 数据,因此它们都有一个新的唯一标识符。
我所做的是向该表添加一个新的“标识符”列(因此有两列:“json”和“标识符”),并在我的 Java 代码中声明了我的实体,使其看起来像这样:>
@Entity
@Table
public class MyItem {
@Lob
private String json;
private String identifier;
public MyItem() {
}
public MyItem(String json) {
this.json = json;
}
public void setIdentifier(String id) {
//fake
}
@Id
public String getIdentifier() {
if (identifier == null) {
identifier = UUID.randomUUID().toString();
}
return identifier;
}
public String getJson() {
return json;
}
public void setJson(String json) {
this.json = json;
}
}
我可以正确创建和访问我的新数据(新数据是用 Id 生成的),但只有当我通过 HQL 访问最旧的数据(标识符列中为 null 的数据)时,我才难以访问。
这是我执行查询的方式(当然,我已经为问题更改了一些内容,请忽略我的假“""json"",当然它不是 json,只是示例):
String myJson = "6044c44a-dd17-40ca-b66b-cb9d29cf8a33-1-0-1";
Query<MyItem> query = statelessSession.createQuery("FROM MyItem WHERE json = :json", MyItem.class);
query.setParameter("json", myJson);
query.setFetchSize(FETCH_SIZE);
query.setReadOnly(true);
query.setLockMode("a", LockMode.NONE);
try (ScrollableResults MyItemList = query.scroll(ScrollMode.FORWARD_ONLY)) {
while (MyItemList.next()) {
MyItem myItem = (MyItem) MyItemList.get(0);
myItem.getJson());
}
}
我在 myItem.getJson() 上得到了一个 NPE;
这里是 Hibernate 跟踪:
14:55:58.263 [TileBuilderCallable_pool-11-thread-2] TRACE o.h.engine.query.spi.QueryPlanCache@157 - Located HQL query plan in cache (FROM MyItem WHERE json = :json)
14:55:58.264 [TileBuilderCallable_pool-11-thread-2] TRACE o.h.engine.query.spi.QueryPlanCache@157 - Located HQL query plan in cache (FROM MyItem WHERE json = :json)
14:55:58.264 [TileBuilderCallable_pool-11-thread-2] TRACE o.h.engine.query.spi.HQLQueryPlan@344 - Iterate: FROM MyItem WHERE json = :json
14:55:58.264 [TileBuilderCallable_pool-11-thread-3] TRACE o.h.r.j.i.AbstractLogicalConnectionImplementor@66 - Preparing to begin transaction via JDBC Connection.setAutoCommit(false)
14:55:58.264 [TileBuilderCallable_pool-11-thread-2] TRACE o.h.engine.spi.QueryParameters@325 - Named parameters: {json=6044c44a-dd17-40ca-b66b-cb9d29cf8a33-1-0-1}
14:55:58.264 [TileBuilderCallable_pool-11-thread-3] TRACE o.h.r.j.i.AbstractLogicalConnectionImplementor@68 - Transaction begun via JDBC Connection.setAutoCommit(false)
14:55:58.264 [TileBuilderCallable_pool-11-thread-3] TRACE o.h.r.t.b.j.i.JdbcResourceLocalTransactionCoordinatorImpl@172 - ResourceLocalTransactionCoordinatorImpl#afterBeginCallback
14:55:58.264 [TileBuilderCallable_pool-11-thread-3] DEBUG o.h.e.t.internal.TransactionImpl@56 - On TransactionImpl creation, JpaCompliance#isJpaTransactionComplianceEnabled == false
14:55:58.264 [TileBuilderCallable_pool-11-thread-2] DEBUG org.hibernate.SQL@94 -
select
myit0_.identifier as identifi1_0_,
myit0_.json as json5_0_
from
MyItem myit0_
where
myit0_.json=?
14:55:58.264 [TileBuilderCallable_pool-11-thread-3] DEBUG o.h.e.t.internal.TransactionImpl@78 - begin
14:55:58.264 [TileBuilderCallable_pool-11-thread-3] DEBUG o.s.j.d.DriverManagerDataSource@144 - Creating new JDBC DriverManager Connection to [jdbc:com.db://localhost:1234/mydb]
14:55:58.264 [TileBuilderCallable_pool-11-thread-2] TRACE o.h.r.j.i.ResourceRegistryStandardImpl@68 - Registering statement [[Statement - handle 1 (Connection ID - 25769822844)]]
14:55:58.264 [TileBuilderCallable_pool-11-thread-2] TRACE o.h.e.j.internal.JdbcCoordinatorImpl@339 - Registering last query statement [[Statement - handle 1 (Connection ID - 25769822844)]]
14:55:58.264 [TileBuilderCallable_pool-11-thread-2] TRACE o.h.type.descriptor.sql.BasicBinder@65 - binding parameter [1] as [VARCHAR] - [6044c44a-dd17-40ca-b66b-cb9d29cf8a33-1-0-1]
14:55:58.264 [TileBuilderCallable_pool-11-thread-2] TRACE org.hibernate.loader.Loader@2034 - Bound [2] parameters total
14:55:58.266 [TileBuilderCallable_pool-11-thread-2] TRACE o.h.r.j.i.ResourceRegistryStandardImpl@196 - Registering result set [com.db.ResultSet@55612811]
14:55:58.266 [TileBuilderCallable_pool-11-thread-2] TRACE o.h.t.descriptor.sql.BasicExtractor@51 - extracted value ([identifi1_0_] : [VARCHAR]) - [null]
14:55:58.266 [TileBuilderCallable_pool-11-thread-2] DEBUG org.hibernate.loader.Loader@1532 - Result row: null
14:55:58.267 [TileBuilderCallable_pool-11-thread-2] TRACE org.hibernate.loader.Loader@1149 - Total objects hydrated: 0
我在这里唯一的想法是尝试/捕获 NPE,因此我通过添加标识符来动态迁移数据。还有其他更智能的方法来执行我的查询吗?
谢谢! :)
答案 0 :(得分:0)
public void setIdentifier(String id) {
//fake
}
为什么不在这里设置 identifier
字段?尝试将其更正为:
public void setIdentifier(String id) {
this.identifier = id;
}
并重新检查您的问题。
您试图混淆可能导致问题的 access strategies。默认情况下,@Id
注释的位置提供默认访问策略。当放置在一个字段上时,Hibernate 将承担基于字段的访问。当放置在标识符 getter 上时,Hibernate 将使用基于属性的访问。 因此,当您使用基于属性的访问时,hibernate 将忽略您的 @Lob
注释。
您对 getIdentifier
方法的实现看起来也很可疑。我建议您使用 @GeneratedValue
来生成实体 ID。 Hibernate 支持 UUID identifier value generation。
因此,我建议您以这种方式更正映射:
import org.hibernate.annotations.Type;
@Entity
@Table
public class MyItem {
@Id
@GeneratedValue
@Type(type = "uuid-char")
private UUID identifier;
@Lob
private String json;
// ...
@Transient
public String getIdentifierAsString() {
return identifier != null ? identifier.toString() : null;
}
}