mybatis_增删改查
# 在前面创建了第一个mybatis程序,在程序中实现了一个向数据库中添加数据的操作,代码如下
<insert id="insertStudent" parameterType="com.doaoao.bean.Student"> INSERT INTO t_student(name,age,score) VALUES (#{name},#{age},#{score}) </insert>id:在上方代码中定义的 id ,是该SQL语句的唯一标识,可以用来代表该SQL语句,在Java代码中要使用到该标识
parameterType:传入参数的类型,因为mybatis可以自动识别,所以可以不用配置
{}:里面要填写的内容是javabean中的属性,其底层是通过反射机制,调用bean类的相关属性的get方法来获取值
# 在dao的实现类中,手动对事务进行提交
//SqlSession继承了AutoCloseable接口,所以可以自动关闭 try(SqlSession sqlSession = MyBatisUtil.getSqlSession()) { //新增数据操作 sqlSession.insert("insertStudent", student); //提交SqlSession sqlSession.commit(); }可以将事务的提交变为"自动提交"或"不自动提交事务",修改util包下的MyBatisUtil类
//自动提交事务 sqlSessionFactory.openSession(true); //不自动提交事务 sqlSessionFactory.openSession(false); sqlSessionFactory.openSession(); // 不写就是默认为false# 获取插入数据的主键
1:修改StudentMapper.xml文件中的内容
<insert id="insertStudent" parameterType="com.doaoao.bean.Student"> INSERT INTO t_student(name,age,score) VALUES (#{name},#{age},#{score}) <selectKey resultType="int" keyProperty="id" order="AFTER"> SELECT @@identity </selectKey> </insert>
<!--
resultType:返回值类型(id的类型为int类型)
keyPeroperty:此处写"id",要与Student中的id名称一样
order:该属性有两个值,一个为 AFTER(语句执行之后),一个为 BEFORE(语句执行之前)
-->当进行上方这样的配置后,当mybatis完成数据的插入后,会将该数据的主键查询出来
2:重写Student的toString方法
// 从写Student中的toString方法 @Override public String toString() { return "Student{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + ", score=" + score + '}'; }
// 修改测试类 package com.doaoao.test; import com.doaoao.bean.Student; import com.doaoao.dao.StudentDao; import com.doaoao.dao.impl.StudentDaoImpl; import org.junit.Test; public class StudentTest01 { @Test public void insertStudent(){ StudentDao studentDao = new StudentDaoImpl(); Student student = new Student("刘德华", 52, 98.50); // 插入之前 id 的默认值为0 System.out.println("插入之前:" + student); studentDao.insertStudent(student); // 插入后可以获取数据在表中的自增id System.out.println("插入之后:"+ student); } }
// 最后输出 插入之前:Student{id=0, name='刘德华', age=52, score=98.5} 插入之后:Student{id=3, name='刘德华', age=52, score=98.5}# 注:在事务提交之前,已经获取到主键的id,也就是说,不管当前是提交还是回滚,都是先获取到主键的id,当执行SQL语句后,数据库就会给该行数据分配一个id,如果回滚的化,当前这个主键就无法再使用,当下次再进行插入数据时,会在该回滚主键id的后方再分配一个id。所以可以得出的结论是,主键的生成和事务没有关系,只要执行了SQL语句,mysql就会为其分配一个主键
1:再StudentMapper.xml中添加删除操作(和insert一样,添加在mapper标签中)
<!-- 注: #{id}中的id只是起到一个占位符的作用,也可写成#{XXX}--> <delete id="deleteStudent"> DELETE FROM t_student where id=#{id} </delete>2:在StudentDao接口中添加deleteStudent方法,再在StudentDaoImpl类中实现
// 在StudentDao中添加接口方法 void deleteStudent(int id); // 实现接口方法 @Override public void deleteStudent(int id) { try(SqlSession sqlSession = MyBatisUtil.getSqlSession()){ // 删除 sqlSession.delete("deleteStudent",id); // 提交SqlSession sqlSession.commit(); } }3:在测试类中添加测试方法
package com.doaoao.test; import com.doaoao.bean.Student; import com.doaoao.dao.StudentDao; import com.doaoao.dao.impl.StudentDaoImpl; import org.junit.Before; import org.junit.Test; public class StudentTest01 { private StudentDao studentDao; // 执行测试方法前执行该初始化语句
@Before public void initStudentDao(){ studentDao = new StudentDaoImpl(); } @Test public void insertStudent(){ // 插入语句省略 } @Test public void deleteStudent(){ studentDao.deleteStudent(2); // 将id为1的数据删除 } }...
1:在StudentMapper.xml文件中添加如下内容
<update id="updateStudent"> UPDATE t_student set name=#{name},age=#{age},score=#{score} where id=#{id} </update>2:在StudentDao中添加接口 updateStudent,并在实现类中实现该接口
// 添加接口方法 void updateStudent(Student student); // 实现该接口 @Override public void updateStudent(Student student) { try(SqlSession sqlSession = MyBatisUtil.getSqlSession()){ // 修改数据操作 sqlSession.update("updateStudent",student); // 提交SqlSession sqlSession.commit(); } }3:创建测试类
@Test public void updateStudent(){ Student student = new Student("李连杰",40,88.88); student.setId(3); studentDao.updateStudent(student); }...
1:在StudentMapper.xml中添加查询语句 resultType为返回的类型,利用的是别名的方法,在mybatis中配置别名方式
<!-- 查询中尽量别用 * 号,会影响查询效率 --> <select id="selectAllStudents" resultType="student"> SELECT id,name,age,score FROM t_student </select>2:在StudentDao中添加查询方法接口,在实现类中实现该接口
// 添加接口 List<Student> selectedAllStudent(); // 实现接口 @Override public List<Student> selectedAllStudent() { List<Student> result = null; try(SqlSession sqlSession = MyBatisUtil.getSqlSession()){ result = sqlSession.selectList("selectAllStudents"); } return result; }3:编写实现方法
@Test public void selectAllStudents(){ List<Student> students = studentDao.selectedAllStudent(); // students.forEach((student)->{ // System.out.println(student); // }); System.out.println(students); }....
1:修改StudentMapper.xml文件中的内容
<select id="selectStudentById" resultType="student"> SELECT id,name,age,score FROM t_student where id=#{id} </select>2:在StudentDao中添加接口,在实现类中实现接口
// 添加接口 Student selectStudentById(int id); // 实现接口 @Override public Student selectStudentById(int id) { Student student = null; try(SqlSession sqlSession = MyBatisUtil.getSqlSession()) { //根据id查询数据操作 student = sqlSession.selectOne("selectStudentById", id); } return student; }3:添加测试类
@Test public void selectStudentById(){ Student student = studentDao.selectStudentById(3); System.out.println(student); }
1:修改StudentMapper.xml文件中的内容
<select id="selectStudentByName" resultType="student"> SELECT id,name,age,score FROM t_student where name like '%' #{name} '%' </select>2:在StudentDao中添加接口,在实现类中实现接口
// 接口 List<Student> selectStudentByName(String name); // 接口实现 @Override public List<Student> selectStudentByName(String name) { List<Student> result = null; try(SqlSession sqlSession = MyBatisUtil.getSqlSession()) { //查询数据操作 result = sqlSession.selectList("selectStudentByName",name); } return result; }3:添加测试类
@Test public void selectStudentByName(){ List<Student> students = studentDao.selectStudentByName("张"); students.forEach((student)->{ System.out.println(student); }); }# 模糊查询的另一种写法
<select id="selectStudentByName" resultType="student"> SELECT id,name,age,score FROM t_student where name like '%${value}%' </select>因为我们传入的name是String字符串类型,所以这里需要注意的是${}中的内容只能写value,如果写上name会报错
可以通过控制台打印的sql语句看出来
SELECT id,name,age,score FROM t_student where name like '%张%'
上面这种方式相当于直接拼接到字符串中,该方式可能会存在SQL注入的问题。
$和#的区别
#其实是占位符,通过控制台打印的sql语句可以看出,#是以?进行占位的,#可以防止SQL注入的问题
$是字符串拼接,所添加的参数会被直接拼接到SQL语句中(如上所示),该方式会有SQL注入问题,
建议使用#{}
...
在开发过程中,可能会遇到数据库表中字段名和实体类中的属性名不一致的情况
例如在数据库表t_student中有有一个字段为 address ,然后再实体类Student中命名为 addr,如果想要进行操作,可利用下面的方式
## 使用别名方式
<select id="selectStudentByAddress" resultType="student"> SELECT id,name,age,score,address addr FROM t_student where id=#{id} </select>## 使用结果映射
将数据库中的字段和实体类中的字段建立一个映射关系
<resultMap id="studentMapper" type="student"> <id column="id" property="id" /> <result column="address" property="addr" /> </resultMap> <select id="selectStudentByAddress" resultType="studentMapper"> SELECT id,name,age,score,address FROM t_student where id=#{id} </select>在标签resultMap中的属性id的值设置为 studentMapper,然后再标签select张的属性resultType的值设置为与resultMap相同的studentMapper
resultMap中的type来指定要映射的实体类
再resultMap中添加一个id的属性来指定主键,可以提高mybatis的查询性能
...