--------------------
线程不安全问题
首先明白什么是线程不安全:
举例:struts2中,每个action中都定义了model模型对象(action类中是全局对象的存在 数据域属性) 用于封装前端页面提交过来的数据 所以就造成了struts2是非线程安全的,
即struts2不能使用单例模式,而只能使用多例模式,因为:当进行多线程并发请求的时候 多个线程会共用一个成员变量的值(例如两个用户请求action时 他们的数据就会有问题)
所以为了解决这个问题 struts2自然就成了多例模式的存在(注解方式配置action时 @Scope(prototype))
所以这句话就可以解释了
----------------------------------------
问题的引出:使用原始的方式开发dao
实现类:
package org.mybatis.dao; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.po.User; public class UserDaoImpl implements UserDao { //通过构造注入SqlSessionFactory private SqlSessionFactory sqlSessionFacory; public UserDaoImpl(){ } public UserDaoImpl(SqlSessionFactory sqlSessionFacory){ this.sqlSessionFacory=sqlSessionFacory; } //问题1:因为sqlSession是非线程安全的 所以不能把sqlSession创建成全局变量 而只能写在每个方法体内 这就造成了问题2的产生 //问题2:这里面把sqlSession在每个方法中都进行了一次创建 以及事务提交 SQLSession关闭 出现大量重复代码 唯独不 //同的就是 执行的语句不同 //3.解决问题2的方法 就是使用代理模式 在执行真正的增删改查之前 先执行这些公共的代码 执行增删改查之后 执行公共代码 @Override public void deleteUser(int id) throws Exception { // TODO Auto-generated method stub SqlSession sqlSession=this.sqlSessionFacory.openSession(); sqlSession.delete("test.deleteUser",id); sqlSession.commit(); sqlSession.close(); } @Override public User findUserById(int id) throws Exception { // TODO Auto-generated method stub SqlSession sqlSession=this.sqlSessionFacory.openSession(); User user=sqlSession.selectOne("test.findUserById",id);//调用的是user.xml中写好的sql语句 //sqlSession.commit(); 没有做数据的变更 此代码不写 sqlSession.close(); return user; } @Override public void insertUser(User user) throws Exception { // TODO Auto-generated method stub SqlSession sqlSession=this.sqlSessionFacory.openSession(); sqlSession.insert("test.insertUser",user); sqlSession.commit(); sqlSession.close(); } }
测试代码:
package org.mybatis.dao; import static org.junit.Assert.*; import java.io.InputStream; 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 org.junit.Before; import org.junit.Test; import org.mybatis.po.User; public class UserDaoImplTest { private SqlSessionFactory sqlSessionFactory; //这个代码是在测试方法之前执行的代码 @Before public void setUp() throws Exception { String resource="SqlMapConfig.xml"; //得到配置文件流 InputStream resourceAsStream = Resources.getResourceAsStream(resource); //创建回话工厂 this.sqlSessionFactory=new SqlSessionFactoryBuilder().build(resourceAsStream); } @Test public void testFindUserById() throws Exception { UserDao userDao=new UserDaoImpl(sqlSessionFactory); User user=userDao.findUserById(1); System.out.println(user); } }
问题的解决:使用代理模式
测试下面配置的方法
创建接口类 接口中的方法 需要和上面的id一样
namespace需要写成接口类的地址
在mybatis核心配置文件中引入sql语句文件
测试类:
package org.mybatis.mapper; import java.io.InputStream; 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 org.junit.Before; import org.junit.Test; import org.mybatis.dao.UserDao; import org.mybatis.dao.UserDaoImpl; import org.mybatis.po.User; public class UserMapperTest { private SqlSessionFactory sqlSessionFactory; @Before public void setUp() throws Exception { // String resource="SqlMapConfig.xml"; InputStream input=Resources.getResourceAsStream(resource); sqlSessionFactory=new SqlSessionFactoryBuilder().build(input); } @Test public void testFindUserById() throws Exception { // UserDao userDao=new UserDaoImpl(sqlSessionFactory); // User user=userDao.findUserById(1); // System.out.println(user); SqlSession sqlSession=sqlSessionFactory.openSession(); //得到代理对象 UserMapper mapper = sqlSession.getMapper(UserMapper.class); //通过代理对象 调用UserMapper类中的方法 User user=mapper.findUserById(1); System.out.println(user); } }
开发思路:开发mapper.xml(UserMapper.xml) 开发mapper接口(UserMapper.java)(不需要实现类 因为sql代码在配置文件中已经创建了) 在核心配置文件中引入mapper.xml
然后就可以在测试类中通过代理对象
(
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
)
调用mapper接口中的方法
User user=mapper.findUserById(1);--------------------------------------------全局配置文件中属性:------------------------------
1.properties:
------------------------------------
---------------------------------------
---------------------------------
-------------------------------------
使用代理方式的前提下(1.配置文件中的namespace=对应接口类的全路径 2.接口类中的方法名=配置文件中statement对象【sql标签对象】的id值) mapper.xml和对应的接口类mapper.java在同一目录下 (接口类名称和xml配置文件名称一样) 加载该类所在的包即可
-------------------------------------------------------