http://www.mybatis.cn/
这个网站的内容很有意思,值得收藏!
MyBatis原名iBatis
2010年从Apache迁移到了Google
原来的JDBC存在的毛病
SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- -- Table structure for `orders` -- ---------------------------- DROP TABLE IF EXISTS `orders`; CREATE TABLE `orders` ( `id` int(11) NOT NULL AUTO_INCREMENT, `user_id` int(11) NOT NULL COMMENT '下单用户id', `number` varchar(32) NOT NULL COMMENT '订单号', `createtime` datetime NOT NULL COMMENT '创建订单时间', `note` varchar(100) DEFAULT NULL COMMENT '备注', PRIMARY KEY (`id`), KEY `FK_orders_1` (`user_id`), CONSTRAINT `FK_orders_id` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of orders -- ---------------------------- INSERT INTO `orders` VALUES ('3', '1', '1000010', '2015-02-04 13:22:35', null); INSERT INTO `orders` VALUES ('4', '1', '1000011', '2015-02-03 13:22:41', null); INSERT INTO `orders` VALUES ('5', '10', '1000012', '2015-02-12 16:13:23', null); -- ---------------------------- -- Table structure for `user` -- ---------------------------- DROP TABLE IF EXISTS `user`; CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(32) NOT NULL COMMENT '用户名称', `birthday` date DEFAULT NULL COMMENT '生日', `sex` char(1) DEFAULT NULL COMMENT '性别', `address` varchar(256) DEFAULT NULL COMMENT '地址', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of user -- ---------------------------- INSERT INTO `user` VALUES ('1', '王五', null, '2', null); INSERT INTO `user` VALUES ('10', '张三', '2014-07-10', '1', '北京市'); INSERT INTO `user` VALUES ('16', '张小明', null, '1', '河南郑州'); INSERT INTO `user` VALUES ('22', '陈小明', null, '1', '河南郑州'); INSERT INTO `user` VALUES ('24', '张三丰', null, '1', '河南郑州'); INSERT INTO `user` VALUES ('25', '陈小明', null, '1', '河南郑州'); INSERT INTO `user` VALUES ('26', '王五', null, null, null);
import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; public class JdbcDemo { public static void main(String[] args) { Connection connection = null; PreparedStatement preparedStatement = null; ResultSet resultSet = null; try { // 加载数据库驱动 Class.forName("com.mysql.jdbc.Driver"); // 通过驱动管理类获取数据库链接 connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8", "root", "root"); // 定义sql语句 ?表示占位符 String sql = "select * from user where username = ?"; // 获取预处理statement preparedStatement = connection.prepareStatement(sql); // 设置参数,第一个参数为sql语句中参数的序号(从1开始),第二个参数为设置的参数值 preparedStatement.setString(1, "王五"); // 向数据库发出sql执行查询,查询出结果集 resultSet = preparedStatement.executeQuery(); // 遍历查询结果集 while (resultSet.next()) { System.out.println(resultSet.getString("id") + " " + resultSet.getString("username")); } } catch (Exception e) { e.printStackTrace(); } finally { // 释放资源 if (resultSet != null) { try { resultSet.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if (preparedStatement != null) { try { preparedStatement.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if (connection != null) { try { connection.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } }
毛病
①频繁的连接和释放资源 ②硬编码问题(要着改SQL) ③返回结果不好包装处理
Mybatis架构
1、 mybatis配置SqlMapConfig.xml,此文件作为mybatis的全局配置文件,配置了mybatis的运行环境等信息。mapper.xml文件即sql映射文件,文件中配置了操作数据库的sql语句。此文件需要在SqlMapConfig.xml中加载。 2、 通过mybatis环境等配置信息构造SqlSessionFactory即会话工厂 3、 由会话工厂创建sqlSession即会话,操作数据库需要通过sqlSession进行。 4、 mybatis底层自定义了Executor执行器接口操作数据库,Executor接口有两个实现,一个是基本执行器、一个是缓存执行器。 5、 Mapped Statement也是mybatis一个底层封装对象,它包装了mybatis配置信息及sql映射信息等。mapper.xml文件中一个sql对应一个Mapped Statement对象,sql的id即是Mapped statement的id。 6、 Mapped Statement对sql执行输入参数进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql前将输入的java对象映射至sql中,输入参数映射就是jdbc编程中对preparedStatement设置参数。 7、 Mapped Statement对sql执行输出结果进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql后将输出结果映射至java对象中,输出结果映射过程相当于jdbc编程中对结果的解析处理过程。
不跟spring整合时需要配置
sqlMapConfig.xml
<?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> <properties resource="jdbc.properties"/> <!-- 别名 包以其子包下所有类 头字母大小都行--> <typeAliases> <!-- <typeAlias type="com.itheima.mybatis.pojo.User" alias="User"/> --> <package name="com.itheima.mybatis.pojo"/> </typeAliases> <!-- 和spring整合后 environments配置将废除 --> <environments default="development"> <environment id="development"> <!-- 使用jdbc事务管理 --> <transactionManager type="JDBC" /> <!-- 数据库连接池 --> <dataSource type="POOLED"> <property name="driver" value="${jdbc.driver}" /> <property name="url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8" /> <property name="username" value="root" /> <property name="password" value="root" /> </dataSource> </environment> </environments> <!-- Mapper的位置 Mapper.xml 写Sql语句的文件的位置 --> <mappers> <!-- <mapper resource="sqlmap/User.xml" class="" url=""/> --> <!-- <mapper resource="sqlmap/User.xml" class="" url=""/> --> <!-- <mapper class="com.itheima.mybatis.mapper.UserMapper" /> --> <!-- <mapper url="" /> --> <package name="com.itheima.mybatis.mapper"/> </mappers> </configuration>
UserMapper.xml
<?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"> <!-- 写Sql语句 --> <mapper namespace="com.itheima.mybatis.mapper.UserMapper"> <!-- 通过ID查询一个用户 --> <select id="findUserById" parameterType="Integer" resultType="User"> select * from user where id = #{v} </select> <!-- //根据用户名称模糊查询用户列表 #{} select * from user where id = ? 占位符 ? == '五' ${} select * from user where username like '%五%' 字符串拼接 --> <select id="findUserByUsername" parameterType="String" resultType="com.itheima.mybatis.pojo.User"> select * from user where username like "%"#{haha}"%" </select> <!-- 添加用户 --> <insert id="insertUser" parameterType="com.itheima.mybatis.pojo.User"> <selectKey keyProperty="id" resultType="Integer" order="AFTER"> select LAST_INSERT_ID() </selectKey> insert into user (username,birthday,address,sex) values (#{username},#{birthday},#{address},#{sex}) </insert> <!-- 更新 --> <update id="updateUserById" parameterType="com.itheima.mybatis.pojo.User"> update user set username = #{username},sex = #{sex},birthday = #{birthday},address = #{address} where id = #{id} </update> <!-- 删除 --> <delete id="deleteUserById" parameterType="Integer"> delete from user where id = #{vvvvv} </delete> </mapper>
安照图示内容,需要搞一个session工厂了
import java.io.InputStream; import java.util.Date; import java.util.List; 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.Test; import com.itheima.mybatis.pojo.User; public class MybatisFirstTest { //成员变量 @Test public void testMybatis() throws Exception { //加载核心配置文件 String resource = "sqlMapConfig.xml"; InputStream in = Resources.getResourceAsStream(resource); //创建SqlSessionFactory SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in); //创建SqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); //执行Sql语句 命名空间com.itheima.mybatis.mapper.UserMapper User user = sqlSession.selectOne("test.findUserById", 10); System.out.println(user); } //根据用户名称模糊查询用户列表 @Test public void testfindUserByUsername() throws Exception { //加载核心配置文件 String resource = "sqlMapConfig.xml"; InputStream in = Resources.getResourceAsStream(resource); //创建SqlSessionFactory SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in); //创建SqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); //执行Sql语句 List<User> users = sqlSession.selectList("test.findUserByUsername", "五"); for (User user2 : users) { System.out.println(user2); } } //添加用户 @Test public void testInsertUser() throws Exception { //加载核心配置文件 String resource = "sqlMapConfig.xml"; InputStream in = Resources.getResourceAsStream(resource); //创建SqlSessionFactory SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in); //创建SqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); //执行Sql语句 User user = new User(); user.setUsername("何炅"); user.setBirthday(new Date()); user.setAddress("sadfsafsafs"); user.setSex("男"); int i = sqlSession.insert("test.insertUser", user); sqlSession.commit(); System.out.println(user.getId()); } //更新用户 @Test public void testUpdateUserById() throws Exception { //加载核心配置文件 String resource = "sqlMapConfig.xml"; InputStream in = Resources.getResourceAsStream(resource); //创建SqlSessionFactory SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in); //创建SqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); //执行Sql语句 User user = new User(); user.setId(29); user.setUsername("何炅292929"); user.setBirthday(new Date()); user.setAddress("222222sadfsafsafs"); user.setSex("女"); int i = sqlSession.update("test.updateUserById", user); sqlSession.commit(); } //删除 @Test public void testDelete() throws Exception { //加载核心配置文件 String resource = "sqlMapConfig.xml"; InputStream in = Resources.getResourceAsStream(resource); //创建SqlSessionFactory SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in); //创建SqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); sqlSession.delete("test.deleteUserById", 29); sqlSession.commit(); } }
Mybatis与Hibernate的区别
Mybatis不完全是一个ORM框架,因为MyBatis需要程序员自己编写Sql语句。
Mybatis学习门槛低,简单易学。
Mybatis无法做到数据库无关性,如果需要实现支持多种数据库的软件则需要自定义多套sql映射文件,工作量大。
dao层开发与测试(反面教材,自己写实现类)
import com.itheima.mybatis.pojo.User; public interface UserDao { //通过用户ID查询一个用户 public User selectUserById(Integer id); }
import java.util.List; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import com.itheima.mybatis.pojo.User; public class UserDaoImpl implements UserDao { //注入 private SqlSessionFactory sqlSessionFactory; public UserDaoImpl(SqlSessionFactory sqlSessionFactory) { this.sqlSessionFactory = sqlSessionFactory; } //通过用户ID查询一个用户 public User selectUserById(Integer id){ SqlSession sqlSession = sqlSessionFactory.openSession(); return sqlSession.selectOne("test.findUserById", id); } //通过用户名称模糊查询 public List<User> selectUserByUsername(Integer id){ SqlSession sqlSession = sqlSessionFactory.openSession(); return sqlSession.selectList("test.findUserById", id); } }
注意这个before方法,用得很好!
import java.io.InputStream; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.Before; import org.junit.Test; import com.itheima.mybatis.dao.UserDao; import com.itheima.mybatis.dao.UserDaoImpl; import com.itheima.mybatis.pojo.User; public class MybatisDaoTest { public SqlSessionFactory sqlSessionFactory; @Before public void before() throws Exception { //加载核心配置文件 String resource = "sqlMapConfig.xml"; InputStream in = Resources.getResourceAsStream(resource); //创建SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in); } @Test public void testDao() throws Exception { UserDao userDao = new UserDaoImpl(sqlSessionFactory); User user = userDao.selectUserById(10); System.out.println(user); } }
mapper取代dao
import com.itheima.mybatis.pojo.User; public interface UserMapper {
//遵循四个原则 //接口 方法名 == User.xml 中 id 名 //返回值类型 与 Mapper.xml文件中返回值类型要一致 //方法的入参类型 与Mapper.xml中入参的类型要一致 //命名空间 绑定此接口 public User findUserById(Integer id); }
注意关注/理解一下接口与实现类
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.Test; import com.itheima.mybatis.mapper.UserMapper; import com.itheima.mybatis.pojo.User; public class MybatisMapperTest { @Test public void testMapper() throws Exception { //加载核心配置文件 String resource = "sqlMapConfig.xml"; InputStream in = Resources.getResourceAsStream(resource); //创建SqlSessionFactory SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in); //创建SqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); //SqlSEssion帮我生成一个实现类 (给接口) UserMapper userMapper = sqlSession.getMapper(UserMapper.class); User user = userMapper.findUserById(10); System.out.println(user); } }
关于sqlMapConfig.xml文件
properties(属性) settings(全局配置参数) typeAliases(类型别名) typeHandlers(类型处理器) objectFactory(对象工厂) plugins(插件) environments(环境集合属性对象) environment(环境子属性对象) transactionManager(事务管理) dataSource(数据源) mappers(映射器)