admin管理员组

文章数量:1794759

Consider defining a bean named ‘entityManagerFactory‘ in your configuration的正确解决方法

Consider defining a bean named ‘entityManagerFactory‘ in your configuration的正确解决方法

一、简述

有一个Java项目A,使用了mybatis-plus; 有一个Java项目B,使用了jpa(hibernate); 现在要把B项目整个合并到A项目中,遇到了这个错误:

Consider defining a bean named 'entityManagerFactory' in your configuration

也就是说,mybatis-plus与jpa(hibernate)在一个Java项目中同时使用时,报错,找不到:entityManagerFactory

二、踩坑过程

1.刚开始合并项目时,报错Consider defining a bean of type 'com.xxx.xxx.XXXRepository' in your configuration,没有找到自己写的Jpa的Repository.java类;后来发现,需要在启动类Application.java中,增加Jpa的包扫描语句:

@EnableJpaRepositories(basePackages="com.xxx") @EntityScan(basePackages="com.xxx")

2.扫描到自己的Jpa的Repository后,就开始报错:

Consider defining a bean named 'entityManagerFactory' in your configuration

3.为了解决这个错误,百度发现几种解决方法:

●删除本地的maven的hibernate-core文件夹

感觉这个挺离谱的,估计是要让maven自动选择正确的hibernate-core版本的意思;总之,试了没有用。

●给spring-boot-starter-data-jpa包声明版本

这个也试了,参考B项目的jpa版本号,但是配置了也没用。

4.自己检查maven树,发现把所有冲突都解决完毕后,也没有用。

5.自己检查maven树,尝试各种exclude、include、指定版本号,都没有用。

三、正确解决方法

1.报错找不到entityManagerFactory,个人推测是,项目中同时使用mybatis-plus与jpa(hibernate),导致默认配置失效,需要手动配置一个新的数据源等

2.首先,自己创建一个entityManagerFactory,例如下方Java文件:

