Spring Boot: «Для поля требуется bean-компонент типа« javax.persistence.EntityManagerFactory », который не найден». - PullRequest
0 голосов
/ 23 января 2020

У меня есть проект java, который использует Spring Boot с JPA и Hibernate для базы данных. Я пытаюсь собрать микросервис, который обращается к базе данных. (Я новичок в микросервисах и Spring Boot).

Ниже приведен основной класс:

@SpringBootApplication
@RestController
@EnableAutoConfiguration
@EnableJpaRepositories
public class CircularsMicroservice {

    @Autowired
    private CircularsService circularsService;



    //microservice called here
    @RequestMapping(value="/circulars-list", method=RequestMethod.POST)
    List<GmCirculars> getAllCircularsForOrganization(@RequestBody  CircularsParams circularsParams)
    {


        List<GmCirculars> circularsList =
                circularsService.fetchAllCircularsForOrganization(circularsParams.getOrganization(), circularsParams.isActiveOnly(), circularsParams.getStartOffset());//invoke the method to get the circulars list
        return circularsList;
    }

    public static void main(String[] args) throws Exception{ 


        SpringApplication springApp= new SpringApplication(CircularsMicroservice.class);

        Map<String, Object> prop= new HashMap<String, Object>();
        prop.put("spring.application.name", "circulars-microservice");
        prop.put("server.port", "8081");
        prop.put("spring.jpa.properties.hibernate.current_session_context_class", "org.springframework.orm.hibernate5.SpringSessionContext");

        //db config
        prop.put("spring.datasource.driver-class-name", "oracle.jdbc.driver.OracleDriver");
        prop.put("spring.datasource.url", "--");
        prop.put("spring.datasource.username", "--");
        prop.put("spring.datasource.password", "--");
        prop.put("spring.jpa.show-sql", "false");
        prop.put("spring.jpa.hibernate.ddl-auto", "create-drop");
        prop.put("spring.jpa.properties.hibernate.dialect", "org.hibernate.dialect.Oracle10gDialect");

        springApp.setDefaultProperties(prop); //configure programmatically

        springApp.run(args);
        System.out.println("done");


    }    



}

IGmCircularsDAO.class:

@Repository
public interface IGmCircularsDAO {


    /**
     * Save or update.
     *
     * @param obj the obj
     * @return the gm circulars
     */
    GmCirculars saveOrUpdate(GmCirculars obj);




    /**
     * Mark as deleted.
     *
     * @param rowId the row id
     * @return true, if successful
     */
    boolean markAsDeleted(BigDecimal rowId);



    /**
     * Find.
     *
     * @param obj the obj
     * @param activeOnly the active only
     * @param startOffset the start offset
     * @param maxRows the max rows
     * @return the list
     */
    List<GmCirculars> find(GmCirculars obj, boolean activeOnly, int startOffset, int maxRows);



}

GMCircularsDAOImpl.class:

@Repository
@Transactional
@SuppressWarnings("unchecked")
public class GmCircularsDaoImpl extends ParentDAO implements IGmCircularsDAO {

    @Override
    public GmCirculars saveOrUpdate(GmCirculars obj) {

        Session session = null;

        try {
            //session = sessionFactory.openSession(); //commented by Zaid
            session= this.getSession(); //Added by Zaid

            session.beginTransaction();
            session.saveOrUpdate(obj);
            session.flush();
            session.getTransaction().commit();

        }
        catch (Exception ex) {
            ex.printStackTrace();
        }
        finally {
            session.close();
        }
        return obj;
    }


    @Override
    public List<GmCirculars> find(GmCirculars obj, boolean activeOnly, int startOffset, int maxRows) {
        Session session = null;
        List<GmCirculars> discounts = null;

        try {
            if (null != obj) {

                //session = sessionFactory.openSession(); //commented by Zaid
                session= this.getSession(); //Added by Zaid

                Criteria criteria = session.createCriteria(GmCirculars.class);

                if (null != obj.getId() && !BigDecimal.ZERO.equals(obj.getId())) {
                    criteria.add(Restrictions.eq("id", obj.getId()));
                }

                if (StringUtil.isNotNullOrEmpty(obj.getTitle())) {
                    criteria.add(Restrictions.ilike("title", obj.getTitle(), MatchMode.ANYWHERE));
                }

                if(null != obj.getOrganization()) {
                    criteria.add(Restrictions.eq("organization", obj.getOrganization()));
                }

                //commented by zaid
                /*if (null != obj.getType() && null != obj.getType().getValueId() && !BigDecimal.ZERO.equals(obj.getType().getValueId())) {
                    criteria.add(Restrictions.eq("type.valueId", obj.getType().getValueId()));
                }*/


                if (null != obj.getSerialNo() && !BigDecimal.ZERO.equals(obj.getSerialNo())) {
                    criteria.add(Restrictions.eq("serialNo", obj.getSerialNo()));
                }

                if (null != obj.getYear() && !BigDecimal.ZERO.equals(obj.getYear())) {
                    criteria.add(Restrictions.eq("year", obj.getYear()));
                }


                if (activeOnly) {
                    criteria.add(Restrictions.eq("active", BigDecimal.ONE));
                }
                else {
                    criteria.add(Restrictions.or(Restrictions.ne("active", CommonConstants.DELETED_STATUS), Restrictions.isNull("active"))); //Except for deleted ones -> NVL(active,2)
                }


                //LIMIT startOffset, maxRows;
                criteria.setFirstResult(startOffset);
                criteria.setMaxResults(maxRows);

                criteria.addOrder(Order.desc("id"));
                criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
                discounts = criteria.list();

            }

        }
        catch (Exception e) {
            e.printStackTrace();
        }
        finally {
            session.close();
        }
        return discounts;
    }


