您的位置:首页 > 其它

Mybatis的关系映射和相应的配置文件

2017-11-18 09:47 176 查看
一 关系映射

MyBatis 有两种不同的关联方式:l

嵌套查询:通过执行另外一个 SQL 映射语句来返回预期的复杂类型。

嵌套结果:使用嵌套结果映射来处理重复的联合结果的子集。

使用的标签:association、collection

1 一对一

人和身份证之间的一对一关系

1)表结构

CREATE TABLE `person` (

  `pid` int(11) NOT NULL,

  `pname` varchar(20) DEFAULT NULL,

  `cid` int(11) DEFAULT NULL,

  PRIMARY KEY (`pid`),

  KEY `cid` (`cid`),

  CONSTRAINT `person_ibfk_1` FOREIGN KEY (`cid`) REFERENCES `card` (`cid`)

)

CREATE TABLE `card` (

  `cid` int(11) NOT NULL,

  `cnum` varchar(20) DEFAULT NULL,

  PRIMARY KEY (`cid`)

)

2)嵌套结果:

执行多表查询的sql语句

PersonMapper.xml

<resultMap type="Person" id="personMap">
<!-- 主键 -->
<id property="id" column="id"/>
<!-- 其他字段 -->
<result property="name" column="name"/>

<!-- 嵌套结果的设置方式 -->
<!-- 表示关联一个对象  resultMap表示关联的对象数据的resultMap值 -->
<association property="card" resultMap="com.rr.one2one.Card.cardMap"></association>

</resultMap>

<!-- 多表查询    必须使用resultMap -->
<select id="findById" parameterType="java.lang.Integer" resultMap="personMap">
select person.*,card.* 
from person 
inner join card 
on person.id=card.id 
where person.id=#{id}
</select>

CardMapper.xml

<resultMap type="Card" id="cardMap">
<!-- 主键 -->
<id property="id" column="id"/>
<!-- 其他字段 -->
<result property="num" column="num"/>

</resultMap>

3)嵌套查询:

会执行多条sql语句

PersonMapper.xml

<resultMap type="Person" id="personMap1">
<!-- 主键 -->
<id property="id" column="id"/>
<!-- 其他字段 -->
<result property="name" column="name"/>

<!-- 嵌套查询的设置方式 -->
<!-- 表示关联一个对象  
select 通过其他sql语句查询关联的数据,格式 namespace的值.sql的id
column 指定关联的查询中 关联的列 本例中column的值来自person表的字段
fetchType 设置懒加载 lazy 懒加载, eager非懒加载
-->
<association property="card" javaType="Card" column="cid" select="com.rr.one2one.Card.findByCId" fetchType="lazy"></association>

</resultMap>
<select id="findByPId" parameterType="java.lang.Integer" resultMap="personMap1">
select * 
from person  
where person.id=#{id}
</select>

CardMapper.xml

<resultMap type="Card" id="cardMap">
<!-- 主键 -->
<id property="id" column="id"/>
<!-- 其他字段 -->
<result property="num" column="num"/>

</resultMap>

<!-- person 嵌套查询时,select对应的sql,必须使用resultMap -->
<select id="findByCId" parameterType="int" resultMap="cardMap">
select * from card where card.id=#{id};
</select>

2 一对多/多对一

部门和员工之间关系

1)表结构

CREATE TABLE `t_dept` (

  `deptId` int(11) NOT NULL AUTO_INCREMENT,

  `deptName` varchar(20) DEFAULT NULL,

  PRIMARY KEY (`deptId`)

)

CREATE TABLE `t_employee` (

  `empId` int(11) NOT NULL AUTO_INCREMENT,

  `empName` varchar(20) DEFAULT NULL,

  `salary` double DEFAULT NULL,

  `dept_id` int(11) DEFAULT NULL,

  PRIMARY KEY (`empId`),

  KEY `FK_jgo5u3npdj1lborc1v50bsens` (`dept_id`),

  CONSTRAINT `FK_jgo5u3npdj1lborc1v50bsens` FOREIGN KEY (`dept_id`) REFERENCES `t_dept` (`deptId`)

)

2)嵌套结果:

DepartmentMapper.xml

<resultMap type="Department" id="deptMap">
<!-- 主键 -->
<id property="id" column="did"/>
<!-- 其他字段 -->
<result property="name" column="dname"/>

<!-- 嵌套结果的设置方式 
collention 表示集合关系
ofType  指定集合中对象的类型
javaType 指定存储数据的的集合的类型
-->
<collection property="emps" javaType="java.util.ArrayList" ofType="Employee" resultMap="com.rr.one2many.Employee.empMap"></collection>

</resultMap>

