springboot踩坑笔记⼆:springboot+mybatis踩坑⼩结
为什么使⽤springboot+mybatis?
这个问题感觉没什么提问价值,但是关于“spring的坑”这个话题向来⽐较沉重,所以咱们先闲谈⼀下这个问题以缓解⽓氛。
springboot相⽐spring的先进之处有很多,⽐如对第三⽅插件的强⼤⽀持,内嵌式web服务器(tomcat,jetty),提供注解式sql语句简化dao层编码以及⾃动配置等等⼀⼤堆。想想当初的SSM框架要写l+⼀⼤坨糟⼼的
⾔归正传,下⾯记录⼀下我在使⽤这个框架过程中遇到的⼏个问题以及解决⽅案。
⼀、 在service层使⽤@Autowired注⼊dao层bean时,报错不到我们想要在dao层返回的entity类:
org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.apache.ibatis.session.SqlSessionFactory]: Factory method ‘sqlSessionFactory’ threw exception; nested exception is NestedIOException: Failed to parse mapping resource: ‘file
[D:\intellij_workspace\springbootTest\target\classes\l]’; nested exception is
org.apache.ibatis.builder.BuilderException: Error parsing Mapper XML. The XML location is ‘file
[D:\intellij_workspace\springbootTest\target\classes\l]’. Cause:
org.apache.ibatis.builder.BuilderException: Error resolving class. Cause: org.pe.TypeException: Could not resolve type alias ‘UserInfo’. Cause: java.lang.ClassNotFoundException: Cannot find class: UserInfo
可能原因:mapper⽂件中⽅法返回值即resultType的值配错了
解决⽅案:
1.这⾥需要正确地写出entity类的全路径,注意是全路径!像这样:
resource和autowired注解的区别
<select id="getUserInfo" parameterType="java.util.Map" resultType="com.mjj.springboot.bean.UserInfo">
2.如果全路径很长,你⼜不想逐个去写全路径,springboot也是替我们想了办法的,就是在项⽬的配置⽂件 application.properties中添加配置:
加了这项配置你就可以简洁地把mapper⽂件entity类的返回值写成:
<select id="getUserInfo" parameterType="java.util.Map" resultType="UserInfo">
spring会⾃动根据你配置的type-aliases-package到相应的路径下名为UserInfo的类,然后⾃动组装返回值。
⼆、注⼊dao层bean时,报错未绑定XXXDao(⼤致是这个意思?)
org.apache.ibatis.binding.BindingException: Invalid bound statement (not found):
com.mjj.springboot.UserInfo…
可能原因:
1.没有配置l⽂件的路径,spring不知道你的dao层接⼝跟哪⾥的mapper⽂件进⾏映射
解决⽅法: 在项⽬的配置⽂件 application.properties中添加配置:
mybatis.mapper-locations=classpath:mapper/*.xml
此处的mapper/*.xml就是你放置l⽂件的路径,*指模糊匹配,程序员都知道 。需要注意的是,maven项⽬中,Java,test、resource都不算包的路径,该路径统统是项⽬的根路径。有⼈习惯把l ⽂件放在Java路径中跟它所映射的mapper.java放⼀起,个⼈更倾向放在resource中,⼆者区别及需要注意的地⽅另请查阅相关资料。
l⽂件中的 namespace项跟其要映射的dao层类的路径不匹配 。
解决办法:这种错误很好检验,光标移动⾄namespace引号中的内容,摁住ctl键+⿏标点击。如果配置正确,此时会跳转到对应的映射类上,否则就是这⾥配置的路径错误。
<mapper namespace="mjj.springboot.dao.UserInfoDao">
三、@mapper的使⽤
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type
‘com.mjj.springboot.dao.UserInfoDao’ available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at
org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFa ctory.java:1646)
at
org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.j ava:1205)
at
org.springframework.beans.factory.solveDependency(DefaultListableBeanFactory.jav a:1166)
at
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(Auto wiredAnnotationBeanPostProcessor.java:593)
… 46 common frames omitted
解决办法:
1.在对应的dao层上加注解@Mapper(不是@Repository)
2.如果dao层的类太多,你⼜不想逐个加@Mapper,springboot也是替我们想了办法的,就是在项⽬的启动类(图标是个⼩电源,有
@SpringbootApplication王者标志)上加注解:
@MapperScan("com.mjj.springboot.dao")
需要注意的是,此处是指dao层的java⽂件,即dao层接⼝⽽不是xml⽂件本⾝,且只对该路径下的接⼝进⾏扫描并注⼊。加了这个注解
后,dao层的类上就不需要加bean注⼊的注解了。
四、resultType返回list类型,报错不⽀持的集合操作
### Error querying database. Cause: java.lang.UnsupportedOperationException
### The error may exist in file [D:\intellij_workspace\springbootTest\target\classes\l]
### The error may involve com.mjj.springboot.DRWInfo
### The error occurred while handling results
### SQL: select count(GJJNBR) from GSL.TAB_DRWINFO where GJJNBR= ? and DRWDAT = ?
### Cause: java.lang.UnsupportedOperationException
可能原因:把list作为resultType的值了,⽬前mybatis的resultType并不⽀持集合类型。 只有resultMap可以灵活定义返回值类型为map 解决⽅案:如果是想返回List类型的值 ,只需要将返回值定义为 resultType=“UserBean” dao层对应的⽅法上返回值定义为List即可mybatis 会⾃动识别并将多条UserBean存⼊list中返回。
五、关于resultType和resultMap,常见报错:
org.apache.ibatis.builder.IncompleteElementException: Could not find result map com.mjj.springboot.bean.UserInfo
Caused by: java.lang.IllegalArgumentException: Result Maps collection does not contain value for
com.mjj.springboot.bean.UserInfo
at org.apache.ibatis.session.(Configuration.java:888)
at org.apache.ibatis.ResultMap(Configuration.java:640)
at org.apache.ibatis.StatementResultMaps(MapperBuilderAssistant.java:344)
… 46 more
可能原因:本意想返回⼀个entity类,却误将resultType写成了resultMap,或者本意确实要⽤resultMap,但是resultMap标签中配置的id 标签跟resultMap=""中的值不⼀致,甚⾄压根⼉忘了写resultMap标签。
resultMap标签的写法⽰例:
<resultMap id="user" type="com.mjj.springboot.bean.UserInfo">
<id column="id" property="id"></id>
<result column="name" property="name"></result>
</resultMap>
个⼈暂时没有发现resultMap的妙⽤,觉得是个挺鸡肋的标签,因为它仍需要在代码中有对应的entity
类,即type所映射的类,同时还要将所有的属性重复⼀遍,遇到字段多的时候实在⿇烦,唯⼀的⽤处是:你跟设计数据库的同事意见不合,觉得他起的字段名不好,你代码⾥对应的entity属性名跟他起的不⼀样,或者数据库的字段太多,你只想要⼀部分封装到entity⾥去,这时候resultMap就派上⽤场了,“偷梁换柱”也好“偷⼯减料”也好都能在这个标签⾥悄悄进⾏。如果没有此类需求,你可以直接⽤resultType=“Entity” 或者
resultType=“map” (此时dao层返回值直接就是Map或者List)。
六、测试类的注解问题
可能报错:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name
‘com.mjj.springboot.daoTest.CutInfoDaoTest’: Unsatisfied dependency expressed through field ‘szgjjCutInfDao’; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type
‘com.mjj.springboot.dao.SzgjjCutInfDao’ available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Auto
wired(required=true)}
可能原因:
1.测试类没有正确地添加注解:
@RunWith(SpringRunner.class)
@SpringBootTest
2.由于各种奇葩原因,你的项⽬⾥有两个Application类,此时@SpringBootTest就晕头了,它不知道它应该去匹配哪⼀个⼊⼝类,此时你只需要指定正确的⼊⼝类就好了:
@RunWith(SpringRunner.class)
@SpringBootTest(Application1.class)
当测试类很多⼜不想逐⼀添加的时候 ,可以写⼀个测试基类 ,在测试基类上添加正确的注解,其他的测试类都继承该基类 ,就不⽤⼀个⼀个写注解了,简化代码同时⽅便测试类注解的管理。
七、⼀个超轻松的问题
报错:
java.sql.SQLException: The server time zone value ‘?D1ú±ê×?ê±??’ is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you want to utilize time zone support.
解决:在项⽬的配置⽂件 application.properties中添加配置:
spring.datasource.url =jdbc:mysql://99.10.50.201:3306/GSL?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLe gacyDatetimeCode=false&serverTimezone=UTC
⼋、配置⽂件
前⾯有说过spring boot相⽐spring的⼀⼤优势是⾃动配置,⾃动配置就是不需要像spring⼀样写很多的配置⽂件了,它只需要⼀个application.properties就好了,也就是不需要l等等。其他的配置交由各式各样的注解去完成。我作为⼀个反应不灵活的程序员,实在深受各种配置⽂件的困扰,所以只愿意掌握诸多⽅法中最简单的⼀个。其次,本⼈初学springboot,
⽂中所提皆是基础,且还有诸多问题不甚清楚,后续若有领悟会回来完善更正。若有⼤神误⼊,发现错误的地⽅万望不吝赐教。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。