【问题标题】:Spring JPA Composite key: This class does not define an IdClassSpring JPA 复合键:此类未定义 IdClass
【发布时间】:2020-06-10 08:31:34
【问题描述】:

在应用运行时出错 This class [class com.socnetw.socnetw.model.Relationship] does not define an IdClass。 当我使用 EntityManager 时,一切都很好。但现在我切换到 Spring CrudRepository<T, T> 并收到此错误。我知道关于映射主键约束的问题。但是我到底应该做什么我不知道。有人可以帮忙处理吗?

Relationship.class

@Table(name = "RELATIONSHIP")
@Getter
@Setter
@Entity
@ToString
@EqualsAndHashCode
public class Relationship implements Serializable {
    @Id
    private Long userIdFrom;
    @Id
    private Long userIdTo;
    @Enumerated(EnumType.STRING)
    private RelationshipStatus status;
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "YYYY-MM-DD HH:mm:ss")
    private LocalDate friendsRequestDate;
}

RelationshipRepository.class 仅用于案例

public interface RelationshipRepository extends CrudRepository<Relationship, Long> {

    @Query(value = "some query", nativeQuery = true)
    Long findAmountOfFriends(@Param("userId") Long userId);  
    ...other methods

}

DataInit.class

@Component
public class DataInit implements ApplicationListener<ContextRefreshedEvent> {
    private UserRepository userRepository;
    private PostRepository postRepository;
    private RelationshipRepository relationshipRepository;
    private MessageRepositorys messageRepository;

    public DataInit(UserRepository userRepository, PostRepository postRepository, RelationshipRepository relationshipRepository, MessageRepositorys messageRepository) {
        this.userRepository = userRepository;
        this.postRepository = postRepository;
        this.relationshipRepository = relationshipRepository;
        this.messageRepository = messageRepository;
    }

    @Override
    @Transactional
    public void onApplicationEvent(ContextRefreshedEvent event) {
     //here I create users and save them
    ...
    ...
    ...
    userRepository.save(someUser);


    relationshipRepository.save(relationship);
    messageRepository.save(message);

    }
}

错误

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'dataInit' defined in file [C:\Users\tpmylov\Desktop\learning\Projects\socnetw\target\classes\com\socnetw\socnetw\bootstrap\DataInit.class]: Unsatisfied dependency expressed through constructor parameter 2; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'relationshipRepository': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: This class [class com.socnetw.socnetw.model.Relationship] does not define an IdClass
...
...
...
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'relationshipRepository': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: This class [class com.socnetw.socnetw.model.Relationship] does not define an IdClass

【问题讨论】:

    标签: java spring hibernate orm spring-data-jpa


    【解决方案1】:

    您的实体Relationship 声明假定使用composite primary key。因此,您应该通过以下方式更正您的实体:

    @Table(name = "RELATIONSHIP")
    @Getter
    @Setter
    @Entity
    @ToString
    @EqualsAndHashCode
    @IdClass(RelationshipPK.class)
    public class Relationship implements Serializable {
        @Id
        private Long userIdFrom;
        @Id
        private Long userIdTo;
        @Enumerated(EnumType.STRING)
        private RelationshipStatus status;
        @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "YYYY-MM-DD HH:mm:ss")
        private LocalDate friendsRequestDate;
    }
    

    然后RelationshipPK:

    public class RelationshipPK implements Serializable {
    
        private Long userIdFrom;
        private Long userIdTo;
    
        public RelationshipPK(Long userIdFrom, Long userIdTo) {
            this.userIdFrom = userIdFrom;
            this.userIdTo = userIdTo;
        }
    
        public RelationshipPK() {
        }
    
        //Getters and setters are omitted for brevity
    
        @Override
        public boolean equals(Object o) {
            if ( this == o ) {
                return true;
            }
            if ( o == null || getClass() != o.getClass() ) {
                return false;
            }
            RelationshipPK pk = (RelationshipPK) o;
            return Objects.equals( userIdFrom, pk.userIdFrom ) &&
                    Objects.equals( userIdTo, pk.userIdTo );
        }
    
        @Override
        public int hashCode() {
            return Objects.hash( userIdFrom, userIdTo );
        }
    }
    

    您的CrudRepository 应该有以下视图:

    public interface RelationshipRepository extends CrudRepository<Relationship, RelationshipPK>
    {
    
        @Query(value = "some query", nativeQuery = true)
        Long findAmountOfFriends(@Param("userId") Long userId);  
        ...other methods
    
    }
    

    实际上,hibernate 允许声明一个复合键并且没有这些东西。这就是所谓的composite identifiers with associations。但是对于下面的CrudRepository方法是必须的:

    public interface CrudRepository<T,ID> extends Repository<T,ID>
    {
       void deleteById(ID id);
    
       boolean existsById(ID id);
    
       Iterable<T> findAllById(Iterable<ID> ids);
    
       Optional<T>  findById(ID id);
    
       // ...
    }
    

    【讨论】:

      【解决方案2】:

      你有一个复合键:

      @Id
      private Long userIdFrom;
      @Id
      private Long userIdTo;
      

      为此,您必须创建一个 IdClass:

      public class RelationshipId implements Serializable {
          private Long userIdFrom;
          private Long userIdTo;
      
          // Getter and Setter
      }
      

      然后就可以在课堂上使用了

      @IdClass(RelationshipId.class)
      public class Relationship ....
      

      在存储库上:

      public interface RelationshipRepository 
                       extends CrudRepository<Relationship, RelationshipId> {
      
          @Query(value = "some query", nativeQuery = true)
          Long findAmountOfFriends(@Param("userId") Long userId);  
          ...other methods
      }
      

      在官方 Hibernate 文档中了解有关复合键的更多信息:

      https://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html#identifiers-composite

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-04-08
        • 2019-12-24
        • 1970-01-01
        • 1970-01-01
        • 2016-11-08
        • 1970-01-01
        相关资源
        最近更新 更多