<!-- 多表查询    必须使用resultMap -->
<select id="findById" parameterType="int" resultMap="deptMap">
select d.id as did, d.name as dname,e.* 
from department d 
inner join employee e
on d.id=e.dept_id
where d.id=#{id};
</select>

其他操作:

<!-- 插入数据 -->
<insert id="add" parameterType="Department">

<!-- keyproperty的值 是实体类中的属性
order 有两个值,
BEFORE表示插入前获取值
AFTER表示插入后获取值,对于mysql,插入后获取值 -->
<selectKey keyProperty="id" resultType="int" order="AFTER">
<!-- LAST_INSERT_ID() 获取最后插入的值 ,将获取的值赋值给keyProperty指定的属性 -->
select LAST_INSERT_ID()
</selectKey>

insert into department(name) values(#{name});
</insert>

<!-- 如果是mysql,可以使用useGeneratedKeys="true"属性 -->
<insert id="addByGK" parameterType="Department" useGeneratedKeys="true" keyProperty="id">

insert into department(name) values(#{name});
</insert>

<!-- 得到表中的记录数,resultType 使用基本类型 -->
<select id="getCount" resultType="int">
select count(1) from department;
</select>

EmployeeMapper.xml

<resultMap type="Employee" id="empMap">
<!-- 主键 -->
<id property="id" column="id"/>
<!-- 其他字段 -->
<result property="name" column="name"/>
<result property="age" column="age"/>
<result property="birth" column="birth"/>
<!-- 嵌套结果 -->
<association property="dept" resultMap="com.rr.one2many.Department.deptMap"></association>

</resultMap>

3)嵌套查询:

DepartmentMapper.xml

<resultMap type="Department" id="deptMap1">
<!-- 主键 -->
<id property="id" column="id"/>
<!-- 其他字段 -->
<result property="name" column="name"/>

<!-- 嵌套查询的设置方式 
collention 表示集合关系
ofType  指定集合中对象的类型
javaType 指定存储数据的的集合的类型
-->
<collection property="emps" javaType="java.util.ArrayList" ofType="Employee" column="id" select="com.rr.one2many.Employee.findByDeptId"></collection>

</resultMap>

<select id="findByDId" parameterType="int" resultMap="deptMap1">
select * 
from department d
where d.id=#{id};
</select>

EmployeeMapper.xml

<resultMap type="Employee" id="empMap1">
<!-- 主键 -->
<id property="id" column="id"/>
<!-- 其他字段 -->
<result property="name" column="name"/>
<result property="age" column="age"/>
<result property="birth" column="birth"/>
<!-- 嵌套查询 -->
<association property="dept" column="dept_id" select="com.rr.one2many.Department.findByDId" fetchType="eager"></association>

</resultMap>

<select id="findByDeptId" parameterType="int" resultMap="empMap">
select * from employee where dept_id=#{id};
</select>

<select id="findAll" resultMap="empMap1">
select * from employee;
</select>

3 多对多

学生和课程之间的关系

1)表结构

CREATE TABLE `t_student` (

  `sid` int(11) NOT NULL AUTO_INCREMENT,

  `sname` varchar(20) DEFAULT NULL,

  PRIMARY KEY (`sid`)

)

CREATE TABLE `t_course` (

  `cid` int(11) NOT NULL AUTO_INCREMENT,

  `cname` varchar(20) DEFAULT NULL,

  PRIMARY KEY (`cid`)

)

CREATE TABLE `t_relation` (

  `sid` int(11) NOT NULL,

  `cid` int(11) NOT NULL,

  PRIMARY KEY (`sid`,`cid`),

  KEY `FK_ma6ynxw6eng27dnn2h242ec6g` (`sid`),

  CONSTRAINT `FK_fje0x78jps0jamjagtdc80r8d` FOREIGN KEY (`sid`) REFERENCES `t_student` (`sid`),

  CONSTRAINT `FK_ma6ynxw6eng27dnn2h242ec6g` FOREIGN KEY (`cid`) REFERENCES `t_course` (`cid`)

)

2)嵌套结果

StudentMapper.xml

<resultMap type="Student" id="stuMap">
<!-- 主键 -->
<id property="id" column="stuid"/>
<!-- 其他字段 -->
<result property="name" column="stuname"/>

<!-- 嵌套结果的设置方式 
collention 表示集合关系
ofType  指定集合中对象的类型
javaType 指定存储数据的的集合的类型
-->
<collection property="courses" javaType="java.util.ArrayList" ofType="Course" resultMap="com.rr.many2many.Course.courseMap"></collection>

</resultMap>

<select id="findById" parameterType="int" resultMap="stuMap">
select s.id as stuid, s.name as stuname,c.id,c.name
from student s
inner join stu_course sc
on s.id=sc.sid
inner join course c
on c.id=sc.cid
where s.id=#{id};
</select>

