我有一个Java项目,它使用带有JPA的Spring Boot和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;
}
}
父道.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);
}
}
通函服务.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.
如何解决?谢谢。
春天是对的:
您正在使用弹簧数据 (@Repository
public interface IGmCircularsDAO extends JpaRepository<GmCirculars, BigDecimal>
(
spring数据的全部意义在于在运行时基于此接口生成实现。此实现被注册为实现IgmCircularDao
接口(的 Bean(
现在,在你下面创建一个 bean:
@Repository
@Transactional
@SuppressWarnings("unchecked")
public class GmCircularsDaoImpl extends ParentDAO implements IGmCircularsDAO {
...
因此,Spring 再次扫描并找到此存储库并尝试将其注册为 bean。它还实现了相同的接口,因此 spring 有两个 bean 相互竞争注入服务的权利:
public class CircularsService {
@Autowired
private IGmCircularsDAO gmCircularDao; // <-- what should spring chose? an autogenerated spring data proxy or your own implementation???
...
因此例外...
您应该了解是否要维护实现相同接口的两个存储库,如果是,当您要将其中任何一个注入服务时,如何区分它们(就像在CircularService
的情况下一样(。
您可以使用限定符,不同的接口 - 有很多解决方案,但同样,您应该首先了解最适合您的用法
问题出在 Spring boot 2.x Release 使用的休眠版本上。在以下添加休眠版本解决了该问题,
<properties>
<hibernate.version>5.2.14.Final</hibernate.version>
</properties>