2013-02-27 25 views
14

Tôi đang cố gắng tham chiếu giao diện kho lưu trữ của mình (UserRepository) mở rộng CrudRepository trong triển khai tùy chỉnh của mình (UserRepositoryExtensionImpl) để truy cập vào tất cả các phương pháp do Spring JPA cung cấp.CrudRepository bên trong triển khai kho lưu trữ tùy chỉnh của tôi

CRUD mở rộng: Giao diện

@Repository 
public interface UserRepository extends CrudRepository<User, String>, UserRepositoryExtension<RosterUser> { 
    ...any custom spring JPA methods... 
} 

Extension:

@Repository 
public interface UserRepositoryExtension <T> { 
    public T put(T entity); 
} 

Tuỳ chỉnh thực hiện:

public class UserRepositoryExtensionImpl implements UserRepositoryExtension<User> { 

    UserRepository userRepository; 

    @Autowired 
    public UserRepositoryExtensionImpl(UserRepository userRepository) { 
     this.userRepository = userRepository; 
    } 

    @Override 
    public User put(User user) { 
     System.out.println(user + "was put"); 
     // ...put logic here 
     return null; 
    }... 
} 

Tuy nhiên, tôi không thể tiêm UserRepository kể từ khi một phụ thuộc chu trình tồn tại (cho rằng UserRepository mở rộng giao diện được triển khai bởi của tôi UserRepositoryImpl). Tôi nhận được lỗi sau:

org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name ' userRepositoryImpl': Requested bean is currently in creation: Is there an unresolvable circular  reference? 

Một có thể, nhưng ít hơn giải pháp lý tưởng sẽ được tiêm và EntityManager vào UserRepositoryImp, nhưng trong trường hợp đó, tôi không có quyền truy cập vào bất kỳ phương pháp xuân JPA được cung cấp bởi CrudRepository hoặc bất kỳ phương thức bổ sung nào mà tôi có thể đã tạo trong UserRepository.

Bất kỳ đề xuất nào về cách giải quyết vấn đề này?

Mọi trợ giúp sẽ được đánh giá cao.

EDIT: Như đã đề cập trong câu trả lời @ shelley, tôi đã có thể giải quyết việc này bằng cách làm cho 3 thay đổi:

  • Loại bỏ các @Repository từ UserRepositoryExtensionImpl
  • Đổi tên UserRepositoryExtensionImpl để UserRepositoryImpl. Rõ ràng điều này làm cho Spring nhận thức được sự tồn tại của thực hiện. Xem Spring Doc
  • Loại bỏ constructor của tôi và di chuyển @Autowired đến userRepository lĩnh vực

THÀNH CÔNG!

+0

Nếu không có bất kỳ phụ thuộc chu trình thực tế (ví dụ: Mùa xuân chỉ bị lẫn lộn vì nó nghĩ rằng bạn có nhiều đậu các loại tương tự). Thêm bổ sung vòng loại như id đậu để Spring biết đậu nào để autowire. – gerrytan

+0

cung cấp cho chúng tôi ngữ cảnh ứng dụng mùa xuân của bạn – Elbek

+1

@gerrytan - Tôi có thể sai, nhưng tôi nghĩ rằng có sự phụ thuộc vòng tròn. FYI: Cùng một vấn đề đang được tham chiếu [ở đây] (http://forum.springsource.org/showthread.php?132889-Spring-Data-Calling-default-CRUD-methods-inside-a-custom-repository-implementation&p= 439701 # post439701) –

Trả lời

9

Một vài điều nhỏ cần phải được thay đổi trong trật tự để làm việc này:

  • Tháo @Repository chú thích từ giao diện kho lưu trữ tùy chỉnh (UserRepositoryExtension).

  • Triển khai kho tùy chỉnh thực sự nên được đặt tên là "<StandardRepository>Impl" thay vì "<CustomRepository>Impl". Trong ví dụ về mã của bạn, số này phải là UserRepositoryImpl thay vì UserRepositoryExtensionImpl.

+0

Cảm ơn @shelley! Đề xuất của bạn, ngoài việc di chuyển '@ Autowired' từ hàm tạo sang trường' userRepository' đã giải quyết được vấn đề. Bây giờ tôi có thể tham khảo 'UserRepository' trong triển khai tùy chỉnh của tôi. :) –

0

Có một số well defined way to create custom repository implementations in Spring Data JPA mà bạn nên làm theo. Về cơ bản bạn cần mở rộng CrudRepository để bạn không phải tiêm một thể hiện của nó trong triển khai tùy chỉnh của bạn.

+0

Tôi nghĩ OP đang theo cách tiếp cận đó nhưng muốn sử dụng các phương thức từ bean kho tiêu chuẩn trong triển khai kho lưu trữ tùy chỉnh. – shelley

+0

@zagyi, Shelley là chính xác. Tôi đang cố gắng làm theo cách tiếp cận rất giống với Mùa xuân gợi ý, và đây là cách tôi tìm thấy chính mình ở vị trí tôi đang ở. Tôi sẽ thêm nhiều chi tiết hơn cho câu hỏi để làm cho vấn đề rõ ràng hơn. –

+0

@shelley, @Julian: xin lỗi, sau khi đọc kỹ lại câu hỏi, rõ ràng là tôi đã hiểu nhầm nó. Tuy nhiên tôi nghĩ đó là một điều kỳ lạ mà Julian cố gắng làm. Thông thường đó là một lớp dịch vụ mà bạn sẽ tiêm các cá thể lưu trữ và thực hiện các phương thức mức cao hơn gọi một hoặc nhiều hoạt động kho lưu trữ. Kiểm tra wheter nó sẽ có ý nghĩa hơn để di chuyển logic của 'put()' một cấp cao hơn vào một giao diện/lớp dịch vụ. – zagyi

0

Tôi đã giải quyết vấn đề bằng cách tiêm ApplicationContext và nhận đậu theo cách lười biếng bằng cách sử dụng applicationContext.getBean(UserRepository.class). Nó hoạt động theo cách này.

4

Như shelley chỉ ra, việc đặt tên thực sự quan trọng để làm cho autowire hoạt động. Trong ví dụ bên dưới, tôi thực hiện theo tiêu chuẩn đặt tên phù hợp cho giao diện tùy chỉnh của tôi và triển khai của nó. Nhưng giao diện của tôi mở rộng JpaRepository được đặt tên là “ItemDao” thay vì “ItemRepository”, điều này dẫn đến mùa xuân đó bỏ qua việc triển khai tùy chỉnh của tôi hoàn toàn ...

OBS !!! Cần được "ItemRepository"

@Repository 
public interface ItemDao extends JpaRepository<Item, Long>, ItemRepositoryCustom {} 

giao diện của tôi

interface ItemRepositoryCustom {...} 

lớp thực hiện của tôi

class ItemRepositoryImpl implements ItemRepositoryCustom {...} 

Nếu ai có vấn đề tương tự, hãy bắt đầu bằng cách làm theo các tiêu chuẩn đặt tên được sử dụng trong tài liệu xuân tại liên kết bên dưới.

http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.custom-implementations

+1

Tôi ước rằng các chi tiết như thế này đã được đề cập rõ ràng hơn ... Nhưng yea, việc đặt tên có vẻ khá quan trọng. Vui mừng bạn đã có thể tìm ra nó quá! –

+1

Tôi, khi bạn đọc một phần của tài liệu mà không có kiến ​​thức trước khi mùa xuân, không có cách nào để tìm ra quy tắc đặt tên nghiêm ngặt như thế nào. – Olle89

Các vấn đề liên quan