如何从Spring Boot中的实体访问存储库?

时间:2017-09-07 09:26:33

标签: java spring jpa spring-boot

在Spring Boot项目中,我有一个JPA实体,如下所示:

@Entity
public class Account {
}

然后我有了查询数据库的存储库:

public interface AccountRepository extends JpaRepository<Account, UUID> {

}

在应用程序和测试中,通过执行以下操作很容易获得存储库:

@Autowired
private AccountRepository accountRepository;

如何在Account类的方法中获取存储库?我试过@Autowired但它没有用。

对于那些争论设计的人,我的问题不是关于设计。我已经在Ruby和Rails以及带有HugSQL的Clojure中编写了这个代码,它是自包含和简洁的:在创建新记录时,我还生成一个紧凑的唯一字母数字id。在Ruby on Rails中,我将其作为库发布:https://github.com/pupeno/random_unique_id

5 个答案:

答案 0 :(得分:0)

我猜你正试图在Hibernate中实现类似Active Record pattern的东西。这很不寻常,但您可以使用@Configurable对您的实体进行注释,以便内部@Autowired能够工作(同时确保实体包在@ComponentScan范围内)

答案 1 :(得分:0)

您必须使用@GenericGenerator@GeneratedValue查看示例here。请注意,在IdentifierGenerator实现中,您可以访问存储库。

如果这是针对非id字段的,那么解决方法是创建一个新实体GeneralSequenceNumber并且其ID是必需的生成ID,然后在GeneralSequenceNumberAccount之间进行一对一映射。您的@Entity public class GeneralSequenceNumber { @Id @GenericGenerator(name = "sequence_dep_id", strategy = "com.xyz.ids.DepartmentIdGenerator") @GeneratedValue(generator = "sequence_dep_id") @Column(name="Department_Id") private String deptId; } @Entity public class Account { @Id .. private Long id; @OneToOne(...) private GeneralSequnceNumber myVal; } 实体(如上所述here

{{1}}

答案 2 :(得分:0)

您可以从静态方法访问Spring Application Context并使用此静态方法在您的@Entity类中加载您的存储库bean,而不是自动装配它。

您需要创建以下类(找到here):

ApplicationContextProvider

@Component
public class ApplicationContextProvider implements ApplicationContextAware {

    private static ApplicationContext context;

    public ApplicationContext getApplicationContext() {
        return context;
    }

    @Override
    public void setApplicationContext(ApplicationContext ctx) {
        context = ctx;
    }
}

SpringConfiguration

@Configuration
public class SpringConfiguration {

    @Bean
    public static ApplicationContextProvider contextProvider() {
        return new ApplicationContextProvider();
    }

}

然后

@Entity
public class Account {
    //your code

    public void doAccountRepositoryStuff() {
        AccountRepository accountRepository = (AccountRepository) SpringConfiguration.contextProvider().getApplicationContext().getBean("accountRepository");
        // Do your own stuff with accountRepository here...
    }
}

答案 3 :(得分:0)

我有同样的问题,发现this Github repository

以下是部分代码:

...
import de.ck35.example.ddd.jpa.SpringEntityListener;
...

@Entity
@Table(name="bookshelf")
@EntityListeners(SpringEntityListener.class)
public class BookshelfEntity implements Bookshelf {

    ...


    private String category;

    @Autowired transient BookRepository bookRepository;
    @Autowired transient BookshelfSpaceRepository bookshelfSpaceRepository;

de.ck35.example.ddd.jpa.SpringEntityListenerJavadoc目的的描述:

/**
 * Entity listener which allows dependency injection inside entities.
 * The listener can be registered via {@link EntityListeners} annotation.
 * 
 * Dependency injection annotations like {@link Autowired} are supported.
 * 
 * @author Christian Kaspari
 * @since 1.0.0
 */
public class SpringEntityListener {

    ...

    @PostLoad
    @PostPersist
    public void inject(Object object) {
        AutowireCapableBeanFactory beanFactory = get().getBeanFactory();
        if(beanFactory == null) {
            LOG.warn("Bean Factory not set! Depdendencies will not be injected into: '{}'", object);
            return;
        }
        LOG.debug("Injecting dependencies into entity: '{}'.", object);
        beanFactory.autowireBean(object);
    }

还有一种配置可以启用嵌套在类(在本例中为实体)中的存储库定义:

@Configuration
@EnableJpaRepositories(basePackages="de.ck35.example.ddd.jpa", considerNestedRepositories=true)
@ComponentScan("de.ck35.example.ddd.jpa")
public class JpaConfiguration {

感谢此存储库的作者Christian Kaspari

答案 4 :(得分:0)

我在项目中看到了下面的方法,因为该项目没有Service层。老实说,我建议添加Service层而不是这些解决方案,但是如果您确实要/必须使用它,请参见下面的解决方案。

创建存储库界面

public interface BookRepository extends JpaRepository<Book, String> {
}

创建组件

@Component
public class Registry {

private static BookRepository bookRepository;

static BookRepository bookRepo() {
    return bookRepository;
}

}

通过使用组件中的静态功能实现回购

import static com.x.Registry.bookRepo;
@Entity
class Book {
    public static List<Book> all() {
        return bookRepo().findAll();
    }
}