56..java基础——零基础入门之Mybatis进阶

一对一

如何配置一对一关联映射
注意,Mybatis设计中有一处缺陷,就是如果配置了关联关系,则resultMap中,要配置全所有的映射关联,否则不会封装数据,为null值
javabean代码:

public class User {
 
private String id;
private String name;
private int age;
private String address;
private UserInfo userInfo;

……get set方法
Xml代码:


<resultMap type="pojo.User" id="userRM">
 
<id property="id" column="id"/>
<result property="name" column="name"/>
<result property="age" column="age"/>
<result property="address" column="address"/>

<association property="userInfo" javaType="pojo.UserInfo">

<id property="id" column="id"/>

<result property="name" column="name"/>
<result property="job" column="job"/>
<result property="hobbit" column="hobbit"/>
association>
 
resultMap>
 

<select id="findOneToOne" resultMap="userRM">
select * from user_c LEFT JOIN user_info on user_c.id=user_info.id
select>

注意:Mybatis同名字段的bug
引发原因:Mybatis是根据反射机制来把结果集数据封装到javabean里的,当做关联的时候,比如先查的是user_c的表,有一个name列名,找到并封装到User的name属性里,然后再查User_info,发现有也有一个name列名,Mybatis就分不清了,就直接把User的name数据封装到User_info的name数据里了。这就是Mybatis的同名字段问题。
怎么避免Mybatis的同名字段问题?
核心思想:让User和User_info的结果集里的列名不一致。
Xml代码:


<resultMap type="pojo.User" id="userRM">
 
<id property="id" column="userid"/>
<result property="name" column="username"/>
<result property="age" column="age"/>
<result property="address" column="address"/>

<association property="userInfo" javaType="pojo.UserInfo">

<id property="id" column="userinfoid"/>

<result property="name" column="userinfoname"/>
<result property="job" column="job"/>
<result property="hobbit" column="hobbit"/>
association>
 
resultMap>
 

<select id="findOneToOne" resultMap="userRM">
select u.id as userid,u.name as username,u.age,u.address,
i.id as userinfoid,i.name as userinfoname,i.job,i.hobbit from
(select * from user_c)u LEFT JOIN
(select * from user_info) i on u.id=i.id
select>

一对多


如何配置一对多关联映射?
javabean代码:

public class Dept {
 
private String deptId;
private String deptName;
private List<User> users;

Xml代码:


<resultMap type="pojo.Dept" id="deptRM">
<id property="deptId" column="dept_id"/>
<result property="deptName" column="dept_name"/>
 

<collection property="users" ofType="pojo.User">
<id property="id" column="id"/>
<result property="name" column="name"/>
<result property="age" column="age"/>
<result property="address" column="address"/>
 
collection>
resultMap>
 
<select id="findOneToMany" resultMap="deptRM">
select * from user_c,dept where user_c.dept_id=dept.dept_id
select>

知识点:
1.用collection配置多的一方,本例中是User,注意:ofType和Collection是固定搭配

持久层代码

public void testFindOneToMany(){
SqlSession session=factory.openSession();
List<Dept> list=session.selectList("pojo.UserMapper.findOneToMany");
for(Dept d:list)System.out.println(d);
}

知识点:
1.因为我们用的resultMap是dept的映射,所以查询结果是List,也就是说,必须通过Dept来查User的信息。
作业:对于一对多,如何通过User来查Dept的信息?如何配置?

多级关联+Extends


部门里有多个用户,每个用户有用户信息,怎么配置多级关联?
Xml代码:


<resultMap type="pojo.Dept" id="multiRM">
<id property="deptId" column="dept_id"/>
<result property="deptName" column="dept_name"/>
<collection property="users" ofType="pojo.User" >
<id property="id" column="userid"/>
<result property="name" column="username"/>
<result property="age" column="age"/>
<result property="address" column="address"/>
<association property="userInfo" javaType="pojo.UserInfo">
<id property="id" column="userinfoid"/>

<result property="name" column="userinfoname"/>
<result property="job" column="job"/>
<result property="hobbit" column="hobbit"/>
association>
collection>
 
resultMap>

配置思路:
一级一级的来配,通过Dept先配一对多,然后通过User配置一对一
持久层代码:

public void testMulti(){
SqlSession session=factory.openSession();
List<Dept> list=session.selectList("pojo.UserMapper.multiRM");
for(Dept d:list)System.out.println(d);
}

自动生成代码工具


为什么要学习这个工具?
在实际项目中,表的字段非常多,手动在映射文件写字段或是建立javabean都是不现实的,这个工具的作用:你指定数据库的一张表,利用这个工具就能自动生成javabean和写好的映射文件。

使用步骤:
1.在elicpse安装这个工具的插件
2.引入两个配置文件(一个是properties,一个是xml)
2.配置一些参数,比如和数据库的连接,指定哪张表,比如生成的javabean和映射文件放在哪个包下等
3.利用工具一键生成
知识点:
1.如何安装插件
将features和plugins都扔到eclipse—dropins的文件夹下,然后重启eclipse

2.如何验证是否安装成功
Eclipse-help-about eclipse -installation details,如果出现Mybatis的插件,证明安装成功

3.配置工具的参数信息
把这两个配置文件考到src目录下

4.工具生成文件的信息配置



<generatorConfiguration>

<properties resource="generatorConfig.properties"/>

<classPathEntry location="C:\Users\msi\Desktop\mysql-connector-java-5.0.8.jar" />

<context id="tarena">

<commentGenerator>
<property name="suppressAllComments" value="${suppressAllComments}"/>
commentGenerator>
<jdbcConnection driverClass="${driverClass}" connectionURL="${url}" userId="${username}" password="${password}" />

<javaModelGenerator targetPackage="${modeltargetPackage}" targetProject="${targetProject}" />

<sqlMapGenerator targetPackage="${sqltargetPackage}" targetProject="${targetProject}" />        
<javaClientGenerator targetPackage="${clienttargetPackage}" targetProject="${targetProject}" type="XMLMAPPER" /> 
 

<table schema="" tableName="user_c" />
context>
generatorConfiguration>

5.属性配置文件的信息

suppressAllComments=false  指定不要生成过多的注释 
driverClass=com.mysql.jdbc.Driver  指定数据库驱动
url=jdbc\:mysql\://localhost\:3306/mybatis?characterEncoding\=utf-8  连接数据库 注意:写自己的路径
username=root   登录账户
password=admin  密码
modeltargetPackage=cn.tarena.mybatis.model  指定javabean生成的目录
targetProject=1507MybatisDay02  指定为哪个工程生成,本例中是1507MybatisDay02
sqltargetPackage=cn.tarena.mybatis.mapper  指定生成的映射文件在哪个目录下
clienttargetPackage=client  指定接口类生成的目录

接口方式


开发步骤:
1.创建一个业务接口,比如UserMapper,这个接口里专门定义和User相关的方法。
2.在service层里调用
持久层代码:

public void testInterfaceFindAll(){
SqlSession session=factory.openSession();
List<User> list=session.getMapper(UserMapper.class).findAll();
for(User u:list)System.out.println(u);
}

1.这个接口我放在了pojo包下,如果放在别的包下行不?
2.这个接口的名字叫UserMapper,换一个行不行?
3.接口里的方法 findAll,这个方法恰巧在xml文件里也有,如果我换个方法名行不行?
思考:这个接口是怎么生效的?
接口方式的工作原理:
1.在映射文件里,我们定义了一个namespace,命名空间:pojo.UserMapper,实际上,这个名字就是接口类的路径名,所以我们在创建接口类:UserMapper.class时,要建在pojo包下。
2.在接口里创建了findAll()方法,实际上调用的是映射文件里的id=findAll()方法,所以,这个方法名要保持一致。

注册mapper类型


我们知道每个mapper配置文件的namespace属性对应于某个接口,应用程序通过接口访问mybatis时,mybatis会为这个接口生成一个代理对象,这个对象就叫mapper对象,在生成代理对象前mybatis会校验接口是否已注册,未注册的接口会产生一个异常。为了避免这种异常,就需要注册mapper类型。这个步骤是在XMLMapperBuilder的bindMapperForNamespace方法中完成的。它通过调用Configuration对象的addMapper方法完成,而Configuration对象的addMapper方法是通过MapperRegistry的addMapper方法完成的,它只是简单的将namespace属性对应的接口类型存入本地缓存中。
Configuration对象提供了一个重载的addMappers(StringpackageName)方法,该方法以包路径名为参数,它的功能是自动扫描包路径下的接口并注册到MapperRegistry的缓存中,同时扫描包路径下的mapper配置文件并解析之。解析配置文件是在MapperAnnotationBuilder类的parse方法里完成的,该方法先解析配置文件,然后再解析接口里的注解配置,且注解里的配置会覆盖配置文件里的配置,也就是说注解的优先级高于配置文件,这点需要注意。采用自动扫描会大大简化配置,只不过需要应用程序自己调用,mybatis默认是不会调用这个方法的(后续将会讲解的spring集成mybatis就用到了自动扫描,敬请期待)。

Spring+SpringMVC+Mybatis整合


整合步骤:
1.创建一个web工程
2.引入整合所需要的jar包
3.引入Mybatis的核心配置文件
4.引入Mybtais的映射文件
5.引入Spring的配置文件
6.引入SPringMVC的配置文件
7.修改web.xml 配置Spring的容器加载的listener +SpringMVC的DispatcherServelt+中文乱码解决器
8.项目部署和测试

Mybatis核心配置文件:



<configuration>
 
configuration>

知识点:
这个配置文件虽然什么都没写,但是还是需要保留。后期会配置别名、驼峰映射规则、分页插件等,需要在这里配置

Spring核心配置文件:

<context:component-scan base-package="service">context:component-scan>
 

<bean id="dataSourceMysql" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver">property>
<property name="url" value="jdbc:mysql://localhost/mybatis?characterEncoding=utf-8">property>
<property name="username" value="root">property>
<property name="password" value="admin">property>
bean>
        
<bean id="dataSourceOracle" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver">property>
<property name="url" value="jdbc:oracle:thin:@127.0.0.1:1521:XE">property>
<property name="username" value="1507htdb">property>
<property name="password" value="htdb">property>
bean>
         

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSourceOracle"/>

<property name="configLocation" value="classpath:sqlMapConfig.xml"/>
<property name="mapperLocations" value="classpath:pojo/*.xml"/>
bean>
 

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

<property name="basePackage" value="mapper"/>
bean>
         
        
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSourceOracle"/>
bean>
 
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<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 id="pc" expression="execution(* service.*.*(..))" />

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

SpringMVC的配置文件:

  
      <mvc:annotation-driven/>
      <context:component-scan base-package="/controller">context:component-scan>
    
      
      
