zoukankan      html  css  js  c++  java
  • MyBatis 增删改查

    MyBatis单表添加操作

    实现了一个向数据库中的添加操作,下面来分析一下:

    <!--parameterType可省略-->
    <insert id="insertStudent" parameterType="com.monkey1024.bean.Student">
        INSERT INTO t_student(name,age,score) VALUES (#{name},#{age},#{score})
    </insert>
    • id:该SQL语句的唯一标识,可被用来代表该sql语句,在Java代码中要使用该标识。
    • parameterType:传入参数的类型,MyBatis会推断出传入参数的类型,因此可以不用配置。
    • { }:里面需要填写javabean中的属性,其底层是通过反射机制,调用bean类相关属性的get方法来获取值的。

    在dao的实现类中,我们手动进行了事务的提交:

    //SqlSession继承了AutoCloseable接口,所以可以自动关闭
        try(SqlSession sqlSession = MyBatisUtil.getSqlSession()) {
            //新增数据操作
            sqlSession.insert("insertStudent", student);
            //提交SqlSession
            sqlSession.commit();
    
        }

    如果想要改成自动的话,可以在MyBatisUtil中的下面openSession方法里面传入true,这样mybatis就会自动提交事务了,如果传入false或者没有传入任何参数,他是不会自动提交事务的。

    //自动提交事务
    sqlSessionFactory.openSession(true);
    
    //不自动提交事务
    sqlSessionFactory.openSession(false);
    sqlSessionFactory.openSession();

    如果不提交事务的话,数据是不会插入到数据库中的。

    获取主键

    在之前的示例中,我们使用了mysql主键自增的策略,当插入数据库后,我们才能获取到该数据的主键,获取主键的操作可以使用下面方式:

    <insert id="insertStudent">
      INSERT INTO t_student(name,age,score) VALUES (#{name},#{age},#{score});
      <selectKey resultType="int" keyProperty="id" order="AFTER">
          SELECT @@identity
      </selectKey>
    </insert>

    这样子在mybatis完成插入数据后,会将该数据的主键查询出来,重写Student的toString方法,然后通过下面示例可以看到被插入student数据的主键:

     @Test
    public void insertStudent(){
        StudentDao studentDao = new StudentDaoImpl();
        Student student = new Student("刘德华", 52, 98.50);
    
        //id是默认值0
        System.out.println("before:" + student);
        studentDao.insertStudent(student);
        //可以获取id的值
        System.out.println("end:" + student);
    }

    这样子在完成插入数据后就不用再单独去数据库中把主键查询出来了,通过上面的配置,mybatis会帮我们做这件事。那么mybatis是如何获取到这个主键id的呢?我们在执行insert语句之后,提交事务之前添加一行打印student对象的代码:

     //SqlSession继承了AutoCloseable接口,所以可以自动关闭
        try(SqlSession sqlSession = MyBatisUtil.getSqlSession()) {
            //新增数据操作
            sqlSession.insert("insertStudent", student);
            System.out.println("提交数据库之前:" + student);
            //提交SqlSession
            sqlSession.commit();
    
        }

    当执行插入操作的时候,可以看到在提交事务之前,其实已经获取到这个主键id的,就是说不管是提交还是回滚,这个主键都是先获取到的。当执行sql语句之后,数据库就会给该条数据分配一个主键,倘若回滚的话,这个主键就不能用了,下次再执行插入操作时,会在该id之后再分配一个id。由此可以得出一个结论就是主键的生成跟事务没有关系,只要执行了sql语句,mysql就会为其分配一个主键。

    单表的删除

    这里的删除还是在之前示例的基础上进行编写,先在StudentMapper.xml中添加删除操作的SQL语句:

    <delete id="deleteStudent">
        DELETE FROM t_student where id=#{id}
    </delete>

    先之后StudentDao接口中添加deleteStudent的方法,然后在其实现类中实现该方法:

    @Override
    public void deleteStudent(int id) {
        try(SqlSession sqlSession = MyBatisUtil.getSqlSession()) {
            //删除
            sqlSession.delete("deleteStudent",id);
            //提交SqlSession
            sqlSession.commit();
    
        }
    }

    在测试类中,为了避免每个方法中都要创建StudentDao类型的对象,我们添加一个方法用来初始化其对象并添加删除操作的方法:

    private StudentDao studentDao;
    
    /**
     * 测试时先执行该方法创建StudentDao对象
     */
    @Before
    public void initStudentDao(){
        studentDao = new StudentDaoImpl();
    }
    
    /**
     * 删除
     */
    @Test
    public void deleteStudent(){
        //删除id是1的数据
        studentDao.deleteStudent(1);
    }

    这样就完成了一个删除操作。

    修改数据

    在mapper中添加修改SQL

    <update id="updateStudent">
        UPDATE t_student set name=#{name},age=#{age},score=#{score} where id=#{id}
    </update>
    在StudentDao中添加updateStudent方法并在StudentDaoImple中实现该方法:
    
     @Override
    public void updateStudent(Student student) {
        try(SqlSession sqlSession = MyBatisUtil.getSqlSession()) {
    
            //修改数据操作
            sqlSession.update("updateStudent", student);
            //提交SqlSession
            sqlSession.commit();
    
        }
    }

    在测试类中添加下面方法进行测试:

    @Test
    public void updateStudent(){
        Student student = new Student("郭富城", 50, 96.50);
        student.setId(2);
        studentDao.updateStudent(student);
    }

    这样就完成了一个修改的操作。

    返回List结果的查询

    StudentMapper.xml中添加查询的sql语句:

    <select id="selectAllStudents" resultType="student">
        SELECT id,name,age,score FROM t_student
    </select>

    其中resultType表示该SQL语句的返回的每一条的数据类型,因为在mybatis.xml文件中添加了类的别名:

    <typeAliases>
        <package name="com.monkey1024.bean"/>
    </typeAliases>

    所以resultType的值可以使用别名student,这里首字母大小写均可。

    在StudentDao中添加查询的方法,然后再StudentDaoImpl中重写:

     @Override
    public List<Student> selectAllStudents() {
    
        List<Student> result = null;
    
        try(SqlSession sqlSession = MyBatisUtil.getSqlSession()) {
            //查询数据操作
            result = sqlSession.selectList("selectAllStudents");
        }
    
        return result;
    }

    在测试类中添加下面内容:

    @Test
    public void selectAllStudents(){
        List<Student> students = studentDao.selectAllStudents();
        students.forEach((student)->{
            System.out.println(student);
        });
    }

    在控制台中看到输出结果就表示执行成功。

    查询单个对象

    上面的示例查询出了数据库中的所有Student对象,有时候我们只需要查询出某一条数据,请看如下示例,在mapper中添加下面SQL语句,这里我们根据传入的主键id进行查询:

    <select id="selectStudentById" resultType="student">
        SELECT id,name,age,score FROM t_student where id=#{id}
    </select>

    在StudentDaoImpl中添加下面方法:

    @Override
    public Student selectStudentById(int id){
    
        Student student = null;
    
        try(SqlSession sqlSession = MyBatisUtil.getSqlSession()) {
    
            //根据id查询数据操作
            student = sqlSession.selectOne("selectStudentById", id);
        }
    
        return student;
    }

    在测试类中进行测试,查询学生id是10的数据:

    @Test
    public void selectStudentById(){
        Student student = studentDao.selectStudentById(10);
        System.out.println(student);
    }

    模糊查询

    下面以Student类中的name属性来演示模糊查询,在mapper文件中添加SQL:

    <select id="selectStudentByName" resultType="student">
        SELECT id,name,age,score FROM t_student where name like '%' #{name} '%'
    </select>

    需要注意的是,这里面的’%’ #{name} ‘%’之间是没有+号的,即这里的字符串拼接不需要+号,而是需要空格。

    在StudentDaoImp中添加下面方法:

    @Override
    public List<Student> selectStudentByName(String name) {
        List<Student> result = null;
    
        try(SqlSession sqlSession = MyBatisUtil.getSqlSession()) {
    
            //查询数据操作
            result = sqlSession.selectList("selectStudentByName",name);
        }
    
        return result;
    }

    在测试类中进行测试:

    @Test
    public void selectStudentByName(){
        List<Student> students = studentDao.selectStudentByName("富");
        students.forEach((student)->{
            System.out.println(student);
        });
    }

    当查询出数据的时候则说明运行成功。

    模糊查询的另一种写法
    其实在上面mapper中的sql语句我们还可以使用$进行操作:

    <select id="selectStudentByName" resultType="student">
        SELECT id,name,age,score FROM t_student where name like '%${value}%'
    </select>

    因为我们传入的name是String字符串类型,所以这里需要注意的是${}中的内容只能写value,可以通过控制台打印的sql语句看出来,这种方式其实就是是字符串拼接,该方式可能会有SQL注入的问题。

    $和#的区别

    • #其实是占位符,通过控制台打印的sql语句可以看出,他是以?进行占位的,类似JDBC的PreparedStatement,可以防止SQL注入的问题,在上面的sql语句中我们写的是#{id},实际上#{}里面的内容可以写成其他字符串#{xxx},这里只是起着占位符的作用,mybatis会将sqlSession.selectList或sqlSession.selectOne等方法中的第二个参数赋值进去。因此如果sql语句需要获取用户的输入从而进行动态拼接的话,就需要使用#{}。
    • $是字符串拼接,参数会被直接拼接到SQL语句中,该方式会有SQL注入问题,如果SQL语句有我们程序员直接写好,不需要用户输入的话,可以使用${},不过一般还是建议使用#{}

     拓展:

    在实际开发中有时候会遇到数据库表中的字段名与实体类中的属性名不一致的情况,例如在t_student表中有一个字段名叫做password,然后在其对应的Student实体类中叫做pwd,此时要想进行查询操作的话,可以通过以下两种方式解决

    在SQL语句中使用别名

    <select id="selectStudentById" resultType="student">
        SELECT id,name,age,score,password pwd FROM t_student where id=#{id}
    </select>

    在查询password的时候将其命名一个别名pwd,此时mybatis可以正常查询。

    使用结果映射 resultMap

    这里的resultMap实际上是将数据库表中的字段与实体类中的属性建立一个映射关系,这样子,即使两者名字不一致,mybatis也会根据resultMap中的映射关系正常执行。

    <resultMap id="studentMapper" type="student">
        <id column="id" property="id"/>
        <result column="password" property="pwd"/>
    </resultMap>
    
    <select id="selectStudentById" resultMap="studentMapper">
        SELECT id,name,age,score,password FROM t_student where id=#{id}
    </select>

    上面示例中通过resultMap来创建了映射关系,id设置为studentMapper,然后在select查询语句中指定属性resultMap的值为studentMapper,这样子就不用在SQL语句中使用别名了。一般在较为复杂的SQL语句中会使用resultMap。

    在resultMap中添加了一个id的属性来指定主键,这样子可以提高mybatis的查询性能。resultMap中的type属性用来指定要映射的实体类。

    转载仅供个人学习,谢谢分享!

    来源:链接

     

  • 相关阅读:
    apache安装 解决无services
    需要看的书
    rbac
    IDocHostShowUI
    Eclipse快捷键大全
    Linux中vi显示中文乱码的问题
    如何编译安装Go语言
    ubuntu11.04 下LAMP 开发环境配置
    网络内核sk_buff结构体
    查看所有表名,查询结果加上字符
  • 原文地址:https://www.cnblogs.com/lucky1024/p/11130310.html
Copyright © 2011-2022 走看看