目录
SqlSession 是线程不安全的
SqlSession
是 线程不安全
的;
对于它,我们建议在方法体内部使用;这样,即使多个线程同时访问了,每个线程都占用一片自己的内存,因此 ,sqlsession
对象就在不同的内存区域内,因此,就可以避免掉线程冲突的问题 ;
原始 dao 开发方法
原始 dao
层开发,需要我们写 接口
和 实现类
;
接口
package xin.ijava.dao; import xin.ijava.pojo.User; /** * @author An */ public interface UserDao { /** * 添加用户 * @param user 封装好的用户信息 * @throws Exception */ public void insertUser(User user) throws Exception ; /** * 删除用户 根据 id * @param id 用户 id * @throws Exception */ public void deleteUserById(int id ) throws Exception ; /** * 更新用户 * @param user 封装新信息的用户对象 * @throws Exception */ public void updateUser(User user) throws Exception ; /** * 查找用户 * @param id 用户id * @return 用户对象 * @throws Exception */ public User findUserById(int id) throws Exception ; }
实现类
package xin.ijava.dao; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import xin.ijava.pojo.User; /** * @author An */ public class UserDaoImpl implements UserDao{ /** * 注入sqlSessionFactory 工厂 */ private SqlSessionFactory factory ; public UserDaoImpl(SqlSessionFactory factory){ this.factory = factory ; } @Override public void insertUser(User user) throws Exception { SqlSession sqlSession = factory.openSession() ; sqlSession.insert("test.insertUser",user) ; sqlSession.close(); } @Override public void deleteUserById(int id) throws Exception { SqlSession sqlSession = factory.openSession() ; sqlSession.delete("test.deleteUserById",id) ; sqlSession.close(); } @Override public void updateUser(User user) throws Exception { SqlSession sqlSession = factory.openSession() ; sqlSession.update("test.updateUserById",user) ; sqlSession.close(); } @Override public User findUserById(int id) throws Exception { SqlSession sqlSession = factory.openSession() ; User user = sqlSession.selectOne("test.findUserById",id) ; sqlSession.close(); return user; } }
总结
1、上面的实现类代码中,可以看出,代码中存在着大量的模板代码,我们重复的写着这些代码;
2、
硬编码问题
,我们把statement
的id
硬编码到了代码中 ;3、参数是
object
类型,导致传任何类型的数据进去,都不会报错,即使传的数据类型根本不是映射关系中要求的类型,也不会得到报错,导致编译期间不会提示错误,直到运行期才能知道错哪了 ;
Mapper 代理方法
程序员只需要写出 mapper
接口(相当于 dao
接口)即可,无须写出实现类 ;
mapper
的开发规范:
在
mapper.xml
中namespace
等于mapper
接口地址<mapper namespace="xin.ijava.dao.UserMapper">
mapper.java
接口中的方法名和mapper.xml
中的statement
的id
一致 ;mapper.java
接口中的方法输入参数类型和mapper.xml
中的statement
的parameterType
指定的类型一致 ;mapper.java
接口中的方法返回值类型和mapper.xml
中的statement
的resultType
指定的类型一致 ;
以上操作完成以后,就可以利用 mybatis
生成代理对象 ;
@Test
public void test2() throws Exception {
SqlSession sqlSession = factory.openSession() ;
// 获取代理对象,参数写上类的全路径名
UserMapper userMapper = sqlSession.getMapper(xin.ijava.dao.UserMapper.class) ;
// 利用代理对象,操作
User user = userMapper.findUserById(1) ;
System.out.println(user);
}
关于代理对象
代理对象是怎么知道具体调用什么方法的呢?
在构建代理对象的时候,会去查询 xxxMapper,xml
映射关系,根据标签名,就可以知道是调用什么方法了;标签名有: <select> 、<delete> 、<update> 、<insert>
;
根据接口方法名字,也就是 标签的 id
值,查询标签的名字,从而知道调用什么方法 ;
其中 select
方法,有点不同;因为有2中,selectOne
、selectList
;
代理对象,是根据接口的返回值来,判断调用哪一个的 ,假如接口的方法,返回单个 pojo
对象,则调用 selectOne
,返回集合类型,则调用 selectList
;