You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

EclipseLink JPA保存User实体后无法通过username查询到该实体

我使用EclipseLink作为JPA实现时遇到以下问题:保存User实体后,立即通过EntityManager以username字段为条件查询该实体,无法找到对应结果。

相关代码

User.java

@Entity
@Table(name = "users")
public class User implements DbObject {

   @Transient
   private static final long serialVersionUID = 1L;
   @Id
   @GeneratedValue(strategy = GenerationType.AUTO)
   @Column(nullable = false, updatable = false)
   private long id;
   @Column(nullable = false)
   private String password;
   @ManyToMany
   @JoinTable(name = "users_roles", joinColumns = @JoinColumn(name = "users_id"), inverseJoinColumns = @JoinColumn(name = "roles_id"))
   private Set<Role> roles;
   @Column(name = "username", nullable = false, unique = true, updatable = false)
   private String username;

   public User() {
   }

   public User(long id, String username, String password, Set<Role> roles) {
      this.id = id;
      this.username = username;
      this.password = password;
      this.roles = roles;
   }

   @Override
   public Object clone() {
      return id == 0 && StringUtils.isNullOrEmpty(username) && StringUtils.isNullOrEmpty(password) && roles.isEmpty()
            ? new User()
            : new User(id, username, password, roles);
   }

   @Override
   public boolean equals(Object o) {
      if (o == this) {
         return true;
      }
      if (o instanceof User) {
         final User u = (User) o;
         // only check name, since role names should be unique across an entire
         // application:
         return getUsername() != null ? getUsername().equals(u.getUsername()) : u.getUsername() == null;
      }
      return false;
   }

   @Override
   public long getId() {
      return id;
   }

   public String getPassword() {
      return password;
   }

   public Set<Role> getRoles() {
      return roles;
   }

   public String getUsername() {
      return username;
   }

   @Override
   public int hashCode() {
      return getUsername() != null ? getUsername().hashCode() : 0;
   }

   @Override
   public void setId(long id) {
      this.id = id;
   }

   public void setPassword(String password) {
      this.password = password;
   }

   public void setRoles(Set<Role> roles) {
      this.roles = roles;
   }

   public void setUsername(String username) {
      this.username = username;
   }

   @Override
   public String toString() {
      return getUsername();
   }

}

UserService.java

public class UserServiceImpl implements UserService {

   private final UserRepository userRepository;

   @Inject
   public UserServiceImpl(final UserRepository userRepository) {
      this.userRepository = userRepository;
   }

   @Override
   public Optional<User> findByName(final String username) {
      return userRepository.findByColumnValue("username", username).stream().findAny();
   }

   @Override
   public AbstractJpaRepository<User, Long> getRepository() {
      return userRepository;
   }

}

AbstractJpaRepository接口

public interface AbstractJpaRepository<T, ID> {

   default void delete(ID id) {
      final EntityManager entityManager = getEntityManager();
      final T toBeRemoved = entityManager.getReference(getType(), id);
      entityManager.remove(toBeRemoved);
   }

   default ObservableList<T> findAll() {
      final EntityManager entityManager = getEntityManager();

      final CriteriaQuery<T> criteriaQuery = entityManager.getCriteriaBuilder().createQuery(getType());
      criteriaQuery.from(getType());

      final ObservableList<T> list = FXCollections
            .observableArrayList(entityManager.createQuery(criteriaQuery).getResultList());
      return list;
   }

   default List<T> findByColumnValue(final String columnHeader, final String columnValue) {
      final EntityManager entityManager = getEntityManager();
      final CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();

      final CriteriaQuery<T> criteriaQuery = criteriaBuilder.createQuery(getType());

      final Root<T> from = criteriaQuery.from(getType());

      criteriaQuery.select(from);
      criteriaQuery.where(criteriaBuilder.equal(from.get(columnHeader), columnValue));

      final TypedQuery<T> typed = entityManager.createQuery(criteriaQuery);
      return typed.getResultStream().collect(Collectors.toList());
   }

   default Optional<T> findById(final ID id) {
      final EntityManager entityManager = getEntityManager();
      return Optional.ofNullable(entityManager.find(getType(), id));
   }

   EntityManager getEntityManager();

   Class<T> getType();

   default T save(final T t) {
      final EntityManager entityManager = getEntityManager();
      for (final DatabaseField dbf : entityManager.unwrap(Session.class).getDescriptor(User.class).getFields()) {
         System.out.println(dbf.getName());
      }
      return entityManager.merge(t);
   }

}

补充说明

保存实体时,我遍历过该实体的DatabaseField,确认username字段存在,但查询时始终返回空Optional。近期将项目POM依赖迁移到Jakarta,怀疑是EclipseLink版本更新引发的bug。测试数据中已创建username为testUser1的用户,但登录时因查询不到该实体抛出异常,急需解决。

内容的提问来源于stack exchange,提问作者Michl

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 05:00:40