      <bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
              <property name="prefix" value="/WEB-INF/"/>
              <property name="suffix" value=".jsp"/>
      bean>                
                                          
   
                  
    <mvc:default-servlet-handler/>

Web.xml代码:

<listener>
          <listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>
  listener>
  
  
 
  <context-param>
  <param-name>contextConfigLocationparam-name>
  <param-value>classpath:applicationContext.xmlparam-value>
  context-param>
  
  
<servlet>
<servlet-name>smvcservlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>

<init-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:springmvc-config.xmlparam-value>
init-param>
servlet>
 
<servlet-mapping>
<servlet-name>smvcservlet-name>
<url-pattern>/url-pattern>
servlet-mapping>

框架分工


56..java基础——零基础入门之Mybatis进阶_第1张图片

as 解决同名字段


方式一:

select user_c.id,user_c.name,user_c.age,user_c.address,user_info.id as userinfoid,
user_info.name as userinfoname,user_info.job,user_info.hobbit from user_c left join
user_info on user_c.id=user_info.id

方式二:

select * from user_c left JOIN
(select id as userinfoid,name as userinfoname,job,hobbit from user_info)ui on user_c.id=ui.userinfoid

上一篇 55.java基础——零基础入门之Mybatis

你可能感兴趣的:(大数据学习之旅)