CourseMapper.xml

<resultMap type="Course" id="courseMap">
<!-- 主键 -->
<id property="id" column="id"/>
<!-- 其他字段 -->
<result property="name" column="name"/>

<!-- 嵌套结果的设置方式 
collention 表示集合关系
ofType  指定集合中对象的类型
javaType 指定存储数据的的集合的类型
-->
<collection property="students" javaType="java.util.ArrayList" ofType="Student" resultMap="com.rr.many2many.Student.stuMap"></collection>

</resultMap>

<!-- 使用嵌套查询,传过来的是学生id -->
<select id="findByStuId" parameterType="int" resultMap="courseMap">
select c.*
from course c
inner join stu_course sc
on c.id=sc.cid
where sc.sid=#{id};
</select>

3)嵌套查询

StudentMapper.xml

<resultMap type="Student" id="stuMap1">
<!-- 主键 -->
<id property="id" column="id"/>
<!-- 其他字段 -->
<result property="name" column="name"/>

<!-- 嵌套查询的设置方式 -->
<collection property="courses" javaType="java.util.ArrayList" ofType="Course" column="id" select="com.rr.many2many.Course.findByStuId"></collection>

</resultMap>

<select id="findBySId" parameterType="int" resultMap="stuMap1">
select *
from student s
where s.id=#{id};
</select>

二 懒加载

映射文件中:fetchType="lazy"

主配置文件中:

<!-- 参数设置 -->
<settings>
    <!-- 启用懒加载,必须按照下面方式配置 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 将积极加载改为消极加载即按需加载。必须写,且为false才会懒加载 -->  
<setting name="aggressiveLazyLoading" value="false"/>
</settings>

三 缓存

1 一级缓存

session级别的缓存

一级缓存是SqlSession级别的缓存。在操作数据库时需要构造 sqlSession对象,在对象中有一个(内存区域)数据结构(HashMap)用于存储缓存数据。不同的sqlSession之间的缓存数据区域(HashMap)是互相不影响的。

一级缓存的作用域是同一个SqlSession,在同一个sqlSession中两次执行相同的sql语句,第一次执行完毕会将数据库中查询的数据写到缓存(内存),第二次会从缓存中获取数据将不再从数据库查询,从而提高查询效率。当一个sqlSession结束后该sqlSession中的一级缓存也就不存在了。Mybatis默认开启一级缓存。
如果没有启动事务,mybatis的一级缓存在spring中是没有作用的.

2 二级缓存

mapper级别的缓存

二级缓存是mapper级别的缓存,多个SqlSession去操作同一个Mapper的sql语句,多个SqlSession去操作数据库得到数据会存在二级缓存区域,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的。

二级缓存是多个SqlSession共享的,其作用域是mapper的同一个namespace,不同的sqlSession两次执行相同namespace下的sql语句且向sql中传递参数也相同即最终执行相同的sql语句,第一次执行完毕会将数据库中查询的数据写到缓存(内存),第二次会从缓存中获取数据将不再从数据库查询,从而提高查询效率。Mybatis默认没有开启二级缓存需要在setting全局参数中配置开启二级缓存。

主配置文件:

<!-- 开启二级缓存 -->
<setting name="cacheEnabled" value="true"/>

映射配置文件

<!-- 相关的映射启用二级缓存 -->
<!-- <cache /> -->

<!-- eviction 缓存策略
flushInterval 刷新间隔,单位毫秒
size 引用数目
readOnly 是否只读
-->
<cache 
eviction="FIFO"
flushInterval="10000"
size="1000"
readOnly="true"
></cache>

flushInterval:

刷新间隔,可以被设置为任意的正整数,单位毫秒。默认情况是不设置,也就是没有刷新间隔。

Size:

引用数目,可以被设置为任意正整数,缓存的对象数目和你运行环境的可用内存资源数目。默认值是1024。

readOnly:

是否只读,属性可以被设置为true或false。只读的缓存会给所有调用者返回缓存对象的相同实例,默认是false。

Eviction:

收回策略,

 LRU – 最近最少使用的:移除最长时间不被使用的对象。

FIFO – 先进先出:按对象进入缓存的顺序来移除它们。

SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。

WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。

四 SSM框架整合

1导入jar文件

导入spring、springmvc、mybatis、数据库驱动、数据库连接池的相关jar文件;

还需要导入mybatis-spring-1.2.1.jar

2 修改web.xml

引入spring、springmvc的核心配置

