zoukankan      html  css  js  c++  java
  • MyBatis-3.2.2

    note

    • SqlSessionFactory 它是一个线程安全的
    • SqlSession 线程非安全,不能做类的公用变量
    • 当数据库字段和实体对象名称不一至时,通过sql的字段命名别名,别名跟实体对象属性一致

    jar包(mybatis3.2.2)

    • mybatis-3.2.2.jar 核心驱动
    • asm-3.3.1.jar
    • cglib-2.2.2.jar
    • commons-logging-1.1.1.jar
    • javassist-3.17.1-GA.jar
    • log4j-1.2.17.jar
    • slf4j-api-1.7.5.jar
    • slf4j-log4j12-1.7.5.jar
    • mysql-connector-java-5.1.26.jar 数据库驱动

    sqlMapConfig.xml

    • 配置内容:
      1) 配置事务
      2) 配置数据源
      3) 声明mapper文件
    <?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="test">
    		<environment id="test">
    			<!-- 事务:JDBC/MANAGED-自己管理去 -->
    			<transactionManager type="JDBC"/>
    			<!-- 数据源:POOLED/UNPOOLED/JNDI -->
    			<dataSource type="POOLED">
    				<property name="driver" value="com.mysql.jdbc.Driver"/>
    				<property name="url" value="jdbc:mysql://localhost:3306/mybatisdb?charsetEncoding=utf8"/>
    				<property name="username" value="root"/>
    				<property name="password" value="root"/>
    			</dataSource>
    		</environment>
    		<environment id="deploy">
    			<!-- 事务:JDBC/MANAGED-自己管理去 -->
    			<transactionManager type="JDBC"/>
    			<!-- 数据源:POOLED/UNPOOLED/JNDI -->
    			<dataSource type="POOLED">
    				<property name="driver" value="com.mysql.jdbc.Driver"/>
    				<property name="url" value="jdbc:mysql://localhost:3306/mybatisdb?charsetEncoding=utf8"/>
    				<property name="username" value="root"/>
    				<property name="password" value="root"/>
    			</dataSource>
    		</environment>
    	</environments>
    	
    	<!-- 映射文件mapper -->
    </configuration>
    
    

    mapper.xml

    • 命名空间,在不同的mapper,但mapper中的方法同名,靠命名空间区分
    • resultMap不是必须,可以不写,前提:表和实体的属性一样。(mybatis底层自动生成resultMap)
    • 它通过数据结果集来映射的。Hibernate它是通过数据库表字段来映射的。
    • 关联关系:
      A.对一association javaType
      B.对多 collection ofType
      jdbcType
      它是指定当NAME为null时,给jdbc驱动程序告诉它,它针对的数据库字段的类型。(Oracle)
    	<update id="update" parameterType="cn.itcast.domain.Person">
    		update person
    		<set>
    			<if test="name!=null">user_name=#{name,jdbcType=VARCHAR},</if>
    			<if test="age!=null">age=#{age},</if>
    			<if test="remark!=null">remark=#{remark},</if>
    		</set>
    		where id = #{id}
    	</update>
    
    • Mapper中写SQL获取参数
    	+ #{} 它会自动根据参数类型做封装。例如对字符串类型,两边加单撇;对整数类型直接使用;好处防止SQL注入(推荐)
    
    	+ ${} 将用户填入的参数直接拼接到SQL。(字符串直接拼接)坏处:SQL注入;例如:拼接order by条件(特殊的地方)
    
    • SQL中含有特殊字符
    <if test="ageEnd!=null"><![CDATA[and age <=]]> #{ageEnd}</if>
    
    • 动态SQL
    	+ <if>	判断条件
    	+ <where> 自动删除最前面的and 或者or,实际开发中常用where 1=1
    	+ <set> 它自动删除最后一个set值的逗号,修改时,修改参数不同
    	+ <foreach> 主要应用在in子查询,批量删除时候,array,list,map
    
    • 常规的标签
    	+ <select>	查询,参数map;返回值List(selectList),可以是一个值(selectOne)
    	+ <insert> 新增,参数po;新增时习惯写所有的字段
    	+ <update> 修改,参数po;修改时习惯使用动态sql语句
    	+ <delete> 删除,参数 int,string,array,list,map
    
    • 参数:

      • parameterMap 废除,早期使用
      • parameterType 简单变量int/string/double/po/map
    • 返回值:

      • resultType 简单变量int/string/double/po/map
      • resultMap 它是mybatis核心;实际resultType使用时,底层自动转为resultMap;在数据库结果集和实体对象加了一层。例如:数据库字段USER_NAME,实体中name;通过它mybatis可以找到映射的规则;它可以配置关联关系;mybatis自动将大大的结果集分拆到各个对象中。(难点)
      • SQL返回的结果集中字段不能有重名的,如果有,必须设置别名,通过resultMap映射时进行转化。
    <?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.fuyi.mapper.PersonMapper">
    
    	<!-- 查询,注意Mybatis中如果有填写集合类型,只填写集合中元素的类型  -->
    	<sql id="cols">id,name,age</sql>
    
    	<resultMap type="com.fuyi.domain.User" id="userRM">
    		<id property="id" column="ID" />
    		<result property="name" column="NAME" />
    		<result property="age" column="AGE" />
    	</resultMap>
    
    	<resultMap type="com.fuyi.domain.User" id="userAndInfoRM"
    		extends="userRM">
    		<association property="userInfo" javaType="com.fuyi.domain.UserInfo">
    			<id property="id" column="info_id" />
    			<result property="jobDate" column="job_date" />
    			<result property="position" column="POSITION" />
    		</association>
    	</resultMap>
    
    	<resultMap type="com.fuyi.domain.User" id="userAndBookRM"
    		extends="userAndInfoRM">
    		<collection property="book" ofType="com.fuyi.domain.Book">
    			<id property="id" column="book_id" />
    			<result property="title" column="title" />
    			<result property="publish" column="publish" />
    		</collection>
    	</resultMap>
    
    	<select id="findUserAndBook" resultMap="userAndBookRM">
    		select p.id, p.name,
    		p.age, p.info_id, p.job_date,p.position, b.id as book_id, b.title,
    		b.publish
    		from (select u.id,u.name,u.age,i.id as info_id,i.job_date,i.position
    		from
    		user u left outer join user_info i on u.id = i.user_id ) p LEFT JOIN
    		book b on p.id = b.user_id;
    	</select>
    
    
    
    
    	<select id="findUserAndInfo1" resultMap="userAndInfoRM">
    		select
    		u.id,u.name,u.age,i.id as info_id,i.job_date,i.position
    		from user u
    		left outer join user_info i on u.id = i.user_id
    	</select>
    
    
    
    	<!-- 查询,注意Mybatis中如果有填写集合类型,只填写集合中元素的类型 -->
    	<select id="find" parameterType="map" resultType="User">
    		select
    		<include refid="cols" />
    		from user
    		<where>
    			<if test="name!=null">and name like #{name}</if>
    			<if test="age!=null">and age = #{age}</if>
    		</where>
    
    	</select>
    
    	<select id="get" parameterType="int" resultType="com.fuyi.domain.User">
    		select * from
    		user
    	</select>
    
    	<insert id="insert" parameterType="com.fuyi.domain.User">
    		insert into user(name, age)
    		values(#{name}, #{age})
    	</insert>
    
    	<update id="update" parameterType="com.fuyi.domain.User">
    		update user
    		<!-- name = #{name}, age = #{age} -->
    		<set>
    			<if test="name!=null"> name = #{name},</if>
    			<if test="age!=null"> age = #{age},</if>
    		</set>
    		where id = #{id}
    	</update>
    
    	<delete id="deleteById" parameterType="int">
    		delete from user
    		where id in
    		<foreach collection="array" item="ind" open="(" close=")"
    			separator=",">
    			#{ind}
    		</foreach>
    	</delete>
    
    	<delete id="deleteList" parameterType="int">
    		delete from user
    		where id in
    		<foreach collection="list" item="ind" open="(" close=")"
    			separator=",">
    			#{ind}
    		</foreach>
    	</delete>
    
    	<delete id="deleteMap" parameterType="map">
    		delete from user
    		where id in
    		<foreach collection="ids" item="id" open="(" close=")"
    			separator=",">
    			#{id}
    		</foreach>
    	</delete>
    
    	<select id="count" resultType="int">
    		select count(*) from user
    	</select>
    </mapper>
    
    

    测试

    public class TestMybatis {
    	@Test
    	public void init() throws IOException{
    		InputStream is = Resources.getResourceAsStream(classpath:mybatis/sqlMapConfig.xml);
    		SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
    		SqlSession session = factory.openSession();
    
    		//如何访问mapper中的方法呢?  规则:命名空间+.+id
    		List<Person> personList = session.selectList("com.fuyi.mapper.PersonMapper.find");
    		System.out.println(personList.size());
    		for(Person p : personList){
    			System.out.println(p);
    		}
    
    	}
    }
    

    mapper接口开发

    • 规则
      • 接口名称必须和mapper文件名称相同
      • 接口包路径和命名空间一致(接口文件和mapper文件在一起)
      • 接口中要声明的方法名和某个sql配置的id属性一致
      • 参数和返回值,要按java规则写
    • Test
    public class TestMapperInterface {
    	private SqlSessionFactory factory;
    	
    	@Before	//最先执行,初始化SessionFactory
    	public void init() throws IOException{
    		String resource = "sqlMapConfig.xml";
    		InputStream is = Resources.getResourceAsStream(resource);
    		factory = new SqlSessionFactoryBuilder().build(is);
    	}
    	
    	@Test
    	public void testFind(){
    		SqlSession session = factory.openSession();
    		//获取接口对象
    		PersonMapper mapper = session.getMapper(PersonMapper.class);
    		Map map = new HashMap();
    		map.put("name", "'t%'");
    		
    		List<Person> pList = mapper.find(map);
    		System.out.println(pList.size());
    	}
    }
    

    缓存

    - 一级缓存Hibernate,session级别
    - 二级缓存Hibernate,sessionFactory级别
    - Mybatis它和hibernate一样
    
    - 一级缓存默认开启
    
    	public void cacheLevel1(){
    		SqlSession session = factory.openSession();
    		PersonMapper mapper = session.getMapper(PersonMapper.class);
    		Map map = new HashMap();
    		map.put("name", "'tony'");
    		
    		List<Person> personList = mapper.find(map);
    		System.out.println(personList.size());
    		
    		PersonMapper mapper2 = session.getMapper(PersonMapper.class);
    		
    		List<Person> personList2 = mapper2.find(map);
    		System.out.println(personList2.size());
    		//结果只发出一条sql查询
    	}
    
    • 二级缓存默认不开启
    开启方式:在mapper.xml中添加  
    <cache
    	eviction="FIFO"
    	flushInterval="60000"
    	size="512" 
        readOnly="true"/>
    在实际开发中,经过在线上压力测试,找到一个符合当前客户运行环境下最恰当的值。
    
    	public void cacheLevel2(){
    		SqlSession session = factory.openSession();
    		PersonMapper mapper = session.getMapper(PersonMapper.class);
    		Map map = new HashMap();
    		map.put("name", "'tony'");
    		
    		List<Person> personList = mapper.find(map);
    		System.out.println(personList.size());
    		
    		session.close();	//关闭session
    		session = factory.openSession();
    		
    		PersonMapper mapper2 = session.getMapper(PersonMapper.class);
    		
    		List<Person> personList2 = mapper2.find(map);
    		System.out.println(personList2.size());
    		// 关闭session后,结果只发出一条sql查询
    	}
    
    

    默认mybatis二级缓存一般使用第三方Ehcache

    - Ehcache 单机
    - Momeycache 集群
    
    - 导入Ehcache的jar包
    - ehcache-core-2.6.5.jar
    - mybatis-ehcache-1.0.2.jar
    
    <cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
    
    - copy ehcache-failsafe.xml rename ehcache.xml
    

    拦截器interceptor

    - Mybatis 分页
    
    1)	自定义一个拦截器类,实现interceptor接口
    2)	插件,在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>
    	<!-- 分页拦截器,拦截用户提交的查询,只查询当前页数据;提高响应速度。 -->
    	<plugins>  
    		<plugin interceptor="cn.itcast.jk.pagination.PageInterceptor">  
    			<property name="databaseType" value="oracle"/>  
    		</plugin>  
    	</plugins>  
    </configuration>	
    
    • Springmvc 拦截器
    性能监控
    开发步骤:
    1、编写拦截器,记录Controller方法执行时间
    
    public class TimerInterceptor implements HandlerInterceptor {
    	private NamedThreadLocal<Long> startTimeThreadLocal = new NamedThreadLocal<Long>("WatchExecuteTime");
    	
    	public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
    		long beginTime = System.currentTimeMillis();			//开始时间
    		startTimeThreadLocal.set(beginTime);
    		return true;
    	}
    	
    	public void afterCompletion(HttpServletRequest req, HttpServletResponse res, Object arg2, Exception arg3) throws Exception {
    		long endTime = System.currentTimeMillis();
    		long executeTime = endTime - startTimeThreadLocal.get();
    		System.out.println(String.format("%s execute %d ms." , req.getRequestURI() , executeTime));
    	}
    	
    	public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,
    			Object arg2, ModelAndView arg3) throws Exception {
    	}
    }
    
    2、在springmvc-servlet.xml文件中配置拦截器
    
    
    对多个controller进行指定方法的拦截
    	<mvc:interceptors>
    		<mvc:interceptor>
    			<mvc:mapping path="/cargo/export/list.action"/>
    			<bean class="cn.itcast.jk.interceptor.TimerInterceptor"/>
    		</mvc:interceptor>
    		<mvc:interceptor>
    			<mvc:mapping path="/cargo/packinglist/list.action"/>
    			<bean class="cn.itcast.jk.interceptor.TimerInterceptor"/>
    		</mvc:interceptor>
    	</mvc:interceptors>
    
    
    对多个controller的所有方法拦截
    	<mvc:interceptors>
    		<mvc:interceptor>
    			<mvc:mapping path="/cargo/export/*"/>
    			<bean class="cn.itcast.jk.interceptor.TimerInterceptor"/>
    		</mvc:interceptor>
    		<mvc:interceptor>
    			<mvc:mapping path="/cargo/packinglist/*"/>
    			<bean class="cn.itcast.jk.interceptor.TimerInterceptor"/>
    		</mvc:interceptor>
    	</mvc:interceptors>
    
    
    对某目录下的controller进行拦截
    
    	<mvc:interceptors>
    		<mvc:interceptor>
    			<mvc:mapping path="/cargo/**"/>
    			<bean class="cn.itcast.jk.interceptor.TimerInterceptor"/>
    		</mvc:interceptor>
    	</mvc:interceptors>
    
     拦截整个项目的所有controller
    
    	<mvc:interceptors>
    		<mvc:interceptor>
    			<mvc:mapping path="/**"/>
    			<bean class="cn.itcast.jk.interceptor.TimerInterceptor"/>
    		</mvc:interceptor>
    	</mvc:interceptors>
    

    spring + mybatis

    • 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>
    
    </configuration>
    
    
    • beans.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xmlns:context="http://www.springframework.org/schema/context"
    	xmlns:aop="http://www.springframework.org/schema/aop"
    	xmlns:tx="http://www.springframework.org/schema/tx"
    	xsi:schemaLocation="http://www.springframework.org/schema/beans 
    				         http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    				         http://www.springframework.org/schema/context
    				         http://www.springframework.org/schema/context/spring-context-3.0.xsd
    				         http://www.springframework.org/schema/tx
    				         http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
    				         http://www.springframework.org/schema/aop 
    				         http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
    	
    	<!-- 1.包扫描,service dao -->
    	<context:component-scan base-package="cn.itcast.ssm.dao,cn.itcast.ssm.service"/>
    	
    	<!-- 2.jdbc.properties属性配置文件 -->
    	<context:property-placeholder location="classpath:jdbc.properties"/>
    	
    	<!-- 3.数据源 DataSource -->
    	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    		<property name="driverClassName" value="${jdbc.driverclass}"/>
    		<property name="url" value="${jdbc.url}"/>
    		<property name="username" value="${jdbc.username}"/>
    		<property name="password" value="${jdbc.password}"/>
    	</bean>
    	
    	<!-- 4.SqlSessionFactory -->
    	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    		<property name="dataSource" ref="dataSource"/>
    		<!-- spring和mybatis整合 -->
    		<!-- 1)引入mybatis核心配置文件 -->
    		<property name="configLocation" value="classpath:sqlMapCongfig.xml"/>
    		
    		<!-- 2)扫描指定目录下的所有Mapper.xml -->
    		<property name="mapperLocations" value="classpath:cn/itcast/ssm/mapper/*.xml"/>
    	</bean>
    	
    	<!-- 5.事务 -->
    	<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    		<property name="dataSource" ref="dataSource"/>
    	</bean>
    	<tx:advice id="txAdvice" transaction-manager="txManager">
    		<tx:attributes>
    			<tx:method name="save*" propagation="REQUIRED"/>
    			<tx:method name="insert*" propagation="REQUIRED"/>
    			<tx:method name="update*" propagation="REQUIRED"/>
    			<tx:method name="delete*" propagation="REQUIRED"/>
    			
    			<tx:method name="find*" read-only="true"/>
    			<tx:method name="get*" read-only="true"/>
    			<tx:method name="view*" read-only="true"/>
    			
    			<tx:method name="*" read-only="true"/>
    		</tx:attributes>
    	</tx:advice>
    	<aop:config>
    		<aop:pointcut expression="execution(* cn.itcast.ssm.service.*.*(..))" id="pointCut"/>
    		<aop:advisor advice-ref="txAdvice" pointcut-ref="pointCut"/>
    	</aop:config>
    			         
    </beans>
    
    
    • springmvc-servlet.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xmlns:mvc="http://www.springframework.org/schema/mvc"
    	xmlns:context="http://www.springframework.org/schema/context"
    	xmlns:aop="http://www.springframework.org/schema/aop"
    	xmlns:tx="http://www.springframework.org/schema/tx"
    	xsi:schemaLocation="http://www.springframework.org/schema/beans 
    	http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
    	http://www.springframework.org/schema/mvc 
    	http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd 
    	http://www.springframework.org/schema/context 
    	http://www.springframework.org/schema/context/spring-context-3.0.xsd 
    	http://www.springframework.org/schema/aop 
    	http://www.springframework.org/schema/aop/spring-aop-3.0.xsd 
    	http://www.springframework.org/schema/tx 
    	http://www.springframework.org/schema/tx/spring-tx-3.0.xsd ">
    	
    	<!-- 1.包扫描controller -->
    	<context:component-scan base-package="cn.itcast.ssm.web.controller"/>
    	
    	<!-- 2.内部资源视图解析器  -->
    	<bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    		<property name="prefix" value="/WEB-INF/pages"/>
    		<property name="suffix" value=""/>
    	</bean>
    	
    </beans>
    
    • web.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    	id="taotao" version="2.5">
    	<display-name>yycg</display-name>
    	<welcome-file-list>
    		<welcome-file>index.html</welcome-file>
    	</welcome-file-list>
    	<!-- 加载spring容器  -->
    	<context-param>
    		<param-name>contextConfigLocation</param-name>
    		<param-value>classpath:spring/applicationContext*.xml</param-value>
    	</context-param>
    	<listener>
    		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    	</listener>
    
    
    	<!-- 解决post乱码 -->
    	<filter>
    		<filter-name>CharacterEncodingFilter</filter-name>
    		<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    		<init-param>
    			<param-name>encoding</param-name>
    			<param-value>utf-8</param-value>
    		</init-param>
    		<init-param>
    			<param-name>forceEncoding</param-name>
    			<param-value>true</param-value>
    		</init-param> 
    	</filter>
    	<filter-mapping>
    		<filter-name>CharacterEncodingFilter</filter-name>
    		<url-pattern>/*</url-pattern>
    	</filter-mapping>
    
    
    	<!-- springmvc的前端控制器  -->
    	<servlet>
    		<servlet-name>yycg</servlet-name>
    		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    		
    		<!-- contextConfigLocation不是必须的, 如果不配置contextConfigLocation, springmvc的配置文件默认在:WEB-INF/servlet的name+"-servlet.xml"  -->
    		<init-param>
    			<param-name>contextConfigLocation</param-name>
    			<param-value>classpath:spring/springmvc.xml</param-value>
    		</init-param>
    		<load-on-startup>1</load-on-startup>
    	</servlet>
    	<servlet-mapping>
    		<servlet-name>yycg</servlet-name>
    		<!-- 做伪静态,做搜索引擎优化(SEO)
    		<url-pattern>*.html</url-pattern>
    		-->
    		<url-pattern>*.action</url-pattern>
    	</servlet-mapping>
    	 
    </web-app>
    
    
  • 相关阅读:
    字体识别
    TMSHttpConfig工具使用
    firedac分页查询
    filefunc.pas
    dbfunc.pas
    TRawByteStringStream
    大小端交换
    variant的序列和还原
    ansistring和unicode的序列和还原
    malinajs来自Svelte 启发的前端编译器
  • 原文地址:https://www.cnblogs.com/fuyiming/p/6907648.html
Copyright © 2011-2022 走看看