admin管理员组文章数量:1794759
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 configuration3.为了解决这个错误,百度发现几种解决方法:
●删除本地的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%2B86.启动项目,就不会出现找不到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/211.昨天又发现一个错误:
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等后,第二天使用就没有报错了。 所以这个方法应该是可以解决问题的。
版权声明:本文标题:Consider defining a bean named ‘entityManagerFactory‘ in your configuration的正确解决方法 内容由林淑君副主任自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.xiehuijuan.com/baike/1686556984a81573.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论