在介绍开发Dao的方法之前先介绍下SqlSession。
1.先介绍一下SqlSessionFactoryBuilder:通过SqlSessionFactoryBuilder创建会话工厂SqlSessionFactory
将SqlSessionFactoryBuilder当成一个工具类使用即可,不需要使用单例管理SqlSessionFactoryBuilder。
在需要创建SqlSessionFactory时候,只需要new一次SqlSessionFactoryBuilder即可。
2.再介绍一下SqlSessionFactory:
通过SqlSessionFactory创建SqlSession,使用单例模式管理sqlSessionFactory(工厂一旦创建,使用一个实例)。将来mybatis和spring整合后,使用单例模式管理sqlSessionFactory。
3.最后重点介绍一下sqlSession:
sqlSession的诞生过程是这样的:我们先用SqlSessionFactoryBuilder创建一个SqlSessionFactory。然后再通过SqlSessionFactory创建一个SqlSession.
SqlSession是一个面向用户(程序员)的接口。
SqlSession中提供了很多操作数据库的方法:如:selectOne(返回单个对象)、selectList(返回单个或多个对象)、。
SqlSession是线程不安全的,在SqlSesion实现类中除了有接口中的方法(操作数据库的方法)还有数据域属性。
SqlSession最佳应用场合在方法体内,定义成局部变量使用。
现在我们来介绍原始Dao开发的方法(程序员需要写dao接口以及dao的实现类):
思路:、
程序员需要写dao接口和dao实现类。
需要向dao实现类中注入SqlSessionFactory,在方法体内通过SqlSessionFactory创建SqlSession
案例如下:
先给出案例的结构图:
第一步:先写po包下面的Uer实体类:
package cn.itcast.mybatis.po; import java.util.Date; public class User { private int id;//主键 private String username;//用户的名称 private Date birthday;//生日 private String sex;//性别 private String address;//地址 public int getId() { return id; } public void setId(int id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } }
第二步:编写SqlMapConfig.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <!-- 和spring整合后 environments配置将废除--> <environments default="development"> <environment id="development"> <!-- 使用jdbc事务管理--> <transactionManager type="JDBC" /> <!-- 数据库连接池--> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/mybaits?characterEncoding=utf-8" /> <property name="username" value="root" /> <property name="password" value="root" /> </dataSource> </environment> </environments> <!-- 把映射文件(sqlmap/user.xml)加载进sqlMapConfig.xml--> <mappers> <mapper resource="sqlmap/user.xml"/> </mappers> </configuration>
第三步:编写user.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"> <!-- nanmespace:命名空间。 作用就是对sql进行分类话管理,理解Sal分离 注意:使用mapper代理方式,namespace有特殊重要的作用 --> <mapper namespace="test"> <!-- 根据id获取用户信息 --> <!-- 在映射文件中配置很多sql语句 --> <!-- id:标识映射文件中的sql; 将sql语句封装到mappedStatement对象中,所以将id称为statement的id;parmenterType:指定输入的参数的类型,这里指定的int型 #{}表示一个占位符号; #{id}:其中的id表示接收输入的参数,参数名称就是id,如果输入参数就是简单类型,#{}中的参数名可以任意,可以value或其它名称 resultType:指定的sql输出结果的所映射的java对象类型,select指定resultType表示将单条记录映射成的java对象; --> <select id="findUserById" parameterType="int" resultType="cn.itcast.mybatis.po.User"> select * from user where id = #{id} </select> <!-- 自定义条件查询用户列表 resultType指的是单条记录所映射的java类型,不管查询的是多条还是单条 --> <select id="findUserByUsername" parameterType="java.lang.String" resultType="cn.itcast.mybatis.po.User"> select * from user where username like ‘%${value}%‘ </select> <!-- 添加用户: partmentType:指定输入参数类型是pojo(包括用户的信息) #{}中指定pojo的属性名,接收到pojo对象的属性值 --> <insert id="insertuser" parameterType="cn.itcast.mybatis.po.User"> <!-- 将插入的数据主键返回,返回到user对象中去。 SELECT LAST_INSERT_ID():得到刚insert进去的记录的主键值, 这个方法只适用于自增长的主键。 KeyProperty:将查询得到的主键值设置到paramaterType指定的对象的哪个属性。 order:SELECT LAST_INSERT_ID()执行的顺序。相对于insert语句来说它的执行顺序。 resultType:指定SELECT LAST_INSERT_ID()的结果类型 --> <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer"> SELECT LAST_INSERT_ID() </selectKey> <!-- 以上的代码是为了实现返回主键的功能 --> insert into user(username,birthday,sex,address) value(#{username},#{birthday},#{sex},#{address}) </insert> <!-- 删除用户 --> <delete id="deleteUser" parameterType="java.lang.Integer"> delete from user where id=#{id} </delete> <!-- 更新用户 --> <update id="updetaUser" parameterType="cn.itcast.mybatis.po.User"> update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id} </update> </mapper>
第四步:编写UserDao.java
package cn.itcast.mybatis.Dao; import cn.itcast.mybatis.po.User; public interface UserDao { //查找用户 public User findUserById(int id); //增加用户 public void insertUser(User user); }
第五步:编写UserDao的实现类UserDaoimpl.java
package cn.itcast.mybatis.Dao; import java.util.Date; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import cn.itcast.mybatis.po.User; public class UserDaoimpl implements UserDao { private SqlSessionFactory sqlSessionFactory; public UserDaoimpl(SqlSessionFactory sqlSessionFactory) { this.sqlSessionFactory=sqlSessionFactory; } @Override public User findUserById(int id) { SqlSession sqlSession=sqlSessionFactory.openSession(); User user=sqlSession.selectOne("test.findUserById", id); return user; } @Override public void insertUser(User user) { SqlSession sqlSession=sqlSessionFactory.openSession(); sqlSession.insert("test.insertuser", user); sqlSession.commit(); sqlSession.close(); } }
第六步:编写Mybatis_daotest.java
package cn.itcast.mybatis.first; import java.io.IOException; import java.io.InputStream; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.Before; import org.junit.Test; import cn.itcast.mybatis.Dao.UserDao; import cn.itcast.mybatis.Dao.UserDaoimpl; import cn.itcast.mybatis.po.User; public class Mybatis_daotest { //会话工厂 private SqlSessionFactory sqlSessionFactory; @Before public void setup() throws IOException { String resource="SqlMapConfig.xml"; InputStream inputStream=Resources.getResourceAsStream(resource); sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream); } @Test public void testDao() { UserDao userDao=new UserDaoimpl(sqlSessionFactory); User user=userDao.findUserById(29); System.out.println(user.getUsername()); } }
结果:输出王王;运行结果正确。
上面是Dao的开发,但是存在一些问题,我们来总结一下原始dao开发问题。
1、dao接口实现类方法中存在大量模板方法,设想能否将这些代码提取出来,大大减轻程序员的工作量。
比如这些代码都要重复去写:
sqlSession.commit();
sqlSession.close();
2、调用sqlsession方法时将statement的id硬编码了
User user=sqlSession.selectOne("test.findUserById", id);
3、调用sqlsession方法时传入的变量,由于sqlsession方法使用泛型,即使变量类型传入错误,在编译阶段也不报错,不利于程序员开发。
比如User user=sqlSession.selectOne("test.findUserById", id);我这么写也是可以的User user=sqlSession.selectOne("test.findUserById", new Object());
因为这些问题,我们接下来要学习mapper代理的方法