培训第2个月的第7天----Mybatis初识

                 今天得知马上要考核了,心里还是有那么紧张的,虽然紧张,也不能阻止我总结今天学习的东西。。。。嘻嘻嘻嘻嘻嘻嘻嘻嘻嘻嘻嘻嘻

                  下面直接说今天学习的内容。

一.jar包

                  要想使用Mybatis开源框架来作为持久层,那么导入Mybatis的相关jar包是必不可少的。

二.创建Mybatis的核心配置文件

               和hibernate,spring一样,Mybatis也有自己的核心配置文件,这个文件的文件名和位置不是固定的。但我们通常把它放在src目录下。

​
<?xml version="1.0" encoding="UTF-8"?>
<!-- 导入Mybatis的约束,在编写代码的时候会有提示 -->
<!DOCTYPE configuration
       PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-config.dtd">
<!-- 编写配置 -->
<configuration>
    <!-- 利用log4j记录执行的sql语句 -->
  <settings>
       <setting name="lazyLoadingEnabled" value="false" />
       <setting name="logImpl" value="LOG4J" />
  </settings>
  
    
    <!-- 为类配置别名,防止代码繁重 .
                           一个类型好像可以同时有好几个别名,即使没有typeAliases标签,
         mapper.xml也能找到 默认的类别名(可以认为configuration标签中默认有一个typeAliases标签
                           用来存放系统提供的默认类别名(zijilijie))。
    -->
    <typeAliases>
    	 <typeAlias alias="User" type="com.java.Bean.User"/>
    	 <typeAlias alias="zidingyi_map" type="java.util.Map"/>
    	 <typeAlias alias="string" type="java.lang.String"/>
    </typeAliases>
      
	<environments default="development">	
		<environment id="development">
		
		    <!-- 先定义事务管理器,管理的底层表现为JDBC -->
			<transactionManager type="JDBC"/>
		    <!-- 数据源类型定义为    池类型 -->
			<dataSource type="POOLED">
			   <property name="driver" value="com.mysql.jdbc.Driver"/>
			   <property name="url" value="jdbc:mysql://localhost:3306/ssgl"></property>
			   <property name="username" value="root"></property>
			   <property name="password" value="root"></property>
			</dataSource>
			
		</environment>
	</environments>
	
	<!-- 引入mapper.xml 使在查询的时候,可以对应上相应的接口-->
    <mappers>
    	<mapper resource="com/java/Dao/UserMapper.xml"></mapper>
    	<mapper resource="com/java/Dao/DormitoryMapper.xml"></mapper>
    </mappers>
	
</configuration>

​

              这是mybatis最基本的核心配置文件,它定义了事务管理器和数据源,并且也导入了相关的mapper映射文件。在该文件的上方,利用log4j来记录执行的sql语句,在它的下面配置了类的别名。为类配置别名,防止代码繁重 ,一个类型可以同时有好几个别名,即使没有typeAliases标签,mapper.xml也能找到 默认的类别名(可以认为configuration标签中默认有一个typeAliases标签
用来存放系统提供的默认类别名(自己理解))。

三.创建相应的接口和对应的mapper映射文件

               我们需要定义一个接口,用于存放操作数据库的方法,并在映射文件中将这个接口实现。

package com.java.Mapper;

import java.util.List;
import java.util.Map;

import com.java.Bean.User;

//创建接口,用于映射mapper.xml,并且定义所要操作数据库的方法
public interface UserMapper {
  
	 //定义要操作数据库的方法
	 public User select_one_user(User user);
	 
	 public User select_one_user1(User user);
	 
	 public List<User> select_map_user(User user);
	
}

                  映射文件:

<?xml version="1.0" encoding="UTF-8"?>
<!-- 导入所需要的约束,用来约定在该xml文件中能够使用的标签,并在写标签的时候有提示功能 -->
<!DOCTYPE mapper
       PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- 进行配置 映射文件,将接口中的方法一一实现 -->
