Mybatis基础知识(1)
来源:互联网 发布:矩阵乘法公式 编辑:程序博客网 时间:2024/05/21 22:25
1、原生态JDBC
1.1、原生态jdbc程序:
package lsq.mybatis.jdbc;import java.sql.Connection;import java.sql.DriverManager;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;/** * 基本的jdbc程序 * @author Daniel Li * */public class JdbcTest {public static void main(String[] args) {//数据库连接Connection connection = null;//预编译的Statement,使用预编译的Statement提高数据库性能PreparedStatement preparedStatement = null;//结果集ResultSet resultSet = null;try {//注册数据库驱动Class.forName("com.mysql.jdbc.Driver");//通过驱动管理类获取数据库连接connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatisday1", "root", "root");//定义sql语句,?表示占位符String sql = "select * from user where username = ?";//获取预处理statementpreparedStatement = 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) {e.printStackTrace();}}if(preparedStatement!=null){try {preparedStatement.close();} catch (SQLException e) {e.printStackTrace();}}if(connection!=null){try {connection.close();} catch (SQLException e) {e.printStackTrace();}}}}}1.2、原生态jdbc问题总结
1)数据库连接,使用时就创建,不使用立即释放,对数据库进行频繁连接开启和关闭,造成数据库资源浪费,影响数据库性能。
设想:使用数据库连接池管理数据库连接。
2)将sql语句硬编码到Java代码中,如果sql语句修改,需要重新编译Java代码,不利于系统维护。
设想:将sql语句配置在xml配置文件中,即使sql变化,也不需要对java代码进行重新编译。
3)向preparedStatement中设置参数,对占位符位置和设置参数值,硬编码在java代码中,不利于系统维护。
设想:将sql语句及占位符号和参数全部配置在xml中。
4)从resultSet中遍历结果集数据时,存在硬编码,将获取表的字段进行硬编码,不利于系统维护。
设想:将查询的结果集,自动映射成java对象。
2、Mybatis框架
2.1、Mybatis是什么?
Mybatis是一个持久层框架,是Apache下的顶级项目。
Mybatis让程序员将主要精力放在sql上,通过Mybatis提供的映射方式,自由灵活生成(半自动化,大部分需要程序员编写sql)满足需要的sql语句。
Mybatis可以将向preparedStatement中的输入参数自动进行输入映射,将查询结果集灵活映射成java对象。(输出映射)
2.3、Mybatis基础架构
基础支持层:Mybatis的一些运行环境(数据源、事务、基本配置加载、缓存处理等)
数据处理层:Mybatis负责接收参数、解析参数,并且执行返回映射结果集。
接口层:Mybatis提供操作数据库的一些接口,供程序员使用。
2.2、Mybatis框架运行流程
加载全局配置文件:加载数据源、事务,用来操作数据库;
获取sqlSessionFactory:用来生成sqlSession,其中sqlSessionFactory是线程安全的(不共享)
sqlSession:由sqlSessionFactory生产,sqlSession中提供了一系列操作数据库的接口,程序员通过调用sqlSession提供的接口来操作数据。
3、入门程序
3.1、创建全局配置文件SQLMapConfig.xml
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd"><configuration><!-- mybatis初始化环境的配置,可以配置多个环境 spring tools suit --><environments default="development"><!-- 配置当前自己的运行环境 --><environment id="development"><!-- jdbc事务,Mybatis负责管理 --><transactionManager type="JDBC" /><!-- jdbc数据源,Mybatis进行管理 --><dataSource type="POOLED"><property name="driver" value="com.mysql.jdbc.Driver" /><property name="url"value="jdbc:mysql://localhost:3306/mybatis_day01?characterEncoding=utf-8" /><property name="username" value="root" /><property name="password" value="root" /></dataSource></environment></environments><mappers><mapper resource="sqlMap/UserMapper.xml" /></mappers></configuration>3.2、创建映射文件
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!-- mapper:表示mybatis的映射文件的开始,namespace:命名空间,用来隔离sql语句(mapper文件的唯一标示),可以随意命名注意:namespace在接口代理开发中,有特殊含义,不能自定义命名 --><mapper namespace="test"><!-- select:mybatis提供的用来查询的标签;id:mybatis加载映射文件之后,把映射文件封装成一个对象,mappedStatement;查询语句被封装成一个Statement对象,id就是Statement的唯一标识;resultType:返回值类型,返回集合,不管返回的是单个对象还是集合,都是一样的返回值类型 --><select id="findAllUser" resultType="lsq.study.domain.User">select * from user</select></mapper>3.3、编写测试方法
package lsq.study.mybatis.test;import java.io.InputStream;import java.util.List;import lsq.study.domain.User;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;public class Main1 { @Test public void findAllUser() throws Exception{ //1、加载全局配置文件 String resource = "sqlMapConfig.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); //2、获取sqlSessionFactory SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //3、使用sqlSessionFactory获取sqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); //4、使用sqlSession操作数据库 List<User> list = sqlSession.selectList("test.findAllUser"); System.out.println(list); } }3.4、根据用户id进行查询
创建映射文件
<!-- 根据用户id进行查询id:statement的唯一标识;parameterType:传递参数类型resultType:返回值类型,根据id查询,返回的是单个对象,和上边查询集合的写法一样#{}:占位符,Mybatis会解析#{}为占位符。如果传递的参数是基本类型:int,string,long等等,#{}里面可以任意写。 --><select id="findUserById" parameterType="int" resultType="lsq.study.domain.User">select * from user where id = #{id}</select>测试方法
@Test public void findUserById(){ SqlSession sqlSession = sqlSessionFactory.openSession(); User user = sqlSession.selectOne("test.findUserById", 10); System.out.println(user); }3.5、根据用户名进行模糊查询
映射文件
<!-- 根据用户名模糊查询#{}:占位符,如果传递参数是非字符类型,获取参数是原样获取,如果是字符串,#{}获取时会自动添加一个引号。${}:拼接sql语句,不管传递参数是什么类型,都是原样获取如果传递是基本类型参数,int,string等,${}只能写value;如果传递参数是对象,#{}${}都是ognl表达式来获取,对象导航语言 属性.属性.属性 --><select id="findUserByUsername" parameterType="string" resultType="lsq.study.domain.User">select * from user where username like '%${value}%'</select>测试方法
@Test public void findUserByUsername(){ SqlSession sqlSession = sqlSessionFactory.openSession(); List<User> list = sqlSession.selectList("test.findUserByUsername", "张"); System.out.println(list); }3.6、根据用户id进行删除
映射文件
<!-- 根据用户id进行删除 --><delete id="deleteUserById" parameterType="int">delete from user where id = #{id}</delete>测试方法
@Test public void deleteUserById(){ SqlSession sqlSession = sqlSessionFactory.openSession(); sqlSession.delete("test.deleteUserById", 26); sqlSession.commit(); sqlSession.close(); }3.7、根据用户id进行更新
映射文件
<!-- 根据id更新用户parameterType:传递对象参数,使用ognl表达式进行获取。 --><update id="updateUserById" parameterType="lsq.study.domain.User">update user set username=#{username},sex=#{sex},birthday=#{birthday} where id=#{id}</update>测试方法
@Test public void updateUserById(){ SqlSession sqlSession = sqlSessionFactory.openSession(); User user = new User(); user.setAddress("上海市浦东新区成山路475弄45号401室"); user.setBirthday(new Date()); user.setUsername("马布里"); user.setSex("男"); user.setId(25); sqlSession.update("test.updateUserById", user); sqlSession.commit(); sqlSession.close(); }3.8、添加用户
映射文件
<!-- 添加用户Mybatis返回主键:使用selectKey标签。keyProperty,表示返回的对应JavaBean里边的属性(id);order:由于MySQL自增主键是在insert语句执行之后生成的,所以要使用AFTER; --><insert id="insertUser" parameterType="lsq.study.domain.User" useGeneratedKeys="true" keyProperty="id"><!-- 第一种方式 --><!-- <selectKey keyProperty="id" order="AFTER" resultType="int">select last_insert_id()</selectKey> --><!-- 第二种方式返回主键:直接在insert标签中配置useGeneratedKeys/keyProperty -->insert into user(id,username,birthday,sex,address) values(#{id},#{username},#{birthday},#{sex},#{address})</insert>测试代码
/* * Hibernate中级联保存外键自动生成: * user-order * user.setOrders(orders) * session.save(user) * * 但是在Mybatis中外键需要我们自己维护 * */ @Test public void insertUser(){ SqlSession sqlSession = sqlSessionFactory.openSession(); User user = new User(); user.setAddress("上海市浦东新区成山路475弄45号401室"); user.setBirthday(new Date()); user.setUsername("steven"); user.setSex("女"); sqlSession.insert("test.insertUser", user); System.out.println(user.getId()+"@@@@@@@@@@@@@@@@@"); sqlSession.commit(); sqlSession.close(); }3.9、Mybatis返回主键
a、返回int类型自增主键
第一种方式:
第二种方式:
b、返回uuid主键
c、返回oracle
总结:
1、parameterType
基本类型
对象
2、ResultType
基本类型
集合、对象(都写对象类型)
3、#$
#{}:占位符,如果传递参数是基本类型,#{}括号中可以是任意字符。
如果传递的是pojo对象,使用ognl表达式进行获取:属性.属性
如果传递的是字符类型,#{}会自动添加引号;
如果传递的是非字符类型,#{}会原样获取。
${}:拼接sql语句,不管传递的是字符类型还是非字符类型都会原样获取。
如果传递的是基本类型,${}括号中只能写value。
4、selectList和selectOne
Mybatis提供的底层查询接口方法,理论上来说不能混合使用。在接口开发当中尤其不能进行混合使用。
4、Mybatis的dao开发
4.1、Mybatis的dao的普通开发模式
自己定义接口和接口实现类
接口代码:
package lsq.study.dao;import java.util.List;import lsq.study.domain.User;public interface UserDao { public List<User> findAllUser(); public User findUserById(Integer id); public List<User> findUserByUsername(String username);}实现类:
package lsq.study.dao.impl;import java.util.List;import org.apache.ibatis.session.SqlSession;import org.apache.ibatis.session.SqlSessionFactory;import lsq.study.dao.UserDao;import lsq.study.domain.User;public class UserDaoImpl implements UserDao { private SqlSessionFactory sqlSessionFactory; String ns = "test."; public UserDaoImpl(SqlSessionFactory sqlSessionFactory){ this.sqlSessionFactory = sqlSessionFactory; } @Override public List<User> findAllUser() { SqlSession sqlSession = sqlSessionFactory.openSession(); List<User> list = sqlSession.selectList(ns + "findAllUser"); return list; } @Override public User findUserById(Integer id) { SqlSession sqlSession = sqlSessionFactory.openSession(); User user = sqlSession.selectOne(ns + "findUserById", id); return user; } @Override public List<User> findUserByUsername(String username) { SqlSession sqlSession = sqlSessionFactory.openSession(); List<User> list = sqlSession.selectList(ns + "findUserByUsername", username); return list; }}测试方法
@Test public void findAllUser01(){ UserDao userDao = new UserDaoImpl(sqlSessionFactory); List<User> list = userDao.findAllUser(); System.out.println(list); } @Test public void findUserById01(){ UserDao userDao = new UserDaoImpl(sqlSessionFactory); User user = userDao.findUserById(25); System.out.println(user); } @Test public void findUserByUsername01(){ UserDao userDao = new UserDaoImpl(sqlSessionFactory); List<User> list = userDao.findUserByUsername("兰"); System.out.println(list); }
4.2、Mybatis的接口代理开发模式
只需要编写接口即可:
package lsq.study.dao;import java.util.List;import lsq.study.domain.User;public interface UserDao { public List<User> findAllUser(); public User findUserById(Integer id); public List<User> findUserByUsername(String username);}接口代码开发需要遵循几个规范:
☆:方法名必须和映射文件Statement的ID一致
☆:Namespace的名字必须是接口的全类路径名
☆:statement传递参数的类型必须和接口参数类型一致
☆:接口返回值类型必须和statement的返回值类型一致,Mybatis底层会根据接口返回值类型判断到底使用selectOne和selectList
注意:这里直接使用resource引用进行接口开发:
5、Mybatis和Hibernate的区别
Hibernate优点:Hibernate也是一个对JDBC封装的持久层框架。
☆:Hibernate是一个ORM框架,面向对象开发,不用自己写sql
☆:由于使用面向对象开发,如果进行数据库迁移,只需要修改方言
缺点:
☆:由于使用面向对象开发,不能开发特别复杂的业务项目。
☆:表的关系维护,Hibernate自己维护表关系,对我们是透明的,不容易进行优化。Hibernate表关系维护特别复杂。
☆:由于使用hql,先把hql转化成sql再进行执行,执行效率变低。生成的sql语句格式不容易维护。
适合需求基本不变的项目,企业当中的ERP、CRM
Mybatis框架:
Mybatis使用纯sql进行开发,程序员只需要集中精力在sql上面就可以,方便对sql进行优化。适合需求变化特别快的项目。互联网项目。
6、Mybatis全局配置文件sqlMapConfig
基本配置内容
SqlMapConfig.xml中的配置内容和顺序如下:
properties(属性)
settings(全局配置参数)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境集合属性对象)
environment(环境子属性对象)
transactionManager(事务管理)
dataSource(数据源)
mappers(映射器)
6.1、properties
Mybatis资源引用标签,用来引入外部资源文件
6.2、typeAliases(别名):Mybatis提供的配置别名的标签
6.2.1 定义单个别名
添加了别名之后,映射文件中的变化
之前
之后
6.2.2 批量定义别名
该包下的所有类都会被定义别名,别名即为该类类名。
Mybatis默认支持别名
6.3、typeHandlers(类型处理器)
通常Mybatis的typeHandlers完成jdbc类型和java类型的转换。
通常情况下,Mybatis提供的类型处理器满足日常的需求,不需要自定义。
6.4、Mappers(映射器)
第一种引入映射文件
第二种引入映射文件
批量扫面接口
7、ParameterType(Mybatis输入参数)
基本类型、pojo、map7.1、传递POJO
☆:需求:
查询参数特别复杂,涉及非持久化的参数
查询用户性别为男,姓马用户
如果业务参数类型特别复杂,使用包装类型pojo进行传递参数
接口方法:
package lsq.study.dao;import java.util.List;import lsq.study.domain.QueryUserVo;import lsq.study.domain.User;public interface UserDao { public List<User> findAllUser(); public User findUserById(Integer id); public List<User> findUserByUsername(String username); public List<User> findUserByUsernameAndSex(QueryUserVo vo); }
映射文件编写:
测试方法
@Test public void findUserByUsernameAndSex(){ SqlSession sqlSession = sqlSessionFactory.openSession(); UserDao userDao = sqlSession.getMapper(UserDao.class); QueryUserVo queryUserVo = new QueryUserVo(); UserCustom userCustom = new UserCustom(); userCustom.setSex("男"); userCustom.setUsername("马"); queryUserVo.setUserCustom(userCustom); List<User> list = userDao.findUserByUsernameAndSex(queryUserVo); System.out.println(list); }
7.2、传递map
需求同上。
映射文件
接口方法
测试方法
@Test public void findUserByMap(){ SqlSession sqlSession = sqlSessionFactory.openSession(); UserDao userDao = sqlSession.getMapper(UserDao.class); Map<String, Object> map = new HashMap<String, Object>(); map.put("sex", "男"); map.put("username", "马"); List<User> list = userDao.findUserByMap(map); System.out.println(list); }
8、ResultType
基本类型、pojo(返回对象或者返回集合都是写全类路径名,或者别名)
8.1、pojo类型
☆:需求查询满足条件的总记录和查询满足条件的总记录数
查询性别为女并且姓兰
查询满足条件总记录数:
映射文件
接口方法:
测试方法
@Test public void findUserByUsernameAndSex(){ SqlSession sqlSession = sqlSessionFactory.openSession(); UserDao userDao = sqlSession.getMapper(UserDao.class); QueryUserVo queryUserVo = new QueryUserVo(); UserCustom userCustom = new UserCustom(); userCustom.setSex("女"); userCustom.setUsername("兰"); queryUserVo.setUserCustom(userCustom); List<User> list = userDao.findUserByUsernameAndSex(queryUserVo); int count = userDao.findUserByUsernameAndSexCount(queryUserVo); System.out.println(count + "@@@@@@@@@@@@@"); System.out.println(list); }
8.2、map类型
开发中,如果返回的是基本类型,使用ResultType;如果返回的是对象,基本上使用ResultMap。
ResultMap高级映射:
映射文件:
测试方法
@Test public void findAllUser(){ SqlSession sqlSession = sqlSessionFactory.openSession(); UserDao userDao = sqlSession.getMapper(UserDao.class); List<User> list = userDao.findAllUser(); System.out.println(list); }测试结果
9、动态sql
9.1、使用动态sql可以对sql语句进行灵活的封装、拼接。
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="lsq.study.dao.UserDao"><resultMap type="user" id="BaseResultMapRm"><id column="id" property="id"/><result column="username" property="username"/><result column="birthday" property="birthday"/><result column="sex" property="sex"/><result column="address" property="address"/></resultMap><!-- where:Mybatis中提供的条件查询标签if:Mybatis提供的条件判断标签 --><select id="findUserByUsernameAndSex" parameterType="queryUserVo" resultMap="BaseResultMapRm">select * from user <where><if test="userCustom.sex != null and userCustom.sex!=''">and sex=#{userCustom.sex}</if><if test="userCustom.username!=null and userCustom.username!=''">and username like '%${userCustom.username}%'</if></where></select><select id="findUserByUsernameAndSexCount" parameterType="queryUserVo" resultType="int">select COUNT(1) from user<where><if test="userCustom.sex != null and userCustom.sex!=''">and sex=#{userCustom.sex}</if><if test="userCustom.username!=null and userCustom.username!=''">and username like '%${userCustom.username}%'</if></where></select></mapper>测试代码
@Test public void findUserByUsernameAndSex(){ SqlSession sqlSession = sqlSessionFactory.openSession(); UserDao userDao = sqlSession.getMapper(UserDao.class); QueryUserVo queryUserVo = new QueryUserVo(); UserCustom userCustom = new UserCustom(); userCustom.setSex("男"); userCustom.setUsername("马"); queryUserVo.setUserCustom(userCustom); List<User> list = userDao.findUserByUsernameAndSex(queryUserVo); int count = userDao.findUserByUsernameAndSexCount(queryUserVo); System.out.println(count+"############################"); System.out.println(list); }
9.2、sql片段
<resultMap type="user" id="BaseResultMapRm"><id column="id" property="id" /><result column="username" property="username" /><result column="birthday" property="birthday" /><result column="sex" property="sex" /><result column="address" property="address" /></resultMap><!-- 定义sql片段,抽取公共的sql语句sql:Mybatis提供的用来定义sql片段的标签;id:sql片段的唯一标识,可以定义多个sql片段 --><sql id="query_sql"><if test="userCustom.sex != null and userCustom.sex!=''">and sex=#{userCustom.sex}</if><if test="userCustom.username!=null and userCustom.username!=''">and username like '%${userCustom.username}%'</if></sql><!-- where:Mybatis中提供的条件查询标签 if:Mybatis提供的条件判断标签 --><select id="findUserByUsernameAndSex" parameterType="queryUserVo"resultMap="BaseResultMapRm">select * from user<where><include refid="query_sql"></include></where></select><select id="findUserByUsernameAndSexCount" parameterType="queryUserVo"resultType="int">select COUNT(1) from user<where><include refid="query_sql"></include></where></select>9.3、Foreach
SELECT * FROM USER WHERE id=1 OR id=23 OR id=33
SELECT * FROM USER WHERE id IN(1,23,33)
传递数组和集合都可以
映射文件测试代码:
@Test public void findUserByIds(){ SqlSession sqlSession = sqlSessionFactory.openSession(); UserDao userDao = sqlSession.getMapper(UserDao.class); List<Integer> ids = new ArrayList<Integer>(); ids.add(1); ids.add(25); ids.add(29); QueryUserVo queryUserVo = new QueryUserVo(); queryUserVo.setIds(ids); List<User> list = userDao.findUserByIds(queryUserVo); System.out.println(list); }测试结果:
测试代码
@Test public void findUserByIdsIN(){ SqlSession sqlSession = sqlSessionFactory.openSession(); UserDao userDao = sqlSession.getMapper(UserDao.class); List<Integer> ids = new ArrayList<Integer>(); ids.add(1); ids.add(25); ids.add(29); QueryUserVo queryUserVo = new QueryUserVo(); queryUserVo.setIds(ids); List<User> list = userDao.findUserByIdsIN(queryUserVo); System.out.println(list); }测试结果:
- Mybatis基础知识(1)
- Mybatis学习(1)--基础知识
- 1、mybatis基础知识
- Mybatis基础知识(2)
- Mybatis基础知识(3)
- MyBatis入门第1天--MyBatis基础知识(一)
- mybatis的基础知识 (一)
- Mybatis(第一天 基础知识)
- mybatis基础知识(第一更)
- mybatis基础知识(第二更)
- mybatis基础知识(第三更)
- mybatis基础知识
- Mybatis基础知识
- MyBatis基础知识
- Mybatis基础知识
- MyBatis基础知识
- mybatis基础知识
- Mybatis基础知识--入门程序篇1
- Linux常用操作命令
- C#的DrawString
- freemaker、velocity、jsp
- 批量删除sap物料
- 在浏览器中输入网址后都发生了什么
- Mybatis基础知识(1)
- JAVA 通过 CLI调用 FFmpeg
- iphone各个型号屏幕分辨率
- SpringMVC学习相关总结
- 浅谈UML的概念和模型之UML九种图
- jdbc 学习总结三之数据库连接池
- PV操作简单理解
- Linux之线程和进程及进程间通信
- Shell函数参数