Spring Java Config DI определения и ("конкретный интерфейс") JpaRepository - PullRequest
0 голосов
/ 29 октября 2019

У меня есть следующий код.

Обратите внимание, что у меня есть интерфейс MySuperCoolEntityRepositoryContract.

И у меня есть «конкретный интерфейс» MySuperCoolEntityJpaRepository, который реализует мой вышеупомянутый интерфейс MySuperCoolEntityRepositoryContory * 100 и Jpa.

Все это прекрасно работает с @ ComponentScan.

Я изменяю свой код на "java config", то есть централизованное место, где я могу кодировать свои определения DI. (Также известный как CompositionRoot в некоторых кругах).

Проблема заключается в том, когда я пытаюсь «закодировать» бетон для интерфейса. (Перейдите к этому вопросу позже.

package com.me.domain.jpaentities;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Transient;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.Objects;
import java.util.Set;

@Entity(name = "MySuperCoolEntityTableName")
public class MySuperCoolEntity implements Serializable {

    @Id
    @Column(name = "CoolSurrogateKeyColumn")
    private String coolSurrogateKey;

    @Column(name = "CoolMagicValueColumn")
    private String coolMagicValue;


    public String getCoolSurrogateKey() {
        return this.coolSurrogateKey;
    }

    public void setCoolSurrogateKey(String coolSurrogateKey) {
        this.coolSurrogateKey = coolSurrogateKey;
    }

    public String getCoolMagicValue() {
        return this.coolMagicValue;
    }

    public void setCoolMagicValue(String coolMagicValue) {
        this.coolMagicValue = coolMagicValue;
    }

}

===============

package com.me.dal.repositories.interfaces;

import com.me.domain.jpaentities.MySuperCoolEntity;
import java.util.Collection;

public interface MySuperCoolEntityRepositoryContract {

    Collection<MySuperCoolEntity> findByCoolMagicValue(String coolMagicValue);

}

=========================

package com.me.dal.repositories;

import com.me.dal.repositories.interfaces.MySuperCoolEntityRepositoryContract;
import com.me.domain.jpaentities.MySuperCoolEntity;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.Collection;

@Repository
public interface MySuperCoolEntityJpaRepository extends MySuperCoolEntityRepositoryContract, JpaRepository<MySuperCoolEntity,String> {

    Collection<MySuperCoolEntity> findByCoolMagicValue(String coolMagicValue);

}

Теперь эта проблема.

package com.me.myapplication.configuration;

import com.me.dal.repositories.MySuperCoolEntityJpaRepository;
import com.me.dal.repositories.interfaces.MySuperCoolEntityRepositoryContract;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MyCompositionRoot {


    @Bean
    public MySuperCoolEntityRepositoryContract getAMySuperCoolEntityRepositoryContract()
    {
        return new MySuperCoolEntityJpaRepository();  /* << issue is here, this is an abstract class, aka, an interface with some methods defined */
    }

}

Использование очень крутого JpaRepository "конкретного интерфейса" aka "действительно абстрактный класс, но называется интерфейс "aka" Методы интерфейса по умолчанию "(см. https://dzone.com/articles/interface-default-methods-java) ........

Точная ошибка:

MySuperCoolEntityJpaRepository is abstract; cannot be instantiated

Я понимаю ошибку. MySuperCoolEntityJpaRepository является абстрактным. Я получаю это.

Но с этим супер крутым "просто расширьте JpaRepository и получите все виды функциональности по умолчанию" .....

Как зарегистрировать конкретный JpaRepository в Spring DI (в частности, с помощью java config «code it up»?

............

Я попытался сделать это"class".

public class MySuperCoolEntityJpaRepository extends MySuperCoolEntityRepositoryContract, JpaRepository<MySuperCoolEntity,String>

, но он хочет, чтобы я определил все встроенные методы, такие как "findAll" и т. д. и т. д.

Ответы [ 2 ]

0 голосов
/ 30 октября 2019

Я нашел обходной путь. Мне это не очень нравится, но я думаю, что это работает.

Я также добавил MySuperCoolEntityBalServiceContract (вы можете получить идею только из приведенного ниже), так что вы знаете, почему / как мне нужен метод getAMySuperCoolEntityRepositoryContract вмой класс CompositionRoot ниже.

Я оставлю это (не отмечено) в качестве ответа на случай, если кто-то другой выберет лучший путь или увидит проблемы с нижеуказанным. Мне не нравится, как работает EntitiyManager, но он заставляет все двигаться.

package com.me.myapplication.configuration;


import com.me.apicore.managers.MySuperCoolEntityBalService;
import com.me.apicore.managers.interfaces.MySuperCoolEntityBalServiceContract;
import com.me.dal.repositories.interfaces.MySuperCoolEntityRepositoryContract;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.support.JpaRepositoryFactory;
import org.springframework.data.repository.core.support.RepositoryFactorySupport;

import javax.inject.Inject;
import javax.persistence.EntityManager;

@Configuration

public class MyCompositionRoot {

    @Inject
    private EntityManager entManager; /* part of the work around trick */

    @Bean
    public MySuperCoolEntityBalServiceContract getAMySuperCoolEntityBalServiceContract() {
        return new MySuperCoolEntityBalService(this.getAMySuperCoolEntityRepositoryContract());
    }


    @Bean
    public MySuperCoolEntityRepositoryContract getAMySuperCoolEntityRepositoryContract() {
        //return new MySuperCoolEntityJpaRepository(); /* does not work.  :(         */
        RepositoryFactorySupport factory = new JpaRepositoryFactory(entManager);
        MySuperCoolEntityRepositoryContract repository = factory.getRepository(MySuperCoolEntityRepositoryContract.class);
        return repository;
    }
}

И я подправил это (обратите внимание на добавление аннотации RepositoryDefinition)

package com.me.dal.repositories.interfaces;

import com.me.domain.jpaentities.MySuperCoolEntity;

import org.springframework.data.repository.RepositoryDefinition;

import java.util.Collection;

@RepositoryDefinition(domainClass = MySuperCoolEntity.class, idClass = String.class)

public interface MySuperCoolEntityRepositoryContract {

    Collection<MySuperCoolEntity> findByCoolMagicValue(String coolMagicValue);

}
0 голосов
/ 30 октября 2019

Spring boot волшебным образом обеспечивает реализацию методов, определенных в вашем интерфейсе. @EnableJpaRepositories сканирует все пакеты ниже пакета на наличие интерфейсов, расширяющих JpaRepository , и создает для него bean-компонент Spring, который поддерживается реализацией SimpleJpaRepository (данные Spring предоставляют значения по умолчанию для хранилища CRUD. через этот класс).

Ваш интерфейс MySuperCoolEntityJpaRepository расширяет интерфейс MySuperCoolEntityRepositoryContract, но вы расширяете JpaRepository только на интерфейсе MySuperCoolEntityJpaRepository, что означает, что spring предоставит реализации по умолчанию только для методов в интерфейсе MySuperCoolEntityJpaRepository. Попробуйте это следующим образом:

public interface MySuperCoolEntityRepositoryContract extends JpaRepository<MySuperCoolEntity,String>{

    Collection<MySuperCoolEntity> findByCoolMagicValue(String coolMagicValue);

}

, затем расширьте это в своем хранилище, например:

@Repository
public interface MySuperCoolEntityJpaRepository extends MySuperCoolEntityRepositoryContract {

    Collection<MySuperCoolEntity> findByCoolMagicValue(String coolMagicValue);

}

Related Post: Как работает аннотация @Repository в java spring?

...