<!-- post提交方式中文乱码的处理 -->

  <filter>

  <filter-name>characterEncoding</filter-name>

  <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>

  <init-param>

  <param-name>encoding</param-name>

  <param-value>utf8</param-value>

  </init-param>

  </filter>

  <filter-mapping>

  <filter-name>characterEncoding</filter-name>

  <url-pattern>/*</url-pattern>

  </filter-mapping>

  

  

    <!-- spring mvc 的核心配置 -->

  <servlet>

  <servlet-name>DispatchServlet</servlet-name>

  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

  <!-- 指定加载哪个配置文件 -->

  <init-param>

  <param-name>contextConfigLocation</param-name>

  <param-value>classpath:spring-mvc.xml</param-value>

  </init-param>

  <!-- tomcat服务器启动时,创建servlet对象 -->

  <load-on-startup>1</load-on-startup>

  </servlet>

  <servlet-mapping>

  <servlet-name>DispatchServlet</servlet-name>

  <!-- 过滤任何资源,会造成静态资源不能访问 -->

  <url-pattern>/</url-pattern>

  </servlet-mapping>

  

  <!-- spring的核心配置 -->
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <!-- classpath相当于/WEB-INF/classes -->
    <param-value>classpath:applicationContext.xml</param-value>
<!--     <param-value>/WEB-INF/classes/bean.xml</param-value> -->
  </context-param>

  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>

3 spring mvc配置

<!-- 扫描注解 -->

  <context:component-scan base-package="com.rr.controller">

  <!-- 指定扫描哪些注解 -->

  <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>

  </context:component-scan>

   

  <mvc:annotation-driven>
  <!-- 处理json里的日期数据,默认日期被fastjson转为时间戳数据 -->
  <mvc:message-converters>  
            <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">  
                <property name="objectMapper">  
                    <bean class="com.fasterxml.jackson.databind.ObjectMapper">  
                        <property name="dateFormat">  
                            <bean class="java.text.SimpleDateFormat">  
                                <constructor-arg type="java.lang.String" value="yyyy-MM-dd HH:mm:ss" />  
                            </bean>  
                        </property>  
                    </bean>  
                </property>  
            </bean>  
        </mvc:message-converters>

  </mvc:annotation-driven>

   

  

  <mvc:resources location="/js/" mapping="/js/**"></mvc:resources>

   
<!-- 视图解析器 -->

   <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">

    <!-- 前缀 -->

    <property name="prefix" value="/"></property>

    <!-- 后缀 -->

    <property name="suffix" value=".jsp"></property>

   

   </bean>

4 spring配置

<!-- 扫描注解 -->

  <context:component-scan base-package="com.rr">

  <!-- 扫描时,排除指定的注解 -->

  <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>

  </context:component-scan>

   

   

   <!-- 数据源的配置 -->

  <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">

  <property name="driverClass" value="com.mysql.jdbc.Driver"></property>

  <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/hib"></property>

  <property name="user" value="root"></property>

  <property name="password" value="root"></property>

  <property name="initialPoolSize" value="5"></property>

  <property name="maxPoolSize" value="10"></property>

  <property name="maxIdleTime" value="1000"></property>

  </bean>

   

   <!-- 创建mybatis的会话工厂对象 -->

   <bean id="sessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 设置数据源 -->
<property name="dataSource" ref="dataSource"></property>
<!-- 加载mybatis主配置文件 -->
<property name="configLocation" value="classpath:mybatis.xml"/>
<!-- 加载映射文件 -->
<property name="mapperLocations" value="classpath:com/rr/mapper/*.xml"/>

   </bean>

   

   <!-- 扫描映射代理的接口类,注入到spring容器中 -->

   <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">

    <property name="sqlSessionFactoryBeanName" value="sessionFactory"></property>

    <property name="basePackage" value="com.rr.dao"></property>

   </bean>

   

    <!-- 1配置事务管理类 -->

    <bean id="txManage" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

   

    <property name="dataSource" ref="dataSource"></property>

    </bean>

   

    <!-- 2配置事务的特性 -->

   <tx:advice id="txAdvice" transaction-manager="txManage">

    <tx:attributes>

   

    <tx:method name="*" read-only="false"/>

   

    </tx:attributes>

   </tx:advice>

   

   <!-- 3AOP配置 -->

   <aop:config>

    <!-- 切入点 -->

    <aop:pointcut expression="execution(* com.rr.service.impl.*.*(..))" id="pc"/>

   

    <!-- 通知 -->

    <aop:advisor advice-ref="txAdvice" pointcut-ref="pc"/>

   

   </aop:config>

5 mybatis配置

<configuration>

<!-- 参数设置 -->
<settings>
    <!-- 启用懒加载,必须按照下面方式配置 -->
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>

<!-- 开启二级缓存 -->
<setting name="cacheEnabled" value="true"/>
</settings>

<typeAliases>

<typeAlias type="com.rr.entity.Department" alias="Department"/>
<typeAlias type="com.rr.entity.Employee" alias="Employee"/>

</typeAliases>

<mappers>

</mappers>

</configuration>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息