Java后端入坑记录(更新中。。。)

 

Java后端入坑记录(更新中。。。)

踩坑记录

MySQL踩坑记录

1,插入数据时 报Unknown column '张三' in 'field list'

-- 错误方式
insert into `user`(`user_id`,`user_name`,`user_pwd`) values(3,`王五`,`wangwu`);
-- 正确方式
insert into `user`(`user_id`,`user_name`,`user_pwd`) values(3,'王五','wangwu');
复制代码

原因 : 对于数据库名,表名,字段名使用user(反双撇号引用-table键上面那个)而对于字符串则使用' 张三'引用(enter键旁边)。

MyBatis踩坑记录

1.,在.java文件中和在.xml文件中配置mysql的url的区别

  • 在.java文件中配置

    jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8
    复制代码
  • 在.xml文件中配置

jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8
复制代码

原因: 在.xml文件中&不能直接解析,需要使用转义字符转义,&对应的转义字符为&amp

2,报not known to the MapperRegistry. 异常

当在.xml文件中写sql语句时,该.xml文件要在mybatis-config.xml文件中进行注册(即加入以下内容)否则会报Type interface com.jgsu.dao.UserMapper is not known to the MapperRegistry. 异常

<mappers>
        <mapper resource="com/jgsu/dao/UserMapper.xml"/>
</mappers>
复制代码

3,报  Could not find resource com/jgsu/dao/UserMapper.xml异常

org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: java.io.IOException: Could not find resource com/jgsu/dao/UserMapper.xml

原因:I DEA是不会编译src的java目录的xml文件,所以在Mybatis的配置文件中找不到xml文件!(也有可能是Maven构建项目的问题,网上教程很多项目是普通的Java web项目,所以可以放到src下面也能读取到)

解决方法: 在当前pom.xml中添加节点(可以放在父级)

    <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
            </resource>
        </resources>
    </build>
复制代码

4,Parsing error was found in mapping #{}异常

org.apache.ibatis.exceptions.PersistenceException: 
### Error building SqlSession.
### The error may exist in com/zuoyueer/dao/UserMapper.xml
### Cause: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: org.apache.ibatis.builder.BuilderException: Error parsing Mapper XML. Cause: org.apache.ibatis.builder.BuilderException: Parsing error was found in mapping #{}.  Check syntax #{property|(expression), var1=value1, var2=value2, ...} 
	at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
	at org.apache.ibatis.session.SqlSessionFactoryBuilder.build(SqlSessionFactoryBuilder.java:80)
	....
Caused by: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: org.apache.ibatis.builder.BuilderException: Error parsing Mapper XML. Cause: org.apache.ibatis.builder.BuilderException: Parsing error was found in mapping #{}.  Check syntax #{property|(expression), var1=value1, var2=value2, ...} 

复制代码

意思就是说,我的映射文件中#{}里没有写值, 于是我找啊找,我的全部配置都加了值啊,最后我一个一个删除,终于定位到了异常,居然是注释的锅!!!

异常代码如下:

<select id="getUserById" resultType="com.jgsu.pojo.User" parameterType="int">
        /*user_id`:数据库中表名,#{}中填该方法对应的参数名*/
       select `user_id`,`user_name`,`user_pwd` from `user` where `user_id`=#{user_id};
</select>
复制代码

原因: 注释中含有#{},这里使用的注释是/**/,会导致xmll文件解析异常,将注释中的#{}也解析了。

解决办法: 删除该注释或采用进行注释,这样注释内容就不会被解析。

参考:mybatis异常Parsing error was found in mapping #{}. mybatis映射文件中使用注释的坑

5,使用mybatis进行insert/delete/update操作时,明明执行成功了,但是数据库中的数据没有更新

原因: mybatis中使用sqlSession对数据进行更新操作后要进行事务的提交即sqlSession.commit();数据才能在数据库中进行更新。

6,万能map

当实体类中或者数据库表中的字段或参数过多时,而我们只需要对部分值在SQL中进行传参时可以考虑使用map。

参考: mybatis中传入多个参数的解决方法

7,模糊查询Like

不建议直接在SQL语句中进行模糊查询,而是将%%放在Java中进行,如下

