从上一篇可以看到测试类有大量的代码冗余,那接下来对SqlSession的创建过程进行封装
1.使用了静态代码块,随着类的加载而执行,而且只执行一次,由于工厂对象是一个超级重量级资源,所以创建一次就足够了,在类加载时候创建它
2.和原来代码比起来有以下特点,减少了工厂的创建次数,减少了代码量,从下面编码可以看到减少了大约一半的代码,使其更加优雅
3.扩展:如果需要确定DAO和Service的使用的是不是同一个Connection对象可以把Sqlsession加进本地线程里面,这里就不加了(懒)
package MybaitsUtil; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import java.io.IOException; import java.io.InputStream; //获取sqlseesiopn对象的封装 public class Mybatisutil { public static SqlSessionFactory sqlSessionFactory; //用于对创建工厂 static { try { sqlSessionFactory=null; String resource = "Mybatis.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } catch (IOException e) { e.printStackTrace(); } } //返回SqlSession public static SqlSession getSqlSession() { SqlSession sqlSession = sqlSessionFactory.openSession(); return sqlSession; } //关闭SqlSession public static void close(SqlSession sqlSession) { if (sqlSession != null) { sqlSession.close(); } } }
依然使用上一篇的代码,对Mybatis的操作基本步骤:
在接口中声明方法
由于我们要增加记录,所以把记录存在实体类对象中,注意必须返回值是void(坑)
void InsertStudentinfo(StudentModle studentModle);
在对应接口配置文件中编写Sql
1.指定ID为接口中对应的方法
2.指定参数类型parameterType为类:MyFirstMybatisApplication.Bean.StudentModle,用于对应的mapper接口方法接受的参数类型
3.注意点:SQL参数必须和实体类的成员变量对应,因为我们是通过实体类传递信息,否则会抛出 There is no getter for property named xxx in xxx
<insert id="InsertStudentinfo" parameterType="MyFirstMybatisApplication.Bean.StudentModle"> insert into student (id,name,email,age) values( #{id},#{name},#{email},#{age}) </insert>
调用
1.给对应需要的字段赋值即可,没有对应赋值的在传输实体类时候,没有赋值的值为null
2.此处对代码进行了异常处理,如果出现问题会回滚事务
3.注意对增删改操作进行事物的提交
public void test7() { //Sqlseesion的创建,可以发现明显少打几行代码 SqlSession sqlSession = Mybatisutil.getSqlSession(); StudentDAO studentDAO = sqlSession.getMapper(StudentDAO.class); try { StudentModle studentModle = new StudentModle(); studentModle.setId(1); studentModle.setEmail("Ilovedyou@before.com"); studentModle.setAge(22); studentModle.setName("DZYS"); studentDAO.InsertStudentinfo(studentModle); sqlSession.commit(); } catch (Exception e) { e.printStackTrace(); sqlSession.rollback(); } }
具体操作和上面差不多,以及注意点
在接口中声明方法
void DeleStudentinfo(StudentModle studentModle);
在对应接口配置文件中编写Sql
<delete id="DeleStudentinfo" parameterType="MyFirstMybatisApplication.Bean.StudentModle"> DELETE from student where id=#{id} </delete>
调用
public void test6() { SqlSession sqlSession = Mybatisutil.getSqlSession(); StudentDAO studentDAO = sqlSession.getMapper(StudentDAO.class); try { StudentModle studentModle = new StudentModle(); studentModle.setId(1); studentDAO.DeleStudentinfo(studentModle); sqlSession.commit(); } catch (Exception e) { e.printStackTrace(); sqlSession.rollback(); } }
在接口中声明方法
void UpdateStudentinfo(StudentModle studentModle);
在对应接口配置文件中编写Sql
<update id="UpdateStudentinfo" parameterType="MyFirstMybatisApplication.Bean.StudentModle"> update student set name=#{name},age=#{age} where id=#{id} </update>
调用
public void test5() { SqlSession sqlSession = Mybatisutil.getSqlSession(); StudentDAO studentDAO = sqlSession.getMapper(StudentDAO.class); try { StudentModle studentModle = new StudentModle(); studentModle.setId(1); studentModle.setAge(22); studentModle.setName("DZYS"); studentDAO.UpdateStudentinfo(studentModle); sqlSession.commit(); System.out.println("studentModle = " + studentModle); } catch (Exception e) { e.printStackTrace(); sqlSession.rollback(); } }
基本就这个套路
之前看一些老的教程发现如果传输空值会报错,比如在数据库中某个值不像给它有值,只想给它弄个null,那么在实体类传输就设置null到对应参数会报错
查阅资源得知:jdbcType这东西,需要在sql参数中指定和实体类对应的参数,那么jdbcType怎么和java内置参数对应呢?
这里有个表,来自于:http://blog.csdn.net/loongshawn/article/details/50496460
可以查阅
不过我在使用最新版本Mybatis没有出现这个情况,我的版本是5.3.7