mybatis开发dao的方法通常用两种,一种是传统DAO的方法,一种是基于mapper代理的方法,下面学习这两种开发模式.
写dao之前应该要对SqlSession有一个更加细致的了解
SqlSessionFactoryBuilder用于创建SqlSessionFacoty,SqlSessionFacoty一旦创建完成就不需要SqlSessionFactoryBuilder了,因为SqlSession是通过SqlSessionFactory生产,所以可以将SqlSessionFactoryBuilder当成一个工具类使用,最佳使用范围是方法范围即方法体内局部变量。
SqlSessionFactory是一个接口,接口中定义了openSession的不同重载方法,SqlSessionFactory的最佳使用范围是整个应用运行期间,一旦创建后可以重复使用,通常以单例模式管理SqlSessionFactory。
if (ExecutorType.BATCH == executorType) {
executor = newBatchExecutor(this, transaction);
} elseif (ExecutorType.REUSE == executorType) {
executor = new ReuseExecutor(this, transaction);
} else {
executor = new SimpleExecutor(this, transaction);
}
if (cacheEnabled) {
executor = new CachingExecutor(executor, autoCommit);
}
结论得出
每个线程都应该有它自己的SqlSession实例。SqlSession的实例不能共享使用,它也是线程不安全的。因此最佳的范围是请求或方法范围。绝对不能将SqlSession实例的引用放在一个类的静态字段或实例字段中。
打开一个 SqlSession;使用完毕就要关闭它。通常把这个关闭操作放到 finally 块中以确保每次都能执行关闭。
传统的方法是建立dao接口定义方法,然后创建其实现类,实现dao中的方法.下面代码用的还是第一篇的例子
无论是哪种开发方法,mapper.xml都要写的,mapper映射也都需要在SqlMapperConfig.xml中配置的
和上一篇中的一模一样,这里为了完整的流程才贴出来的
<mapper namespace="test">
<select id="findUserById" parameterType="int" resultType="com.aust.model.User">
SELECT * FROM user WHERE id=#{id}
select>
<select id="findUserByName" parameterType="java.lang.String" resultType="com.aust.model.User">
SELECT * from user WHERE nickname LIKE '%${value}%'
select>
<insert id="insertUser" parameterType="com.aust.model.User">
<selectKey keyProperty="id" resultType="java.lang.Integer" order="AFTER" >
SELECT last_insert_id()
selectKey>
INSERT INTO user(username,password,nickname,status) VALUE (#{username},#{password},#{nickname},#{status})
insert>
<delete id="deleteUser" parameterType="int">
DELETE FROM user WHERE id =#{id}
delete>
<update id="updateUser" parameterType="com.aust.model.User">
UPDATE user SET username=#{username},password=#{password},nickname=#{nickname} WHERE id = #{id}
update>
mapper>
在SqlMapperConfig,xml中配置即可
<mappers>
<mapper resource="mapper/User.xml"/>
mappers>
public interface UserDao {
//根据id查询用户
public User findUserById(int id);
//根据姓名模糊查询用户
public List findUserByName(String name);
//插入一个用户,返回主键
public int insertUser(User user);
//删除一个用户
public boolean deleteUser(int id);
//更新一个用户
public boolean updateUser(User user);
}
public class UserDaoImp implements UserDao{
private SqlSessionFactory factory;
//通过构造注入SqlSessionFactory,后期整合spring,全部交给spring管理
public UserDaoImp(SqlSessionFactory factory) {
this.factory = factory;
}
@Override
public User findUserById(int id) {
//放在方法体内创建,保证线程安全
SqlSession session = factory.openSession();
User user = session.selectOne("test.findUserById",id);
session.close();
return user;
}
@Override
public List findUserByName(String name) {
//放在方法体内创建,保证线程安全
SqlSession session = factory.openSession();
List users = session.selectList("test.findUserByName",name);
session.close();
return users;
}
@Override
public int insertUser(User user) {
//放在方法体内创建,保证线程安全
SqlSession session = factory.openSession();
session.insert("test.insertUser",user);
//一定要提交,不然是失败
session.commit();
session.close();
return user.getId();
}
@Override
public boolean deleteUser(int id) {
//放在方法体内创建,保证线程安全
SqlSession session = factory.openSession();
int i = session.delete("test.deleteUser",id);
//一定要提交,不然是失败
session.commit();
session.close();
return i>0;
}
@Override
public boolean updateUser(User user) {
//放在方法体内创建,保证线程安全
SqlSession session = factory.openSession();
int i = session.delete("test.updateUser",user);
//一定要提交,不然是失败
session.commit();
session.close();
return i>0;
}
}
SqlSessionFactory factory = null;
@Before
public void init(){
InputStream is = null;
try {
is = Resources.getResourceAsStream("SqlMapperConfig.xml");
} catch (IOException e) {
e.printStackTrace();
}
factory = new SqlSessionFactoryBuilder().build(is);
}
//测试取出单个
@Test
public void findUserByIdTest(){
UserDaoImp daoImp = new UserDaoImp(factory);
User user = daoImp.findUserById(2);
System.out.println(user);
}
//测试取出多个
@Test
public void findUserByNameTest(){
UserDaoImp daoImp = new UserDaoImp(factory);
List users = daoImp.findUserByName("张");
System.out.println(users);
}
//测试插入数据
@Test
public void insertUserTest(){
UserDaoImp daoImp = new UserDaoImp(factory);
User u = new User();
u.setUsername("niuli1");
u.setPassword("123456");
u.setNickname("牛李");
u.setStatus(2);
int index = daoImp.insertUser(u);
System.out.println(index);
}
以上五步就是传统DAO开发方法
Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象,代理对象的方法体同上边Dao接口实现类方法。换句话说也就是不用程序员自己编写DAO接口的实现类了
接口定义有如下特点:
1、Mapper接口方法名和Mapper.xml中定义的statement的id相同
2、Mapper接口方法的输入参数类型和mapper.xml中定义的statement的parameterType的类型相同
3、Mapper接口方法的输出参数类型和mapper.xml中定义的statement的resultType的类型相同
public interface UserMapper {
//根据id查询用户
public User findUserById(int id);
//根据姓名模糊查询用户
public List findUserByName(String name);
//插入一个用户,返回受影响的行数
public int insertUser(User user);
//删除一个用户,返回受影响的行数
public int deleteUser(int id);
//更新一个用户,返回受影响的行数
public int updateUser(User user);
}
Mapper接口开发需要遵循以下规范:
1、Mapper.xml文件中的namespace与mapper接口的类路径相同。
<mapper namespace="com.aust.dao.UserMapper">
mapper>
无论哪种方式都需要配置映射
<mappers>
<mapper resource="mapper/UserMapper.xml"/>
mappers>
@Before
public void init(){
InputStream is = null;
try {
is = Resources.getResourceAsStream("SqlMapperConfig.xml");
} catch (IOException e) {
e.printStackTrace();
}
factory = new SqlSessionFactoryBuilder().build(is);
}
//测试取出单个
@Test
public void findUserByIdTest(){
//获取sqlsession
SqlSession session = factory.openSession();
//创建mapper代理
UserMapper mapper = session.getMapper(UserMapper.class);
//利用mapper代理查询
User u = mapper.findUserById(2);
session.close();
System.out.println(u);
}
//测试取出多个
@Test
public void findUserByNameTest(){
SqlSession session = factory.openSession();
UserMapper mapper = session.getMapper(UserMapper.class);
List users = mapper.findUserByName("张");
session.close();
System.out.println(users);
}
//测试插入数据
@Test
public void insertUserTest(){
SqlSession session = factory.openSession();
UserMapper mapper = session.getMapper(UserMapper.class);
User u = new User();
u.setUsername("niuli1");
u.setPassword("123456");
u.setNickname("牛李");
u.setStatus(2);
int index = mapper.insertUser(u);
System.out.println(index);//获取受影响的行数
System.out.println(u.getId());//获取返回的自增主键
}
项目示例:
SSM框架整合: https://github.com/nl101531/JavaWEB
自己做的一个项目: https://github.com/nl101531/AUSTOJ