1.mybatis的入门
首先我们需要配置一下log4j.properties文件
代码如下,直接放进resource文件里就可以.
# Set root category priority to INFO and its only appender to CONSOLE.
#log4j.rootCategory=INFO, CONSOLE debug info warn error fatal
log4j.rootCategory=debug, CONSOLE, LOGFILE
# Set the enterprise logger category to FATAL and its only appender to CONSOLE.
log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE
# CONSOLE is set to be a ConsoleAppender using a PatternLayout.
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n
# LOGFILE is set to be a File appender using a PatternLayout.
log4j.appender.LOGFILE=org.apache.log4j.FileAppender
log4j.appender.LOGFILE.File=d:\axis.log
log4j.appender.LOGFILE.Append=true
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.LOGFILE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n
接下来再往后,入门的时候,我们创建一个测试类,我们使用main函数来执行。
main函数的思路: 读取配置文件 创建SqlSessionFactory工厂 创建SqlSession对象 创建Dao接口的代理对象 执行dao长的方法 释放资源
通过读取配置文件来准备一个工厂 工厂来创建一个对象 用于提供Dao的实现 有了Dao的实现就能提供查询方法 从而实现功能
SqlSessionFactory是一个接口,我们要用它的实现类,我们使用这个工厂,不外乎就是为了创建对象,于是Mybatis给我们提供工厂的时候,把工厂的实现细节给省略了,它为我们准备了一个SqlSessionFactoryBuilder的对象,这个对象可以直接new,new这个对象的好处就是我们用builder.build来构建工厂把流传进去,如何解析如何封装的细节都被隐藏起来,我们可以不再管,以后的事情就交给mybatis。
有了openSession 以后,我们可以用IUserDao来去接受session.getMapper()返回的代理对象
有了代理对象后,我们就可以使用代理对象来执行方法,得到返回的List,并遍历出结果。
接下来就是释放资源了
完整代码:
public class Test {
public static void main(String[] args)throws Exception {
//1.读取配置文件
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建SqlSessionFactory工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
//3.使用工厂生产SqlSession对象
SqlSession session = factory.openSession();
//4.使用SqlSession创建Dao接口的代理对象
IUserDao userDao = session.getMapper(IUserDao.class);
//5.使用代理对象执行方法
List users = userDao.findAll();
for(User user : users){
System.out.println(user);
}
//6.释放资源
session.close();
in.close();
}
}
到了这一步,还没有完成我们的流程
mybatis框架 并不知道查询完了以后要封装到哪里去,它并不清楚实体类和表的关系。
我们在开发过程中,除了Sql语句,还需要配置 ResultType 返回类型,当我们执行了findAll语句,实现封装的时候,会把结果集封装在User对象里,并把User对象添加到List当中,这样,我们的功能就完整了。
初学Mybatis,这些都是新的知识,不必过于纠结,关注流程就好。
mybatis的入门案例的步骤总结
- 读取配置文件
- 创建SqlSessionFactory工厂
- 创建SqlSession对象
- 创建Dao接口的代理对象
- 执行dao长的方法
- 释放资源、
还需要两点需要注意
- 用代理的方式,不写Dao接口
- 配置的过程中 必须说清楚,要配置到哪里去
我们强调这两点,是为了自定义Mybatis时把一些情况说明白。
2.mybatis 注解开发和编写dao实现类的方式
- ①mybatis基于注解的入门案例
如果我们觉得xml方式很麻烦,我们用注解的方式一样的也能实现功能。
注解如何使用?xml将不再有意义,可以删掉了,但是主配置文件是仍需要保存的。
使用注解的方式是在dao的方法上打上注解,我们的findAll方法是查询功能,我们用到了@select
注解
package com.itheima.dao;
import com.itheima.domain.User;
import org.apache.ibatis.annotations.Select;
import java.util.List;
/**
* @author 黑马程序员
* @Company http://www.ithiema.com
*
* 用户的持久层接口
*/
public interface IUserDao {
/**
* 查询所有操作
* @return
*/
@Select("select * from user")
List findAll();
}
在SqlMaoConfigxml文件中 我们指定了映射文件的位置 现在我们不是用配置文件了,我们应该用class属性来指定注解的dao的全限定类名。
我们运行一下,可以看到结果仍然能查询出来。注解比起来xml更加简单,它不再需要指定id和和返回类型。
总结
把 IUserDao.xml移除,在dao接口的方法上使用@Select注解,并指定Sql语句。
同时需要在SqlMapConfig中mapper配置时,使用class属性指定dao的全限定类名。
- ②编写dao实现类的方式
我们在实际开发中都是越简单越好,所以都是采用不写dao实现类的方式,不管是xml和注解配置。
mybatis也是支持写实现类的,如果我们需要写实现类,那要如何使用?
有实现类的时候我们需要提供方法来实现功能,我们需要通过测试类的sqlSession这个对象来看一看。
我们现在有了实现类,就不再需要代理实现类。
session有很多方法 selectForList 就是我们需要的,因为它返回的是一个List,但我们不是在这里用到它,而是在dao里面。
现在我们拥有了Dao的实现类 UserDaoImpl2,它里面需要有session对象的selectList方法。
我们现在是没有session对象的,于是我们需要定义一个能拿到session对象的SqlSessionFactory。
SqlSessionFactory怎么能保证它一定有值呢?
我们只需要在创建的时候传值就可以,换句话说,我们把默认构造函数给覆盖掉,这就相当于没有默认构造函数了。
当我们用的时候,它就一定会给我们传一个工厂进来。
有了工厂以后,我们就可以使用使用工厂 创建SqlSession对象,再用SqlSesson对象的selectList方法。需要思考的是,selectList方法里的参数的statement究竟该是什么?
我们也许会想,可用在statement里写上Sql语句,但如果在statement里写sql语句,那么我们配置文件又有什么用呢?所以我们的目标是需要读取配置文件里的sql语句。
如果我们在这里写上findAll的id,那么也过于理想化了,实际上开发过程中有很多FindAll方法,如何才能找到我们想用的哪个findAll呢?
这个时候
这个属性就起到作用了 它就指定了它是IUserDao,并且IUserDao里的id为findAll的方法,它能作为一种唯一标识来使用。
于是我们在statement上写上namespace和方法的id所组成的全限定名
这样我们就能执行selectList方法了。
完整的IUserDao的代码如下:
package com.itheima.dao.impl;
import com.itheima.dao.IUserDao;
import com.itheima.domain.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import java.util.List;
public class UserDaoImpl implements IUserDao {
private SqlSessionFactory sqlSessionFactory;
public UserDaoImpl(SqlSessionFactory sqlSessionFactory) {
this.sqlSessionFactory = sqlSessionFactory;
}
public List findAll() {
//用SqlSessionFactory创建SqlSeesion
SqlSession sqlSession = sqlSessionFactory.openSession();
//使用SqlSession查询所有方法
List lists = sqlSession.selectList("com.itheima.dao.IUserDao.findAll");
//释放资源
sqlSession.close();
//返回结果
return lists;
}
}
那么现在我们IUserDao的实现类有了方法可实现功能了 。
在测试类中,我们现在通过Dao来执行方法,来得到list。
我们用Dao的实现类也同样实现了功能 但是没有意义 因为不写Dao实现类也可以实现功能
那么我们为什么要写Dao的实现类呢 其实我们的目的就是为了说明 namespace 和 id 它们两个的作用,光有id是无法定位到的,还需要namespace。
即使我们用了代理对象来执行方法,也是需要让代理对象知道Sql语句的位置,它也是通过namespace定位到具体的Dao接口,并且根据id定位到方法,找到我们的sql语句。
3.mybatis入门案例中的设计模式分析
读取配置文件绝对路径和相对路径都会遇到一些问题
绝对路径:d:/xxxx/xxxx.xml
那如果我的机器没有D盘怎么办
相对路径: src/java/main/xxxxx.xml
而相对路径大家知道,如果是web工程,一部署,src文件就没了
所以这两种方式我们都不用
读取src文件 只有两招
1.使用类加载器,它只能读取类路径的配置文件
2.使用ServletContext对象的getRealPath(),它能得到当前应用部署的绝对路径,这个绝对路径就是项目运行在哪,它就在哪.
我们的工厂并不是我们自己创建的,创建工厂mybatis使用了构建者模式 什么是构建者模式?
举个例子 我们在创建一个工厂的时候 需要诸多考虑 比如选址 选完地址之后 还需要雇佣人工啊等操作 就费时费力 工厂也不一定建好 所以我们选择了找一个包工队 给他钱 剩下的事就交给他
那在这段代码中,builder就是构建者,我们只需要把钱给了它,剩下的事情都不要再操心.这不就是我们框架的目的吗?把繁琐的细节封装起来
生产SqlSession使用了工厂模式 它有降低耦合的作用
不修改源码的方式上,对代码进行增强.我们通过代理对象对接口进行增强,实现了不写实现类也能实现功能.
通过这里面的代码我们使用了这么多设计模式 其实它可以非常简单的为我们实现功能,如果要想做的简单,就直接getMapper然后直接拿个dao实现类接口即可
(我试了下没懂老师是什么意思,先记录在这里)
既然简单就能实现,那么我们为什么要分步骤写的那么复杂呢 为了灵活 每加出一个类都能可以选择更灵活的配置,比如builder就有很多重载的方法,我们虽然只用了InputStream的对象,但用其他的也行.
以后在实际开发中,以后可能就像刚刚老师讲的,以实现项目为目的,把细节隐藏。