public class MybatisTest { 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<User> users = userDao.findAll(); for(User user : users) { System.out.println(user); } //6.释放资源 session.close(); in.close(); } }
在读取文件时,一般有两种方法,一种是采用绝对路径,另外一种是采用相对路径。若是采用绝对路径,其缺点为不易迁移和部署,在开发时若是咱们路径为“D:\SqlMapConfig.xml”,部署到服务器时,可能服务器上没有D盘。相对路径的缺点就在于,若是项目为Web工程,部署以后src目录就不存在了。所以在读取配置文件时,只有两种方法:html
1.使用类加载器:只能读取类路径的配置文件。java
2.使用SeverletContext对象的getPath()方法。mysql
在建立工厂时,mybatis使用了构建者模式,builder就是构建者,把对象的建立细节隐藏,使用户直接调用方法即可得到对象。sql
生产SqlSession对象时使用了工厂模式,能够下降类间的依赖关系,便于以后对项目进行修改。数据库
建立DAO接口实现类的代理对象实现了使用了代理模式,这样就不须要本身写DAO实现类。设计模式
1.注册驱动,获取connection对象数组
2.建立数据库的执行sql的预处理对象服务器
3.执行sql语句session
4.封装查询结果mybatis
5.释放资源
public class JDBCTest { public static void main(String[] args) { JDBCTest test=new JDBCTest(); test.firstJDBC(); } public void firstJDBC(){ Connection connection=null; PrepareStatement prepareStatement=null; ResultSet resultSet=null; try { //1.register,注册驱动 DriverManager.registerDriver(new Driver()); //2.获得数据链接。url格式:jdbc:mysql://主机IP:端口号/数据库名?user=用户名&password=密码 //由于MySQL安装时,端口号默认设置的是3306,因此都是3306 String url="jdbc:mysql://localhost:3306/sport?user=root&password=12345678"; connection=DriverManager.getConnection(url); //3.获得数据库的执行sql对象 String sql="select * from player"; //SQL查询语句 prepareStatement=connection.prepareStatement(); //4.执行语句 resultSet=prepareStatement.executeQuery(); while(resultSet.next()){ //取出查询的信息 String name=resultSet.getString("player_name"); int age=resultSet.getInt("player_age"); int score=resultSet.getInt("player_score"); System.out.println("name="+name+",age="+age+",score="+score); } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally { //5.关闭资源 if(connection!=null){ try { connection.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(prepareStatement!=null){ try { prepareStatement.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(resultSet!=null){ try { resultSet.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } }
<!-- mybatis的主配置文件 --> <configuration> <!-- 配置环境 --> <environments default="mysql"> <!-- 配置mysql的环境 --> <environment id="mysql"> <!-- 配置事务的类型 --> <transactionManager type="JDBC"></transactionManager> <!-- 配置数据源(链接池) --> <dataSource type="POOLED"> <!-- 配置链接数据库的四个基本信息 --> <property name="driver" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/> <property name="username" value="root"/> <property name="password" value="12345678"/> </dataSource> </environment> </environments> <!-- 指定映射配置文件的位置,映射配置文件指的是每一个dao独立的配置文件 --> <mappers> <mapper resource="dao/IUserDao.xml" /> </mappers> </configuration>
1.建立connection对象。经过主被配置文件SqlMapConfig.xml,咱们能够得到链接数据库的信息(驱动、路径、用户名和密码)以及映射配置文件的位置。经过链接数据库的信息,咱们能够构建connection对象。
<mapper namespace="dao.IUserDao"> <!-- 配置查询全部 --> <select id="findAll" resultType="domain.User"> select * from user; </select> </mapper>
2.建立prepareStatement对象。经过映射配置文件的信息,咱们能够得到执行的SQL语句和封装的实体类全限定类名,就能够建立prepareStatement对象。mybatis经过dom4j技术来解析xml文件获取上述信息。
3.存储解析结果。在获取相关信息中后,mybatis须要将执行的SQL语句和封装结果的实体类全限定类名组合起来定义成一个Mapper对象,每个Mapper对象对应一个完整String类型的id(namespace+“.”+id)。例如本项目中的SQL语句为“select * from user;”,封装结果的实体类全限定类名为“domain.user”,完整的id为"dao.IUserDao.findAll",这些都是String类型的字段。
4.利用反射技术封装。建立prePareStatement对象以后,经过resultSet = prepareStatement.executeQuery();语句咱们能够得到查询结果集,在对查询结果集进行封装时。咱们经过完整的id(即封装结果的全限定类名),利用反射技术(Class.forName("domain.User").getDeclaredConstructor().newInstance();)便可进行封装。因为实体类的属性和数据库表中的列名一致,能够把表的列名看成是实体类的属性名称,而后利用反射技术来根据名称获取每一个属性,并把值赋进去。反射参考连接。
//MybatisTest.class IUserDao userDao = session.getMapper(IUserDao.class); //DefaultSqlSession.class public <T> T getMapper(Class<T> type) { return this.configuration.getMapper(type, this); } //Configuration.class public <T> T getMapper(Class<T> type, SqlSession sqlSession) { return this.mapperRegistry.getMapper(type, sqlSession); } //MapperRegistry.class public <T> T getMapper(Class<T> type, SqlSession sqlSession) { MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory)this.knownMappers.get(type); if (mapperProxyFactory == null) { throw new BindingException("Type " + type + " is not known to the MapperRegistry."); } else { try { return mapperProxyFactory.newInstance(sqlSession); } catch (Exception var5) { throw new BindingException("Error getting mapper instance. Cause: " + var5, var5); } } } //MapperProxyFactory.class public T newInstance(SqlSession sqlSession) { MapperProxy<T> mapperProxy = new MapperProxy(sqlSession, this.mapperInterface, this.methodCache); return this.newInstance(mapperProxy); } protected T newInstance(MapperProxy<T> mapperProxy) { return Proxy.newProxyInstance(this.mapperInterface.getClassLoader(), new Class[]{this.mapperInterface}, mapperProxy); } //Proxy.class public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) { Objects.requireNonNull(h); final Class<?> caller = System.getSecurityManager() == null ? null : Reflection.getCallerClass(); /* * Look up or generate the designated proxy class and its constructor. */ Constructor<?> cons = getProxyConstructor(caller, loader, interfaces); return newProxyInstance(caller, cons, h); }
上述是MybatisTest类中,getMapper()的调用层级。能够看到最终调用的方法是public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h),这个方法有三个参数,分别是:
1.类加载器loader:使用和被代理对象相同的类加载器
2.代理对象要实现的接口字节码数组interfaces:和被代理对象实现的是相同的接口
3.代理方式h:就是加强的方法,实际上就是一个InvocationHandler接口的实现类,在实现类中调用selectList方法(查询全部方法)。
mybatis入门案例,能够参考个人上一篇博客:mybatis入门实例