<!--方法一:根据name中某个字符查-->
    <select id="getUserListByLike" resultType="com.jgsu.pojo.User" parameterType="string">
        select `user_id`,`user_name`,`user_pwd` from user where `user_name` like #{value};
    </select>
<!--方法二:在sql中拼接%-->
 <select id="getUserListByLike" resultType="com.jgsu.pojo.User" parameterType="string">
        select `user_id`,`user_name`,`user_pwd` from user where `user_name` like "%"#{value}"%";
    </select>
复制代码

在java中

    // 接口UserMapper中如下定义
    /**
     * 模糊查询
     * */
    List<User> getUserListByLike(String value);


    @Test
    public void getUserListByLike(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        // %表示任意个或多个字符。可匹配任意类型和长度的字符 -- 在代码中拼接
        String temp = "%";
        List<User> userList = userMapper.getUserListByLike(temp+"张"+temp);
        for (User user : userList) {
            System.out.println(user);
        }
        sqlSession.close();
    }
复制代码

8,在xxx.xml文件中的某条sql语句中引入另一个xxx2.xml文件中的某条sql。

目的: 实现多个学生关联一个老师实现多对一查询。

思路:

1.在TeacherMapper.xml文件中编写sql实现根据teacher_id查询对应的teacher。对应的select标签中的id为getTeacherById
2.在StudentMapper.xml文件中编写sql实现全表查询,但是因为student类中存放的是teacher类而不是teacherId,所以要用到resultMap实现数据库中的列于对应的类中的属性一一对应,而对于复杂的属性比如对象teacher则需要用association进行处理,将student类中的teacher属性跟数据库中的t_id进行绑定,获取t_id的值则通过select标签对TeacherMapper.xml中的getTeacherById方法进行绑定。(意思就是从TeacherMapper.xml中的getTeacherById获取到teacher对象然后再将这个对象传给StudentMapper.xml中属性为teacher实现绑定从而实现一对多查询)
复制代码

**1)**其对应的pojo包中的teacher类和student类分别为:

// ----------------------pojo包中的student类
@AllArgsConstructor // lombok插件简化生成set,get,Constructor等方法
@NoArgsConstructor
@Data
public class Student {
  // id
    private int studentId;
  // name
    private String studentName;
  // 对应的teacher
    private Teacher teacher;
}

// ----------------------pojo包中的teacher类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Teacher {
  // id
    private int teacherId;
  // name
    private String teacherName;
}
复制代码

**2)**创建的student表和teacher表如下:

# 创建student表其中t_id对应的是teacher中的teacher_id
create table if not exists `student`(
    `student_id` int not null primary key ,
    `student_name` varchar(30) not null,
    `t_id` int not null
)engine =innodb default charset =utf8;
use mybatis;
# student表中插入数据
insert into `student`(`student_id`,`student_name`,`t_id`) values (1,'小明',1),(2,'小红',1),(3,'小绿',1);
# 创建teacher表
create table if not exists `teacher`(
    `teacher_id` int not null primary key ,
    `teacher_name` varchar(30) not null
)engine =innodb default charset =utf8;
# teacher表中插入数据
insert into `teacher`(`teacher_id`,`teacher_name`)values (1,'张老师');
# sql语句实现两张表关联查询
select `student_id`,`student_name`,`teacher_name` from `student`,`teacher` where `t_id` = `teacher_id`;
复制代码

**3) **创建的TeacherMapper接口,TeacherMapper.xml,StudentMapper接口,StudentMapper.xml如下:

  • TeacherMapper接口和StudentMapper接口

public interface StudentMapper {
    /**
     * 多对一连表查询
     * */
    List<Student> getStudentList();
}
public interface TeacherMapper {
    /**
     * 根据Id获取老师信息
     * */
    Teacher getTeacherById(@Param("t_id") int id);
}
复制代码
  • TeacherMapper.xml,StudentMapper.xml

<!--StudentMapper对应的StudentMapper.xml文件------------------------------------>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace=绑定一个对应的dao/mapper接口的路径-->
<mapper namespace="com.jgsu.dao.StudentMapper">

    <!--多对一查询:查询多个学生对应同样一个老师的所有学生-->
    <select id="getStudentList" resultMap="StudentTeacher">
       select `student_id`,`student_name`,`t_id` from `student`;
    </select>
    <resultMap id="StudentTeacher" type="Student">
        <result property="studentId" column="student_id"/>
        <result property="studentName" column="student_name"/>
        <!--对于复杂的属性需要单独处理: association处理对象,collection:处理集合-->
        <association property="teacher" column="t_id" javaType="com.jgsu.pojo.Teacher" select="getTeacherById"/><!---注意:这里应该写:com.jgsu.dao.TeacherMapper.getTeacherById-->
    </resultMap>