    @Override
    public boolean markAsDeleted(BigDecimal rowId) {

        Session session = null;
        int updatedRows = 0;
        try {

            //session = sessionFactory.openSession(); //commented by Zaid
            session= this.getSession(); //Added by Zaid

            Query query = session.createQuery("update GmCirculars set active = :statusForDel where id = :rowId");
            query.setParameter("statusForDel", CommonConstants.DELETED_STATUS);
            query.setParameter("rowId", rowId);

            updatedRows = query.executeUpdate();
            session.flush();
        }
        catch (Exception ex) {
            ex.printStackTrace();
        }
        finally {
            session.close();
        }

        return updatedRows > 0;
    }


}

ParentDAO.class

@Transactional
public class ParentDAO {

    //commented by zaid
    //@Autowired
    //protected SessionFactory sessionFactory;

        //added by Zaid //spring boot way
        //@Autowired

        @PersistenceContext
        protected EntityManager entityManager;

        protected Session getSession() {
            return entityManager.unwrap(Session.class);

        }



}

CircularsService.class

@org.springframework.stereotype.Service
public class CircularsService {

    @Autowired
    private IGmCircularsDAO gmCircularDao;



    @Value("${circulars.maxRows}")
    private int circularsMaxRows;


    /**
     * Save or update.
     *
     * @param obj the obj
     * @return the gm circulars
     */
    public GmCirculars saveOrUpdate(GmCirculars obj) {
        return gmCircularDao.saveOrUpdate(obj);
    }


    /**
     * Find.
     *
     * @param obj the obj
     * @param activeOnly the active only
     * @param startOffset the start offset
     * @return the list
     */
    public List<GmCirculars> find(GmCirculars obj, boolean activeOnly, int startOffset) {
        return gmCircularDao.find(obj, activeOnly, startOffset, circularsMaxRows);
    }


    /**
     * Fetch all circulars for organization.
     *
     * @param userOrg the user org
     * @param activeOnly the active only
     * @param startOffset the start offset
     * @return the list
     */
    public List<GmCirculars> fetchAllCircularsForOrganization(Organization userOrg, boolean activeOnly, int startOffset) {

        GmCirculars criteria = new GmCirculars();
        criteria.setOrganization(userOrg);
        return gmCircularDao.find(criteria, activeOnly, startOffset, circularsMaxRows);
    }


    /**
     * Find by id.
     *
     * @param id the id
     * @return the gm circulars
     */
    public GmCirculars findById(BigDecimal id) {
        GmCirculars result = null;

        List<GmCirculars> discs = gmCircularDao.find(new GmCirculars(id), false, 0, circularsMaxRows);

        if (null != discs && !discs.isEmpty()) {
            result = discs.get(0);
        }
        return result;
    }


    /**
     * Mark as deleted.
     *
     * @param entryId the entry id
     * @return true, if successful
     */
    public boolean markAsDeleted(BigDecimal entryId) {
        return gmCircularDao.markAsDeleted(entryId);
    }
}

Когда я запускаю этот код, я получаю следующую ошибку, которая застряла на некоторое время.

ERROR LoggingFailureAnalysisReporter 

***************************
APPLICATION FAILED TO START
***************************

Description:

Field gmCircularDao in service.CircularsService required a bean of type 'javax.persistence.EntityManagerFactory' that could not be found.

The injection point has the following annotations:
    - @org.springframework.beans.factory.annotation.Autowired(required=true)


Action:

Consider defining a bean of type 'javax.persistence.EntityManagerFactory' in your configuration.

Как исправить? Спасибо.

1 Ответ

0 голосов
/ 23 января 2020

Spring is right:

Вы используете данные пружины (@Repository public interface IGmCircularsDAO extends JpaRepository<GmCirculars, BigDecimal>)

Весь смысл данных пружины заключается в создании реализации на основе этого интерфейса во время выполнения. Эта реализация зарегистрирована как bean-компонент, который реализует IgmCircularDao интерфейс)

Теперь, прямо под вами, вы создаете bean-компонент:

@Repository
@Transactional
@SuppressWarnings("unchecked")
public class GmCircularsDaoImpl extends ParentDAO implements IGmCircularsDAO {
...

Итак, Spring сканирует и находит этот репозиторий и пытается зарегистрируйте это как боб. Он также реализует тот же интерфейс, поэтому у Spring есть два bean-компонента, которые конкурируют друг с другом за право быть введенным в сервис:

public class CircularsService {

    @Autowired
    private IGmCircularsDAO gmCircularDao; // <-- what should spring chose? an autogenerated spring data proxy or your own implementation???
...

Отсюда исключение ...

Вы должны понимать хотите ли вы поддерживать оба репозитория, которые реализуют один и тот же интерфейс, и если да, то как провести различие между ними, когда вы хотите внедрить какой-либо из них в сервисы (как в случае CircularService).

Вы можно использовать классификаторы, разные интерфейсы - есть много решений, но опять же, вы должны сначала понять, какое использование вам больше подходит

...