为何会产生 Hibernate Mybatis 这类的dao层框架java
传统的jdbc 虽然执行速度很快,可是开发效率很低,随着面向对象开发的设计思想,在面向对象编程中 将对象 进行持久化,存入关系型的数据库时,因为关系型数据库的设计思想是数学思惟,在持久化时,必需要对象拆分各个属性值,才可存入数据库;传统的jdbc 持久化时 对象持久化时 ,取出对象的一个一个属性,过去繁琐,而且不便于维护,而市场上的面向对象的数据库还并不成熟,因此为了调节面向对象设计的开发思想与落后的关系型数据库之间持久化时繁琐的问题,产生了一种新的设计规范mysql
ORM (Object Relation Mapping) 程序员
Spring对数据库的操做在jdbc上面作了深层次的封装,也就是工具类 jdbcTemplatespring
先看一下jdbcTemplate的大体流程图sql
做用:数据库
1: 它提供了AOP式的事务管理apache
AOP式的事物管理:在之前的事务管理是要融合在逻辑代码中的,在逻辑代码中决定事务是否提交或者回滚,这样很容易形成代码难以维护,代码冗余
可是使用spring的声明式事务后,只须要在数据库处理方法上注解事务,就能够对操做进行管理,事务的设置和逻辑代码分开,容易维护。编程
<!-- 定义template组件 --> <bean id="template" class="org.springframework.jdbc.core.JdbcTemplate"> <!-- 注入链接信息 --> <property name="dataSource" ref="bonecp"> </property> </bean>
com.alibaba.druid.pool.DruidDataSource
<!-- DataSource 数据源 链接池 存储管理大量的连接 流行的 dbcp c3p0,proxool --> <!-- 数据源配置, 使用 BoneCP 数据库链接池 --> <bean id="bonecp" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> <!-- 数据源驱动类可不写,Druid默认会自动根据URL识别DriverClass --> <property name="driverClassName" value="com.mysql.jdbc.Driver" /> <!-- 基本属性 url、user、password --> <property name="url" value="jdbc:mysql://localhost:3306/medicine?useUnicode=true&characterEncoding=utf-8" /> <property name="username" value="root" /> <property name="password" value="root" /> <!-- 配置获取链接等待超时的时间 --> <property name="maxWait" value="60000" /> <!-- 配置间隔多久才进行一次检测,检测须要关闭的空闲链接,单位是毫秒 --> <property name="timeBetweenEvictionRunsMillis" value="60000" /> <!-- 配置一个链接在池中最小生存的时间,单位是毫秒 --> <property name="minEvictableIdleTimeMillis" value="300000" /> <property name="testWhileIdle" value="true" /> <property name="testOnBorrow" value="false" /> <property name="testOnReturn" value="false" /> <!-- 配置监控统计拦截的filters --> <property name="filters" value="stat" /> </bean>
下一部是根据表 编写实体类缓存
实体类session
package com.mxp.jdbc.entity; import java.io.Serializable; public class User implements Serializable { /** * */ private static final long serialVersionUID = 1L; private String id; private String userName; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } }
还须要根据实体类写一个rowmapper
注意这里要继承
org.springframework.jdbc.core.RowMapper,而后重写maprow方法
package com.mxp.jdbc.entity; import java.sql.ResultSet; import java.sql.SQLException; import org.springframework.jdbc.core.RowMapper; /** * 每一个实体类都有这个封装组件 * 将User记录封装成 User对象 * @author Administrator * */ public class UserRowMapper implements RowMapper<User>{ /** * arg1:第几行记录 */ @Override public User mapRow(ResultSet arg0, int arg1) throws SQLException { User user = new User(); user.setId(arg0.getString("id")); user.setUserName(arg0.getString("user_name")); return user; } }
下面能够编写dao了 编写以前咱们在spring的主配置文件中要把spring的扫描组件启动
<!-- spring组件扫描 --> <context:component-scan base-package="com.mxp"> </context:component-scan>
dao
package com.mxp.jdbc.dao; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Repository; import com.mxp.jdbc.entity.User; import com.mxp.jdbc.entity.UserRowMapper; @Repository public class ItinerantDAO { @Autowired private JdbcTemplate template;//注入的方式 public void save(User user){ String sql = "insert into test_user" + "(id,user_name) values (?,?)"; Object[] params = { user.getId(),user.getUserName() }; template.update(sql, params); } public List<User> findAll(){ String sql ="select * from test_user"; UserRowMapper rowMapper = new UserRowMapper(); List<User> list = template.query(sql, rowMapper); return list; } }
那如今就能够写测试方法
package test; import java.io.IOException; import java.util.List; import org.apache.ibatis.session.SqlSession; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.mxp.ControllerQW; import com.mxp.jdbc.dao.ItinerantDAO; import com.mxp.jdbc.entity.User; import com.mxp.mybatis.util.MybatisUtil; public class Test { public static void main(String[] args) {
//spring的主配置文件名 String conf = "spring-context.xml"; ApplicationContext ac = new ClassPathXmlApplicationContext(conf); ItinerantDAO dao = ac.getBean("itinerantDAO",ItinerantDAO.class); User user = new User(); user.setId("1455"); user.setUserName("文森特"); dao.save(user); } @org.junit.Test public void test(){
String conf = "spring-context.xml"; ApplicationContext ac = new ClassPathXmlApplicationContext(conf); ItinerantDAO dao = ac.getBean("itinerantDAO",ItinerantDAO.class); List<User> list = dao.findAll(); for(User u:list){ System.out.println(u.getUserName()); } } }
这jdbcTemplate 见的次数不多 至今为止 尚未见到用的
Mybatis
原来在咱们使用jdbc的问题
1 对数据库的链接 使用时就建立链接,不使用就当即释放,对数据库进行频繁链接开启和关闭,形成数据库的资源浪费,影响数据库的性能;
解决办法:使用数据库链接池,管理数据库的链接。
2 将sql语句硬编码到java代码中,若是sql语句修改,须要从新编译java代码,不利于系统维护,
解决办法:把sql语句I定义到xml配置文件里;
3 在向statement中设置参数,对站位符位置和设置参数数值,硬编码到java代码中,
4 从result结果集中遍历数据时,存在硬编码,讲获取表的字段名硬编码,不便于维护,
讲结果集 自动映射成java对象
mybatis的架构
是一个持久层的项目,是阿帕奇的顶级项目,
经过 mybatis提供的映射方式,半自动的生成sql,大部分仍是须要程序员编写sql
核心:输入映射:能够将statement中的输入参数自动输入到映射 经过ongl表达式,将查询的结果集灵活映射成为java对象(输出映射)
一、 mybatis配置
SqlMapConfig.xml,此文件做为mybatis的全局配置文件,配置了mybatis的运行环境等信息。
mapper.xml文件即sql映射文件,文件中配置了操做数据库的sql语句。此文件须要在SqlMapConfig.xml中加载。
二、 经过mybatis环境等配置信息构造SqlSessionFactory即会话工厂
三、 由会话工厂建立sqlSession即会话,操做数据库须要经过sqlSession进行。
四、 mybatis底层自定义了Executor执行器接口操做数据库,Executor接口有两个实现,一个是基本执行器、一个是缓存执行器。
五、 Mapped Statement也是mybatis一个底层封装对象,它包装了mybatis配置信息及sql映射信息等。mapper.xml文件中一个sql对应一个Mapped Statement对象,sql的id便是Mapped statement的id。
六、 Mapped Statement对sql执行输入参数进行定义,包括HashMap、基本类型、pojo,Executor经过 Mapped Statement在执行sql前将输入的java对象映射至sql中,输入参数映射就是jdbc编程中对preparedStatement设置参数。
七、 Mapped Statement对sql执行输出结果进行定义,包括HashMap、基本类型、pojo,Executor经过 Mapped Statement在执行sql后将输出结果映射至java对象中,输出结果映射过程至关于jdbc编程中对结果的解析处理过程。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <environments default="environment"> <environment id="environment"> <transactionManager type="JDBC" /> <!-- mybatis 自带链接池 --> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/medicine?useUnicode=true&characterEncoding=utf-8" /> <property name="username" value="root" /> <property name="password" value="root" /> </dataSource> </environment> </environments> <!-- 定义sqlMapper文件位置的 --> <mappers> <mapper resource="com/mxp/mybatis/entity/UserMapper.xml" /> </mappers> </configuration>
第二步 实体类及其sqlmap映射文件
package com.mxp.mybatis.entity; import java.io.Serializable; public class User implements Serializable { /** * */ private static final long serialVersionUID = 1L; private String id; private String userName; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } }
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.mxp.mybatis.entity.UserMapper"> <sql id="userColumns"> a.id AS "id", a.user_name AS "userName" </sql> <select id="findAll" resultType="com.mxp.mybatis.entity.User" > SELECT <include refid="userColumns"/> FROM test_user a </select> <select id="findLikeName" parameterType="string" resultType="com.mxp.mybatis.entity.User" > SELECT <include refid="userColumns"/> FROM test_user a <where> a.user_name like #{name} </where> </select> </mapper>
第三部 获取sqlsession
package com.mxp.mybatis.util; import java.io.InputStream; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; public class MybatisUtil { public static SqlSession getInsertance(){ SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); //这是读取文件后 造成一个输入流 涨知识了 //Test 其实就是一个类型 写本身的什么类型都行 主要是为了获取到getClassLoader().getResourceAsStream InputStream reader = MybatisUtil.class.getClassLoader().getResourceAsStream("SqlMapConfig.xml"); //获取sqlsessionFactory SqlSessionFactory factory = builder.build(reader); //获取session SqlSession session = factory.openSession(); return session; } }
第四部 写测试类
package test; import java.io.IOException; import java.util.List; import org.apache.ibatis.session.SqlSession; import com.mxp.mybatis.util.MybatisUtil; public class Test { @org.junit.Test public void getSqllSession() throws IOException{ SqlSession session = MybatisUtil.getInsertance(); System.out.println("获取session"); session.close(); } @org.junit.Test public void findall(){ SqlSession sqlsession = MybatisUtil.getInsertance(); List<com.mxp.mybatis.entity.User> list = sqlsession.selectList("findAll"); for(com.mxp.mybatis.entity.User u:list){ System.out.println(u.getUserName()); } sqlsession.close(); } @org.junit.Test public void findLike(){ SqlSession sqlsession = MybatisUtil.getInsertance(); List<com.mxp.mybatis.entity.User> list = sqlsession.selectList("findLikeName","%文%"); for(com.mxp.mybatis.entity.User u:list){ System.out.println(u.getUserName()); } sqlsession.close(); } }
Mybatis的
Mapper映射器接口规则,会自动生成接口实现类。
修饰public
a.根据sqlMapper定义的id属性当接口方法名
b 根据sqlMapper定义的parameterType类型定义参数类型
c 根据sqlMapper定义的resultType的类型 定义方法的返回类型
(多行使用list<泛型(resultType的类型)>,单行使resultType的类型)
d 将sqlMapper的namespace属性指定成为 包名.接口名字,就是接口的位置,
如何取到接口实现类呢
从sqlsession中获取
sqlsession.getMapper(接口的class对象);
mybatis替我生成实现类,在实现类中把sqlsession.select*的各类操做封装起来
首先实现 d
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.mxp.mybatis.dao.UserDao"> <sql id="userColumns"> a.id AS "id", a.user_name AS "userName" </sql> <select id="findAll" resultType="com.mxp.mybatis.entity.User" > SELECT <include refid="userColumns"/> FROM test_user a </select> <select id="findLikeName" parameterType="string" resultType="com.mxp.mybatis.entity.User" > SELECT <include refid="userColumns"/> FROM test_user a <where> a.user_name like #{name} </where> </select> </mapper>
a b c
package com.mxp.mybatis.dao; import java.util.List; import com.mxp.mybatis.entity.User; public interface UserDao { public List<User> findAll(); public List<User> findLikeName(String name); }
测试生成的映射器接口实现类
@org.junit.Test public void testMapper(){ SqlSession sqlsession = MybatisUtil.getInsertance(); UserDao dao = sqlsession.getMapper(UserDao.class); List<com.mxp.mybatis.entity.User> os = dao.findAll(); for(com.mxp.mybatis.entity.User u:os){ System.out.println(u.getUserName()); } sqlsession.close(); }