Mybatis使用入门与逆向工程

一.Mabatis架构

在这里插入图片描述

二.操作步骤

  • 1.导包(mybatis包+依赖包+数据库驱动包)

  • 2.配置文件:sqlMapConfig.xml+User.xml…

  • 3.获取SQLSession

    //加载核心配置文件
    String resource = "sqlMapConfig.xml";
    InputStream in = Resources.getResourceAsStream(resource);
    //创建SqlSessionFactory
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
    //创建SqlSession
    SqlSession sqlSession = sqlSessionFactory.openSession();
    
  • 4.元数据配置

    <mapper namespace="com.itheima.mybatis.mapper.UserMapper">
        <!--
    		parameterType:入参类型
    		 resultType:结果参数类型
    	-->
        <!--  通过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 '%五%'  字符串拼接  
    	-->
    	<selectid="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">
            <!--插入后获取User的id-->
    		<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>
    
  • 5.根据语句的id来执行sql

    // 执行Sql语句 
    User user = sqlSession.selectOne("test.findUserById", 10);
    System.out.println(user);
    
    // 执行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();
    // id已经封装到User中了
    System.out.println(user.getId());
    

三.Mybatis与Hibernate区别(面试题)

  • 1.Mybatis和hibernate不同,它不完全是一个ORM框架,因为MyBatis需要程序员自己编写Sql语句。mybatis可以通过XML或注解方式灵活配置要运行的sql语句,并将java对象和sql语句映射生成最终执行的sql,最后将sql执行的结果再映射生成java对象。
  • 2.Mybatis学习门槛低,简单易学,程序员直接编写原生态sql,可严格控制sql执行性能,灵活度高,非常适合对关系数据模型要求不高的软件开发,例如互联网软件、企业运营类软件等,因为这类软件需求变化频繁,一但需求变化要求成果输出迅速。但是灵活的前提是mybatis无法做到数据库无关性,如果需要实现支持多种数据库的软件则需要自定义多套sql映射文件,工作量大。
  • 3.Hibernate对象/关系映射能力强,数据库无关性好,对于关系模型要求高的软件(例如需求固定的定制化软件)如果用hibernate开发可以节省很多代码,提高效率。但是Hibernate的学习门槛高,要精通门槛更高,而且怎么设计O/R映射,在性能和对象模型之间如何权衡,以及怎样用好Hibernate需要具有很强的经验和能力才行 .