</mapper>

<!--TeacherMapper对应的TeacherMapper.xml文件----------------------------------->
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace=绑定一个对应的dao/mapper接口的路径-->
<mapper namespace="com.jgsu.dao.TeacherMapper">

    <!--多对一查询:查询多个学生对应同样一个老师的所有学生-->
    <select id="getTeacherById" resultType="Teacher">
        select `teacher_id`,`teacher_name` from `teacher` where `teacher_id` = #{t_id};
    </select>

</mapper>
复制代码

**4)**测试用例如下:

public class StudentMapperTest {
    @Test
    public void getStudentList(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
        List<Student> studentList = mapper.getStudentList();
        for (Student student : studentList) {
            System.out.println(student);
        }
        sqlSession.close();
    }
}
复制代码

问题: 系统会默认去找StudentMapper下的方法,但是问题是我们引入的方法在Teacher类中,写的sql语句也是在TeacherMapper.xml文件中。

org.apache.ibatis.exceptions.PersistenceException: 
### Error querying database.  Cause: java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for com.jgsu.dao.StudentMapper.getTeacherById
### The error may exist in com/jgsu/dao/StudentMapper.xml
### The error may involve com.jgsu.dao.StudentMapper.getStudentList
### The error occurred while handling results
### SQL: select `student_id`,`student_name`,`t_id` from `student`;
### Cause: java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for com.jgsu.dao.StudentMapper.getTeacherById
复制代码

解决方法: 在StudentMapper.xml文件引入另有一个文件的引用出应该写该方法的完全限定名,而不是该方法的方法名,否则会识别不出。

<!--对于复杂的属性需要单独处理: association处理对象,collection:处理集合-->
        <association property="teacher" column="t_id" javaType="com.jgsu.pojo.Teacher" select="com.jgsu.dao.TeacherMapper.getTeacherById"/>

<!--错误用例-->
<association property="teacher" column="t_id" javaType="com.jgsu.pojo.Teacher" select="getTeacherById"/>
复制代码

Spring踩坑记录

1,什么是IOC?

我的理解:

将一些本由程序员自己做的事,现在可以交给客户去做。就比如程序员给客户提供了三种分别连接sqlserver,mysql,oracle的接口,假设用户现在需要连接的数据库mysql,程序员在业务层直接指定数据库是mysql,然后用户直接使用。但是过了一段时间,用户公司转型了,现在需要对接的数据库是Oracle,那么此时就要叫程序员在业务层对数据库类型进行更改,如果用户公司需要频繁的切换数据库那怎么办呢???如果交给程序员去做的话,那程序员岂不累死,这需要频繁的对原来的代码进行修改。此时我们就可以考虑在不更改源代码的前提下,这种切换数据库的操作就由用户自己去解决,程序员只需要提供对应的数据库的接口即可,用户通过调用对应的数据库接口实现对数据库的切换。

2,静态代理,JDK动态代理,cglib动态代理的主要区别

  • 静态代理在编译时就已经实现,编译完成后代理类是一个实际的class文件

  • 动态代理是在运行时动态生成的,即编译完成后没有实际的class文件,而是在运行时动态生成类字节码,并加载到JVM中。比如:interface不能实例化,那有没有可能不编写实现类,直接在运行期创建某个interface的实例呢?答案是可能的,我们可以使用动态代理提供在运行期创建某个interface的实例。

  • 使用JDK动态代理的对象必须实现一个或多个接口

  • 使用cglib代理的对象则无需实现接口,达到代理类的无侵入

  • jdk动态代理对象不需要实现接口,但是要求目标对象必须实现接口,否则不能使用动态代理。

    参考: 1) www.liaoxuefeng.com/wiki/125259…

    1. segmentfault.com/a/119000001…

 

  

推荐阅读:

来源 微信公众号:撸Java源码

上一篇:Mongoose添加验证Node-Demo连接方式


下一篇:Spring的循环依赖的问题及解决