<mapper namespace="com.java.Mapper.UserMapper">

	<!-- 简化sql代码 -->
	<sql id="select_1">
		select * from t_user 
	</sql>
	
	
    <!-- 定义结果集 -->
    <resultMap id="user_map" type="User">
    	<result column="userid" property="userId" javaType="string"></result>
    	<result column="userpassword" property="userPassword" javaType="string"></result>
    	<result column="username" property="userName" javaType="string"></result>
    	<result column="usersex" property="userSex" javaType="string"></result>
    	<result column="userrole" property="userRole" javaType="string"></result>
    	<result column="usercollege" property="userCollege" javaType="string"></result>
    	<result column="usermajor" property="userMajor" javaType="string"></result>
    	<result column="userclass" property="userClass" javaType="string"></result>
    	<result column="dormitoryid" property="dormitoryId" javaType="string"></result>
    </resultMap>

	<select id="select_one_user" parameterType="com.java.Bean.User" resultType="com.java.Bean.User">
		select * from t_user where userId= #{userId} 
	</select>
	
	<select id="select_one_user1" parameterType="User" resultType="User">
		select * from t_user where userId= #{userId} 
	</select>
	
	<!-- 演示查询结果集的情况  ,只定义实现,没有接口,不会报错-->
	<select id="select_map_user" parameterType="User" resultMap="user_map">
		<include refid="select_1"></include>
		where username= #{userName} 
	</select>
	

</mapper>

                   当我们在测试类的时候,需要定义所要所要执行的方法类型,比如在《select》标签内,进行查询操作。注意,标签的id值要和 要映射的接口的类路径相同,这也是方便虚拟机进行映射。parameterTyep 的值是接口方法的参数类型,resultType 的值是查询语句查询出来的每一行的类型。resultMap类型就是自定义的类型,通常用于进行表联查,resultMap 的type值同样的是查询语句从数据库中查询出来的每一行的类型,也就是resultMap 的type类型值可以封装查询出来的每一行即可。

                  上述代码还有简化sql的代码,也就是将重复的sql语句进行的封装,然后在所需要的时候进行引入。

四.进行测试

               下面贴一下测试的代码:

package com.java.Text;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;

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 com.java.Mapper.DormitoryMapper;

public class Text2 {
     public static void main(String[] args) throws IOException {
    	 //指定Mybatis核心配置文件的路径
    	 String url="Mybatis.xml";
    	 //用流对象读取(加载)核心配置文件
    	 InputStream inputStream=Resources.getResourceAsStream(url);
    	 //创建一个SqlSessionFactory工厂用于指向这个文件(指向数据库)
    	 SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
    	 //获得sessoin用于操作数据库
    	 SqlSession sqlSession=sqlSessionFactory.openSession();
    	 //将session绑定操作数据库的方法,得到操作数据库的对象
    	 DormitoryMapper dormitoryMapper=sqlSession.getMapper(DormitoryMapper.class);
    	 //调用方法
    	 //Map集合是无序的,直接输出map,是可以得到结果的
    	 Map map=dormitoryMapper.select_one_dormitory("1");
    	 System.out.println(map);
    	 //遍历map
    	 for(Object key:map.keySet()) {
    		 System.out.print(map.get(key)+"-----");
    	 }
    	 
    	 //按照非主键来进行查询
    	 List<Map> list=dormitoryMapper.select_dormitory_byPlay(1);
    	 //进行遍历
    	 System.out.println(list);
    	 for(Map map2:list) {
    		 System.out.println(map2);
    	 }
    	 
    	 /*验证由于返回值类型不一致,而导致的返回值为空的情况
    	  *
    	  *接口中的返回值类型要和mapper.xml文件中的返回值类型一样,要不查询到的返回值将不能接收到。
    	  *
    	 */
    	 List<Map> map_error=dormitoryMapper.select_dormitory_byPlay2(1);
    	 System.out.println(map_error);
     }
}

                 其实,mapper方法的返回值类型是什么就返回什么类型,只要接口中的方法返回值可以接收mapper返回的值就可以。但是一旦接口中的方法返回值类型接收不了mapper方法的返回值(可能由于类型不一样),那么就会抛出异常。