四.Mapper动态代理开发(只需写接口不需要实现类)

  • 遵循四个原则

    1.接口中的函数名要和Mapper.xml中的id相同

    2.返回值类型要和Mapper.xml中的resultType相同

    3.方法的参数要与Mapper.xml中的parameterType相同

    4.Mapper.xmlnamespace的值为接口的完整路径*

  • 操作过程

    1.接口

    public interface UserMapper {
    	/**
    	 * 根据id查询
    	 * 
    	 * @param id
    	 * @return
    	 */
    	User queryUserById(int id);
    
    	/**
    	 * 根据用户名查询用户
    	 * 
    	 * @param username
    	 * @return
    	 */
    	List<User> queryUserByUsername(String username);
    
    	/**
    	 * 保存用户
    	 * 
    	 * @param user
    	 */
    	void saveUser(User user);
    }
    
    

    2.Mapper.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">
    <!-- 1.namespace:命名空间,用于隔离sql -->
    <!-- 2.namespace必须和Mapper接口类路径一致 -->
    <mapper namespace="cn.itcast.mybatis.mapper.UserMapper">
    	<!-- 根据用户id查询用户 -->
    	<!-- 2. id必须和Mapper接口方法名一致 -->
    	<!-- 3. parameterType必须和接口方法参数类型一致 -->
    	<!-- 4. resultType必须和接口方法返回值类型一致 -->
    	<select id="queryUserById" parameterType="int"
    		resultType="cn.itcast.mybatis.pojo.User">
    		select * from user where id = #{id}
    	</select>
    
    	<!-- 根据用户名查询用户 -->
    	<select id="queryUserByUsername" parameterType="string"
    		resultType="cn.itcast.mybatis.pojo.User">
    		select * from user where username like '%${value}%'
    	</select>
    
    	<!-- 保存用户 -->
    	<insert id="saveUser" parameterType="cn.itcast.mybatis.pojo.User">
    		<selectKey keyProperty="id" keyColumn="id" order="AFTER"
    			resultType="int">
    			select last_insert_id()
    		</selectKey>
    		insert into user(username,birthday,sex,address) values
    		(#{username},#{birthday},#{sex},#{address});
    	</insert>
    </mapper>
    
    

    3.测试

    public class UserMapperTest {
    	private SqlSessionFactory sqlSessionFactory;
    
    	@Before
    	public void init() throws Exception {
    		// 创建SqlSessionFactoryBuilder
    		SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
    		// 加载SqlMapConfig.xml配置文件
    		InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
    		// 创建SqlsessionFactory
    		this.sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
    	}
    	@Test
    	public void testQueryUserById() {
    		// 获取sqlSession,和spring整合后由spring管理
    		SqlSession sqlSession = this.sqlSessionFactory.openSession();
    		// ******从sqlSession中获取Mapper接口的代理对象*****
    		UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    		// 执行查询方法
    		User user = userMapper.queryUserById(1);
    		System.out.println(user);
    		// 和spring整合后由spring管理
    		sqlSession.close();
    	}
    
    

五.sqlMapConfig.xml详解

  • properties:用于读取properties文件

    <!-- 是用resource属性加载外部配置文件 -->
    	<properties resource="db.properties">
    		<!-- 在properties内部用property定义属性 -->
    		<!-- 如果外部配置文件有该属性,则内部定义属性被外部属性覆盖 -->
    		<property name="jdbc.username" value="root123" />
    		<property name="jdbc.password" value="root123" />
    	</properties>
    
  • typeAliases:别名

    	<typeAliases>
    		<!-- 单个别名定义 -->
    		<typeAlias alias="user" type="cn.itcast.mybatis.pojo.User" />
    		<!-- 批量别名定义,扫描整个包及子包下的类,别名为类名(大小写不敏感) -->
    		<package name="cn.itcast.mybatis.pojo" />
    		<package name="其它包" />
    	</typeAliases>
    
  • mapper:映射

    1.使用相对路径的资源

    <mappers>
    	<mapper resource="com/tz/pojo/User.xml"/>
    </mappers>
    

    2.使用Mapper接口类路径

    <mappers>
    	<mapper  class="cn.itcast.mybatis.mapper.UserMapper"/>
    </mappers>
    

    注意:此种方法要求**Mapper接口名称(Mapper.java)Mapper映射文件(Mapper.xml)**名称相同,且放在同一个目录中。

    3.注册指定包下的所有mapper接口

    <mappers>
    	<package name="cn.itcast.mybatis.mapper"/>
    </mappers>
    

    注意:此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。

六.输入映射和输出映射

  • parameterType(输入)

    1.传递简单类型

    2.传递pojo

    3.传递pojo包装对象

  • resultType(输出)

    1.输出简单类型

    2.输出pojo对象

    3.输出pojo列表

  • resultMap(输出)

    用于pojo与sql字段不一致时使用

    <!--type是返回值类型-->
    <resultMap type="order" id="orderResultMap">
    	<!-- 定义主键 ,非常重要。如果是多个字段,则定义多个id -->
    	<!-- property:主键在pojo中的属性名 -->
    	<!-- column:主键在数据库中的列名 -->
    	<id property="id" column="id" />
    
    	<!-- 定义普通属性 -->
    	<result property="userId" column="user_id" />
    	<result property="number" column="number" />
    	<result property="createtime" column="createtime" />
    	<result property="note" column="note" />
    </resultMap>
    <!-- 查询所有的订单数据 -->
    <select id="queryOrderAll" resultMap="orderResultMap">
    	SELECT 
        	id, user_id,number,createtime, note 
        FROM `order`
    </select>
    
    

七.动态SQL(通过mybatis提供的各种标签方法实现动态拼接sql)

  • if标签:用于判断是否添加条件

    <select id="queryUserByWhere" parameterType="user" resultType="user">
    	SELECT id, username, birthday, sex, address FROM `user`
    	WHERE 1=1
    	<if test="sex != null and sex != ''">
    		AND sex = #{sex}
    	</if>
    	<if test="username != null and username != ''">
    		AND username LIKE
    		'%${username}%'
    	</if>
    </select>
    
  • where标签:上面的sql还有where 1=1 这样的语句,很麻烦可以使用where标签进行改造(前and)

    <select id="queryUserByWhere" parameterType="user" resultType="user">
    	SELECT id, username, birthday, sex, address FROM `user`
    	<!-- where标签可以自动添加where,同时处理sql语句中第一个and关键字 -->
    	<where>
    		<if test="sex != null">
    			AND sex = #{sex}
    		</if>
    		<if test="username != null and username != ''">
    			AND username LIKE
    			'%${username}%'
    		</if>
    	</where>
    </select>
    
  • sql片段

    <!-- 根据条件查询用户 -->
    <select id="queryUserByWhere" parameterType="user" resultType="user">
    	<!-- SELECT id, username, birthday, sex, address FROM `user` -->
    	<!-- 使用include标签加载sql片段;refid是sql片段id -->
    	SELECT <include refid="userFields" /> FROM `user`
    	<!-- where标签可以自动添加where关键字,同时处理sql语句中第一个and关键字 -->
    	<where>
    		<if test="sex != null">
    			AND sex = #{sex}
    		</if>
    		<if test="username != null and username != ''">
    			AND username LIKE
    			'%${username}%'
    		</if>
    	</where>
    </select>
    <!-- 声明sql片段 -->
    <sql id="userFields">
    	id, username, birthday, sex, address
    </sql>
    
    
  • foreach标签:向sql传递数组或List,mybatis使用foreach

    <!-- 根据ids查询用户 -->
    <select id="queryUserByIds" parameterType="queryVo" resultType="user">
    	SELECT * FROM `user`
    	<where>
    		<!-- foreach标签,进行遍历 -->
    		<!-- collection:遍历的集合,这里是QueryVo的ids属性,数组就是array,list就是list -->
    		<!-- item:遍历的项目,可以随便写,,但是和后面的#{}里面要一致 -->
    		<!-- open:在前面添加的sql片段 -->
    		<!-- close:在结尾处添加的sql片段 -->
    		<!-- separator:指定遍历的元素之间使用的分隔符 -->
    		<foreach collection="ids" item="item" open="id IN (" close=")"
    			separator=",">
    			#{item}
    		</foreach>
    	</where>
    </select>
    

    注意:使用vo对象是*时collection写的是vo中数组或list的属性名,而数组是array,list为list

八.关联查询

  • 一对一查询

    <resultMap type="order" id="orderUserResultMap">
    	<id property="id" column="id" />
    	<result property="userId" column="user_id" />
    	<result property="number" column="number" />
    	<result property="createtime" column="createtime" />
    	<result property="note" column="note" />
    	<!-- association :配置一对一属性 -->
    	<!-- property:order里面的User属性名 -->
    	<!-- javaType:属性类型 -->
    	<association property="user" javaType="user">
    		<!-- id:声明主键,表示user_id是关联查询对象的唯一标识-->
    		<id property="id" column="user_id" />
    		<result property="username" column="username" />
    		<result property="address" column="address" />
    	</association>
    </resultMap>
    
    <!-- 一对一关联,查询订单,订单内部包含用户属性 -->
    <select id="queryOrderUserResultMap" resultMap="orderUserResultMap">
    	SELECT
    		o.id,o.user_id,o.number,o.createtime,o.note,u.username,u.address
    	FROM 
        	`order` o
    	LEFT JOIN 
        	`user` u 
        ON 
        	o.user_id = u.id
    </select>
    
    
  • 一对多映射

    <resultMap type="user" id="userOrderResultMap">
    	<id property="id" column="id" />
    	<result property="username" column="username" />
    	<result property="birthday" column="birthday" />
    	<result property="sex" column="sex" />
    	<result property="address" column="address" />
    
    	<!-- 配置一对多的关系 -->
    	<collection property="orders" javaType="list" ofType="order">
    		<!-- 配置主键,是关联Order的唯一标识 -->
    		<id property="id" column="oid" />
    		<result property="number" column="number" />
    		<result property="createtime" column="createtime" />
    		<result property="note" column="note" />
    	</collection>
    </resultMap>
    <!-- 一对多关联,查询订单同时查询该用户下的订单 -->
    <select id="queryUserOrder" resultMap="userOrderResultMap">
    	SELECT
    		u.id,u.username,u.birthday,u.sex,u.address,o.id oid,o.number,o.createtime,o.note
    	FROM
    		`user` u
    	LEFT JOIN 
        	`order` o 
        ON 
        	u.id = o.user_id
    </select>
    
    

九.Mybatis整合Spring

  • 整合思路

    1.SqlSessionFactory对象应该放到spring容器中作为单例存在。

    2.传统dao的开发方式中,应该从spring容器中获得sqlsession对象。

    3.Mapper代理形式中,应该从spring容器中直接获得mapper的代理对象

    4.数据库的连接以及数据库连接池事务管理都交给spring容器来完成。

  • 配置SqlSessionFactoryBean

    <!-- 加载配置文件 -->
       <context:property-placeholder location="classpath:db.properties" />
    
    	<!-- 数据库连接池 -->
    	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
    		destroy-method="close">
    		<property name="driverClassName" value="${jdbc.driver}" />
    		<property name="url" value="${jdbc.url}" />
    		<property name="username" value="${jdbc.username}" />
    		<property name="password" value="${jdbc.password}" />
    		<property name="maxActive" value="10" />
    		<property name="maxIdle" value="5" />
    	</bean>
    
    	<!-- 配置SqlSessionFactory -->
    	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    		<!-- 配置mybatis核心配置文件 -->
    		<property name="configLocation" value="classpath:sqlMapConfig.xml" />
    		<!-- 配置数据源 -->
    		<property name="dataSource" ref="dataSource" />
    	</bean>
    </beans>
    

    原始dao开发,继承SqlSessionDaoSupport(类似HibernateDaoSupport),只需注入sqlSessionFactory;

    public class UserDaoImpl extends SqlSessionDaoSupport implements UserDao {
    	@Override
    	public User queryUserById(int id) {
    		// 获取SqlSession
    		SqlSession sqlSession = super.getSqlSession();
    		// 使用SqlSession执行操作
    		User user = sqlSession.selectOne("queryUserById", id);
    		// 不要关闭sqlSession
    		return user;
    	}
    }
    

    Mapper代理开发dao:

    1.创建接口,使用代理子类,mybatis中使用MapperFactoryBean来创建代理对象

    <!-- Mapper代理的方式开发方式一,配置Mapper代理对象 -->
    <bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
    	<!-- 配置Mapper接口 -->
    	<property name="mapperInterface" value="cn.itcast.mybatis.mapper.UserMapper" />
    	<!-- 配置sqlSessionFactory -->
    	<property name="sqlSessionFactory" ref="sqlSessionFactory" />
    </bean>
    

    由spring创建Mapper工厂,再由工厂创建代理类

    2.扫描包形式不用配置factory

    <!-- Mapper代理的方式开发方式二,扫描包方式配置代理 -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    	<!-- 配置Mapper接口,包下所有的接口 -->
    	<property name="basePackage" value="cn.itcast.mybatis.mapper" />
    </bean>
    

    每个mapper代理对象的id就是类名,首字母小写

十.Mybatis逆向工程

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
  PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
  "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">

<generatorConfiguration>
	<context id="testTables" targetRuntime="MyBatis3">
		<commentGenerator>
			<!-- 是否去除自动生成的注释 true:是 : false:否 -->
			<property name="suppressAllComments" value="true" />
		</commentGenerator>
		<!--数据库连接的信息:驱动类、连接地址、用户名、密码 -->
		<jdbcConnection driverClass="com.mysql.jdbc.Driver"
			connectionURL="jdbc:mysql://localhost:3306/mybatis" userId="root" password="root">
		</jdbcConnection>
		<!-- <jdbcConnection driverClass="oracle.jdbc.OracleDriver" connectionURL="jdbc:oracle:thin:@127.0.0.1:1521:yycg" 
			userId="yycg" password="yycg"> </jdbcConnection> -->

		<!-- 默认false,把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer,为 true时把JDBC DECIMAL 
			和 NUMERIC 类型解析为java.math.BigDecimal -->
		<javaTypeResolver>
			<property name="forceBigDecimals" value="false" />
		</javaTypeResolver>

		<!-- targetProject:生成PO类的位置 -->
		<javaModelGenerator targetPackage="cn.itcast.ssm.po"
			targetProject=".\src">
			<!-- enableSubPackages:是否让schema作为包的后缀 -->
			<property name="enableSubPackages" value="false" />
			<!-- 从数据库返回的值被清理前后的空格 -->
			<property name="trimStrings" value="true" />
		</javaModelGenerator>
		<!-- targetProject:mapper映射文件生成的位置 -->
		<sqlMapGenerator targetPackage="cn.itcast.ssm.mapper"
			targetProject=".\src">
			<!-- enableSubPackages:是否让schema作为包的后缀 -->
			<property name="enableSubPackages" value="false" />
		</sqlMapGenerator>
		<!-- targetPackage:mapper接口生成的位置 -->
		<javaClientGenerator type="XMLMAPPER"
			targetPackage="cn.itcast.ssm.mapper" targetProject=".\src">
			<!-- enableSubPackages:是否让schema作为包的后缀 -->
			<property name="enableSubPackages" value="false" />
		</javaClientGenerator>
		<!-- 指定数据库表 -->
		<table schema="" tableName="user"></table>
		<table schema="" tableName="order"></table>
	</context>
</generatorConfiguration>

猜你喜欢

转载自blog.csdn.net/qq_42469834/article/details/88774883