返回null而不是org.hibernate.ObjectNotFoundException: java

laik7k3q  于 2022-12-02  发布在  Java
关注(0)|答案(1)|浏览(111)

我有一个名为ad_session的表,用于记录用户会话。(这是ad_user表的外键)。然后,我获取属于该用户的客户机,并将该客户机添加到列表中。但是,其中一个用户已不存在,所以我的代码停止运行,并抛出以下异常:

org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [ADUser#76A5C22E6D2446A399AE9AD7C1DED0C7]

这是我的原始代码:

List<Session> sessions = getAllSuccessfulSessionsInTable();
List<Client> clientsForThatDay = new ArrayList<>();

try {
   for (Session session : sessions) {
     //code fails when trying to get the non-existent user:
     User user = session.getCreatedBy();
     Client userClient = user.getClient();
     clientsForThatDay.add(userClient);
   }
} catch (Exception e) {     
     log.error("Error getting client from user: ", e);
}

我假设当获取一个不存在的记录时,它会返回null,所以我尝试了以下方法:

List<Session> sessions = getAllSuccessfulSessionsInTable();
List<Client> clientsForThatDay = new ArrayList<>();

//Create new user object to stand in place of the non-existent user
User deletedUser = new User();
deletedUser.setName("Deleted User");

//Create new client object to stand in place of the non-existent client
Client deletedUserClient = new Client();
deletedUserClient.setName("Unknown Client");

try {
  for (Session session : sessions) {
    //check is User is null, if it is, use the deletedUser object, otherwise, use the existing user
    User user = session.getCreatedBy() == null ? deletedUser : session.getCreatedBy();
    
    Client userClient = user.getName().equals("Deleted User") ? deletedUserClient : user.getClient();
    clientsForThatDay.add(userClient);
   }
} catch (Exception e) {
   log.error("Error getting client from user: ", e);
}

但是,它并没有返回null,它只是抛出异常,然后停止。**我如何才能让它在这里返回null,这样我就可以在不停止代码的情况下处理丢失的记录?**提前感谢您的建议。

oxalkeyp

oxalkeyp1#

您的数据库似乎缺少外键约束。这意味着表MapUser引用了Client表中不再存在的行。
只有在删除了客户端而没有更新用户表的情况下才会发生这种情况。解决方法是在表之间添加外键约束。
请记住,如果表中的数据不正确,当Hibernate加载实体User时,它也会认为存在一个客户端。这意味着User#getClient不会为空,代码中的每个地方都将出现类似user.getClient() == null的检查。try-catch方法在这方面没有帮助(我猜,除非在出错的情况下将关联设置为null)。
我能想到的解决方案:
1.添加外键约束(imho,最佳解决方案)
1.不要Map关联,将client_idMap为属性,然后使用第二个查询或find加载客户端(只有在无法更新数据库时,我才会这样做)

class User {
    @Column(name = "client_id")
    Long clientId;
}

User user = ...
Client client = session.find(Client.class, user.getClientId());

1.您可以通过session.find(Client.class, user.getClient().getId())加载客户端并设置与结果的关联:

User user = //...
Client client = session.find(Client.class, user.getClient().getId());
user.setClient(client);

1.根本不要在User中Map关联,并运行本机SQL查询来加载客户端:

User user = ...
String sql = "select * from Client c join User u on c.id = u.client_id where u.id = :uid";
Client client = session.createNativeQuery(sql, Client.class)
    .setParameter("uid", user.getId())
    .getSingleResultOrNull();

您可以选择最适合您的方法,但请记住,Map没有外键约束的关联将导致各种一致性问题。
我之所以选择选项3,只是因为有时候人们在工作中会遇到一些不可能的情况,但我不会推荐它。

相关问题