五.三表联查

             在进行几个表同时联合查询的时候,那么这几个表必然会通过主键和外键联系在一起。这时候就需要把这几个表中相同的字段删除掉(其实不删的话我猜也可以,明天我验证一下,然后在明天的博客我会 说一下demo的结果)。删除掉相应外键,并定义一个外键联系的表的对应的实体类类型字段(属性),用于封装查询到的对象。在一对多的里面,会定义一个集合用来承载查询到的多的一方,在多对一的类里面,会定义一个多的一方的类的对象属性,用来承载一的一方。

           下面是多表联查的mapper映射文件代码。

<?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.zf.dao.UserMapper">

	<!-- 自定义resultMap -->
	<resultMap type="User" id="my_map_1">
		<result column="userid" property="userId"/>
		<result column="userpwd" property="userPwd"/>
		<result column="username" property="userName"/>
		<result column="usersex" property="userSex"/>
		<result column="userrole" property="userRole"/>
		<result column="usercollege" property="userCollege"/>
		<result column="usermajor" property="userMajor"/>
		<result column="userclass" property="userClass"/>
		
		<!-- 站在多方配置一方信息使用association -->
		<association property="dormitory" javaType="com.zf.bean.Dormitory">
			<result column="dormitoryid" property="dormitoryId"/>
			<result column="planpersons" property="planPersons"/>
			<result column="realpersons" property="realPersons"/>
			<result column="waterprice" property="waterPrice"/>
			<result column="powerprice" property="powerPrice"/>
			<result column="grade" property="grade"/>
		</association>
		<!-- 站在一方角度配置多方信息 -->
		<collection property="lates" ofType="com.zf.bean.Late">
			<result column="lateid" property="lateId"/>
			<result column="latetime" property="lateTime"/>

		</collection>
	</resultMap>

	
	<!-- 查询语句 -->
	<select id="sel_user_dor_late" parameterType="User" resultMap="my_map_1" > 
		
		select * from t_user u join t_dormitory d
				on u.dormitoryid = d.dormitoryid
				join t_late l
				on u.userid = l.userid
			where u.userid = #{userId}
		
	</select>
	
	
	
</mapper>

 六.Mabatis中#{}和${}的区别

                     动态 sql 是 mybatis 的主要特性之一,在 mapper 中定义的参数传到 xml 中之后,在查询之前 mybatis 会对其进行动态解析(也就是将传进来的参数和事先定义好的sql语句组成一个可以在数据库中执行的sql文)。mybatis 为我们提供了两种支持动态 sql 的语法:#{} 以及 ${}。

                      在下面的语句中,如果 username 的值为 zhangsan,则两种方式无任何区别:

                   但是 #{} 和 ${} 在预编译中的处理是不一样的。#{} 在预处理时,会把参数部分用一个占位符 ? 代替,变成如下的 sql 语句:

               而 ${} 则只是简单的字符串替换,在动态解析阶段,该 sql 语句会被解析成:

               以上,#{} 的参数替换是发生在 DBMS 中,而 ${} 则发生在动态解析过程中。

         那么,在使用过程中我们应该使用哪种方式呢?

         答案是,优先使用 #{}。因为 ${} 会导致 sql 注入的问题。看下面的例子:

            在这个例子中,如果表名为

         user; delete user; -- 

         则动态解析之后 sql 如下:

           --之后的语句被注释掉,而原本查询用户的语句变成了查询所有用户信息+删除用户表的语句,会对数据库造成重大损伤,极大可能导致服务器宕机。

         但是表名用参数传递进来的时候,只能使用 ${} ,具体原因可以自己做个猜测,去验证。这也提醒我们在这种用法中要小心sql注入的问题。

猜你喜欢

转载自blog.csdn.net/qq_41160264/article/details/82117691