@Configuration @EnableTransactionManagement @EnableJpaRepositories( entityManagerFactoryRef = "myEntityManagerFactory", transactionManagerRef = "myTransactionManager", basePackages = {"com.xxx.repository"} //设置repository所在位置 ) public class DBConfig{ //这4个value与application.properties中对应;冒号后是默认值 @Value("${myuser:root}") private String myuser; @Value("${mypass:root}") private String mypass; @Value("${mydriver}") private String mydriver; @Value("${myurl}") private String myurl; @Bean public HikariDataSource hds(){ HikariDataSource hds = new HikariDataSource(); hds.setUsername(myuser); hds.setPassword(mypass); hds.setJdbcUrl(myurl); hds.setDriverClassName(mydriver); hds.setAutoCommit(true); return hds; } @Bean public Properties prop(){ Properties prop = new Properties(); //prop.put("hibernate.connection.driver_class",mydriver); //prop.put("hibernate.connection.url",myurl); //prop.put("hibernate.connection.username",myuser); //prop.put("hibernate.connection.password",mypass); prop.put("hibernate.show_sql","true"); prop.put("hibernate.connection.userUnicode","true"); prop.put("hibernate.connection.characterEncoding","UTF-8"); prop.put("hibernate.format_sql","true"); prop.put("hibernate.use_sql_comments","true"); prop.put("hibernate.hbm2ddl.auto","update"); prop.put("hibernate.dialect","org.hibernate.dialect.MySQL5Dialect"); prop.put("hibernate.connection.autoReconnect","true"); prop.put("hibernate.connection.autoReconnectForPools","true"); prop.put("hibernate.connection.is-connection-validation-required","true"); prop.put("validationQuery","SELECT 1"); prop.put("testOnBorrow","true"); return prop; } @Primary @Bean(name = "myEntityManagerFactory" ) public LocalContainerEntityManagerFactoryBean myEntityManagerFactory(HikariDataSource hds, Properties prop){ LocalContainerEntityManagerFactoryBean bean = new LocalContainerEntityManagerFactoryBean(); //这个扫描的是Entity(JavaBean)的位置,注意与上方的repository区别开 bean.setPackagesToScan("com.xxx.entity"); HibernateJpaVendorAdapter hjva = new HibernateJpaVendorAdapter(); bean.setJpaVendorAdapter(hjva); bean.setLoadTimeWeaver(new InstrumentationLoadTimeWeaver()); bean.setDataSource(hds); bean.setJpaProperties(prop); return bean; } @Primary @Bean(name="myEntityManager") public EntityManager myEntityManager(EntityManagerFactory myEntityManagerFactory){ return myEntityManagerFactory.createEntityManager(); } @Primary @Bean(name="myTransactionManager") public PlatformTransactionManager myTransactionManager(EntityManagerFactory myEntityManagerFactory){ JpaTransactionManager jtm= new JpaTransactionManager(); jtm.setEntityManagerFactory(myEntityManagerFactory); return jtm; } }

3.上方代码,也配置了@EnableJpaRepositories;因此,记得把启动类的Application.java中的这个注解去掉(总共配一个就行了)

4.下面看一下pom.xml,除了必要的jpa注解之外,本人的项目中,漏了一个hibernate-entitymanager的jar包配置,因此加上:

<dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-entitymanager</artifactId> <version>4.3.9.Final</version> <exclusions> <exclusion> <artifactId>hibernate-core</artifactId> <groupId>org.hibernate</groupId> </exclusion> </exclusions> </dependency> <dependency> <artifactId>hibernate-core</artifactId> <groupId>org.hibernate</groupId> <version>4.3.9.Final</version> <scope>compile</scope> </dependency>

上方是为了保证jar包版本统一,才用了exclusion。 (虽然看起来奇怪,但是本人项目不这样写就jar包冲突…)

5.最后,在配置文件中配置与上方xml对应的数据库连接信即可,例如,在application-test.properties中进行如下配置:

myuser=root mypass=root mydriver=com.mysql.cj.jdbc.Driver myurl=jdbc:mysql://10.123.123.123:3306/mydbname?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8

6.启动项目,就不会出现找不到entityManagerFactory的错误了。

四、总结

当Java项目启动出现找不到entityManagerFactory的错误信时,正确解决方法是,自己创建一个entityManagerFactory放入spring容器,步骤如上。(亲测有效)

五、后记

后来,本人的这个项目又出现了一个奇葩问题,jpa(hibernate)执行select语句正常,可以返回数据; 但是执行save方法(insert),数据库并没有写入数据。

当时使用以下代码测试,关闭自动开启的事务:

@EnableJpaRepositories(basePackages="xxx.xxx.xxx", enableDefaultTransactions = false )

然后执行save方法时,就报错找不到EntityManager; 如果开启事务:

//这两句一样,因为默认是开启的 @EnableJpaRepositories(basePackages="xxx.xxx.xxx") //@EnableJpaRepositories(basePackages="xxx.xxx.xxx", enableDefaultTransactions = true )

执行到save方法时,代码就不会报错,但是数据库就是没有数据存入。

整了两三天,总算是解决了,但是不太清楚原因;

个人推测,如果不开启事务,jpa就不允许执行insert等操作,只能select;如果开启事务,由于项目哪里有问题,执行save后没有提交,因此不报错,数据库也没有存入数据。

解决方法也不是很清楚,百度搜了一堆,改了一大堆代码,不知道哪里有用,哪里没用,只能总结下可能的解决方法

1.对比下上方的代码(上方是已解决这个错误的代码)

2.pom.xml中,缺失了jar包hibernate-entitymanager与hibernate-core,需要加上这两个。

3.需要增加@Primary注解,否则可能不行。

4.自定义的entityManager等JavaBean,最好起别名,例如myEntityManager,不要与默认的重名了(例如就起成entityManager,就是重名)

5.TransactionManager,事务管理的JavaBean,自定义时,jpa返回类型要为PlatformTransactionManager。(具体自定义方法看上方代码)

六、后记的后记,2022/2/21

1.昨天又发现一个错误:

DataAccessResourceFailureException: could not extract ResultSet

好像是程序刚启动没事,跑一阵子后就报这个错,sql相关的代码就无法执行、导致页面500。

开始以为是配置了autoReconnect=true后,导致了这个错误; 然后注释了autoReconnect=true,结果还是不行,还报错:

SqlExceptionHelper : The last packet successfully received from the server war xxx milliseconds age. is longer than the server configured value of 'wait_timeout'. You Should consider either expiring and/or testing connection validity before use in your application, increasing the server configured values for client timeouts, or using the Connector/J connection property 'autoReconnect=true' to avoid this problem.

意思是还得加autoReconnect=true,因为不加时间长了也会报错。

原因:

如果连接池中的某个连接长时间未被使用,mysql就会中断这个连接; 后续如果程序用到了这个被中断的连接,就会导致程序报错。 (进而页面500,只能重启项目了。)

可能的解决方法: 1.配置正确autoReconnect=true相关代码(之前可能是本人配置有问题),如下:

prop.put("hibernate.connection.autoReconnect","true"); prop.put("hibernate.connection.autoReconnectForPools","true"); prop.put("hibernate.connection.is-connection-validation-required","true"); prop.put("validationQuery","SELECT 1"); prop.put("testOnBorrow","true");

2.换一个数据源试试,例如HikariDataSource.

●之前总是项目到第二天就报这个错(因为晚上没人用,数据库连接就被关闭了,然后第二天一用就报错了); 现在配置了SELECT 1与HikariDataSource等后,第二天使用就没有报错了。 所以这个方法应该是可以解决问题的。

本文标签: 解决方法正确beandefiningnamed