mybatis基础知识

Mybatis框架
1.What?
  MyBatis是支持普通SQL查询,存储过程和高级映射的优秀持久层框架!以面向对象的方式进行持久化业务,采用XML配置文件,说明映射关系,动态查询,关系映射。
  MyBatis可以使用简单的XML或注解用于配置和原始映射,比较有特色的地方是可以定义操作xxx表的sql映射文件(可以对对象的操作采用配置方式进行)。


  持久层(ORM):
  1)对象--->数据库
  2)数据库数据---->对象
  
2.用于进行持久化业务!
3.HelloWorld:学习应用MyBatis框架的一般步骤(掌握Mybatis框架的体系结构)
  1)创建工程
     a.创建数据库表:
     create table Users(


userId numeric primary key,
userName varchar2(50) not null,
userAge Integer check(userAge > 0)


     );
     create sequence seq_userid
     start with 1
     increment by 1
     nomaxvalue
     nocache;


     insert into users values(seq_userid.nextval, 'James', 31);
     insert into users values(seq_userid.nextval, 'Jordan',58);


     b.创建实体类:
     public class User {


private int userId;
private String userName;
private int userAge;
// 添加SET以及GET方法
     }


  2)导入jar包:mybatis-3.1.1.zip
     lib-->mybatis-3.1.1.jar-->add to buildpath
     ojdbc6.jar(Oracle11g)
     classes12.jar(Oracle10g)

  3)创建Mybatis的配置文件conf.xml,在里面配置相关信息(数据源,映射文件,对类名重命名,装载properties资源文件,日志业务定义)
     定义在src根目录下
     名称一般为conf.xml
     标签解读:
      PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">








 



















     a.:作为conf.xml文件的根标记
     b.:用于引入xx.properties文件
     c.:其中可以有若干个environment,MyBatis可以配置多种环境。这会帮助你将SQL映射应用于多种数据库之中
                                            要记得一个很重要的问题:你可以配置多种环境,但你只能为每个SqlSessionFactory实例选择一个
     d.environment:对应一个SqlSessionfactory
     e.     f.dataSource:访问数据库的信息写在其中
     g.mappers:映射其他文件机构
       mapper:
       
       补充:Mybatis对于映射文件支持,也对指定的POJO类或接口支持——对于其中定义好的业务操作,进行代理实现。
    实现主要方式:在相关接口类中的抽象方法头部加注解,也就是说对于实体类相关持久化操作都有对应的注解,比如:@Insert,@Update,@Delete,@Select
       
Eg:采用注解的方式对于所谓的POJO类或接口进行业务代理实现步骤
1)定义对于某个实体类的业务操作接口
2)定义接口中的实体业务方法
3)在相关方法头部添加注解(其中说明如何实施对应的操作)
4)使用前提:将该接口类信息注册到conf.xml文件中
 
        5)调用或执行业务接口类中的业务行为:
  
  // 谁负责调用?session调用getMapper(xxxIterfaceName.class),从而得到业务接口类的代理对象

  // 如何调用?由业务接口代理对象,调用相关业务行为


  Eg:
  // 通过session调用getMapper(XXXInerfaceName.class),得到业务接口类的对象
  IUser userDao = session.getMapper(IUser.class);
  // 由业务接口对象调用业务行为
  userDao.deleteUser(3);
  // 从而得到业务实现
  // session.commit();




  4)定义操作xxx表(某某实体类)的sql映射文件(xml文件)
     定义对于某些类的持久化业务操作的映射文件:
     a.位置:和其对应的实体类在同一个包。

     b.命名方式:xxxTypeNameMapper.xml
userMapper.xml
     c.内容构成:
       
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

       





       



  5)调用业务方法实现持久化业务:
     Hibernate:
     // 定义一个全局Configuration对象
Configuration config = new Configuration();
config.configure("/hibernate.cfg.xml");
     // 创建SessionFactory对象,装载所有的对象映射文件
SessionFactory sessionFactory = config.buildSessionFactory();
     // 创建session对象,从而为查询遍历做准备
        Session session = sessionFactory.openSession();
     
     Mybatis:
 
     String resource = "conf.xml"; 
     //加载mybatis的配置文件(它也加载关联的映射文件)
     Reader reader = null;
     try {
  reader = Resources.getResourceAsReader(resource);
     } catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
     } 
     //构建sqlSession的工厂
     SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);
     //创建能执行映射文件中sql的sqlSession
     SqlSession session = sessionFactory.openSession();
     //映射sql的标识字符串
     String statement = "com.hd.netstore.entity.userMapper.getUser";
     //执行查询返回一个唯一user对象的sql
     User user = session.selectOne(statement, 1);
     System.out.println(user);
     需要参与到持久化业务中的类:
     a.Reader:相当于Hibernate框架的Configuration,加载conf.xml文件
       Reader reader = null;
       reader = Resources.getResourceAsReader("conf.xml");
     b.SqlSessionFactory:用于将映射文件解析装载
       SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);
     c.SqlSession:相当于链接对象,执行所有增删改的操作。
       SqlSession session = sessionFactory.openSession();
       Methods:
       c-1.selectOne:通过session去进行持久化查询操作时用到的方法
       c-2.selectList:通过session去进行持久化查询操作时用到的方法,但是可以查询多个值
       c-3.insert:insert通过session去进行持久化添加操作时用到的方法,执行之后会返回一个整数,表示进行添加操作之后,数据库中受此影响的行数。
       c-4.update:通过session去进行持久化修改操作时用到的方法
       c-5.delete:通过session去进行持久化删除操作时用到的方法
       c-6.close():关闭流,撤销资源
       c-7.commit():提交事务。
4.补充
  修改操作事务,最终提交方式有两种:
  1)在获得Session对象引用时,在openSession()方法的括号中,增加值为true的参数,可以实现自动提交
     session = sessionFactory.openSession(true); 
  2)通过session对象的commit()方法,实现业务提交
     session.commit();
5.优化功能实现?
  5-1.将业务实现时一些重复操作封装起来,便于重用:
      1)session的获得
      2)关闭session
      public class MybatisOrmDbhelper {


public static SqlSession getSession() {
SqlSession session = null;
// 相当于Hibernate框架的Configuration,加载conf.xml文件
Reader reader = null;
try {
reader = Resources.getResourceAsReader("conf.xml");
// 用于将映射文件解析装载
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);
// 相当于链接对象,执行所有增删改的操作。
session = sessionFactory.openSession(true);


} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();

return session;
}

public static void closeSession(SqlSession session) {
if (session != null) {
session.close();
}
}
      }
  5-2.优化resultType所使用的全命名格式-->给package.xxxtype ==> target: typeparam,希望可以以typeparam替代package.xxxtype
      1)重命名在什么地方?
     


      2)怎么实现重命名?
重命名应该让整个系统知道,应该将类的命名参数定义在conf.xml文件中


...

      3)使用:在系统中需要表达类别的时候,可以使用alias属性替换原有比较冗长的命名











  5-3.解决字段名与实体类属性名不相同的冲突
      类的成员变量和对应表的列的好的命名习惯——将类的成员变量的名和表中列的明明保持一致。
      如何解决冲突:
      Eg:
create table batches(
    batchNo varchar2(50) primary key,
    batchDirection varchar2(100) not null,
batchEmpCount integer check(batchEmpCount > 0)
 );

Teachers(teacherId,teacherName,teacherAge,teacherDirection, batchId)
create table teachers(
    teacherId varchar2(50) primary key,
teacherName varchar2(50) not null,
teacherAge integer check(teacherAge>0),
teacherDirection varchar2(100),
    batchId varchar2(50) references batches(batchNo)


);
         public class Teacher {


private String teaId;
private String teaName;
private int teaAge;
private String teaDirection;
private String batId;
// SET以及GET方法
...


}
      解决方案:
      1)通过在sql语句中定义别名


      2)通过








6.关系映射:实现对象级的关联操作
  6-1.one to one:一对一关联,期望:通过一对一的关联,实现通过一个对象的属性,直接检索和它一对一关系的对象
      Eg:班级 对 老师
      1)创建表和类:
 reate table batches(
    batchNo varchar2(50) primary key,
    batchDirection varchar2(100) not null,
batchEmpCount integer check(batchEmpCount > 0)
 );
 insert into batches values('Batch01','Java', 30);
 insert into batches values('Batch02','Html5', 50);
 insert into batches values('Batch03','Test', 20);


 create table teachers(
    teacherId varchar2(50) primary key,
teacherName varchar2(50) not null,
teacherAge integer check(teacherAge>0),
teacherDirection varchar2(100),
    batchId varchar2(50) references batches(batchNo)
 );
          insert into teachers values('SX001','Kobe',39,'Java','Batch01');
 insert into teachers values('SX002','KD',29,'HTML5','Batch02');
 insert into teachers values('SX003','Jordan',59,'Java','Batch03');
       2)创建映射文件:希望通过一个老师,检索他对应的班级对象
          a.Method1:结果嵌套
   
   











   

   
          b.Method2:通过查询嵌套
           
   
   
   



   



   
       



       
       


       Class Task:创建两个表——国家首都关系,通过一对一关联,可以实现对象级操作。
   
  6-2.one to many:订单(订单编号,订单总额,订单时间,订单发货地址,卖家) -- 订单构成项(订单构成项编号,订单构成项商品id,订单构成项商品数量,订单编号)

      1)创建表和关系:
create table orderspre(
        orderId number primary key,
        orderTotal numeric check(orderTotal >= 0),
      orderTime timestamp,
        orderAddress varchar2(200)


);
create sequence seq_orderidpre
start with 1
increment by 1
nomaxvalue;


insert into orderspre values(seq_orderidpre.nextval, 1000, sysdate, 'Shanghai Yanan road 3000');
insert into orderspre values(seq_orderidpre.nextval, 2000, sysdate, 'JiaXing Luli street 100');
insert into orderspre values(seq_orderidpre.nextval, 3000, sysdate, 'Beijing Qianmen road 10');


create table orderIterms(
        orderItermId number primary key,
        orderId number references orderspre(orderId),
        orderItermName varchar2(50) not null,
        orderItermCount integer check(orderItermCount>0) 


);
create sequence seq_orderItermidpre
start with 1
increment by 1
nomaxvalue;


insert into orderIterms values(seq_orderItermidpre.nextval,1,'Apple8', 5);
insert into orderIterms values(seq_orderItermidpre.nextval,1,'DellBIZ01', 20);
insert into orderIterms values(seq_orderItermidpre.nextval,3,'Lenovo', 30);
      2)创建表所对应的实体类:
a.Order.java-->订单表所对应的类型
  由于Order是一对多关系一方,所以,在该类的属性中要有一个存储对应多方(订单项)的集合作为属性
  private int orderId;
  private double orderTotal;
  private Timestamp orderTime;
  private String orderAddress;
  private List orderItermList;
  注意:在Order类中,记着定义订单项集合属性的SET以及GET方法!!!
  
 
b.OrderIterm.java--->订单项对应的类型
           private int orderItermId;
  private int orderId;
  private String orderItermName;
  private int orderItermCount;
3)定义一个Order的映射文件,OrderMapper.xml,并将其添加到conf.xml文件:
 
 

  Content shown as bellow:

 











 

 
  或
 
         
  6-3.many to one:站在many to one的many方来看,任何一个对象,都有一个一对一的一方关联(就是many to one中的one)。
      采用one to one的配置方法就可以了:
      Eg: orderIterm  order
      1)在OrderIterm的属性中,添加order属性,并增加SEG和GET方法。
      2)给OrderIterm类添加对应的映射文件:OrderItermMapper.xml
内容:
         














3)客户端调用执行
  
  6-4.many to many: Employees  Projects
      分析出多对多关系之后,要分别创建三个表,其中一个表示关系表(纳入了另外两个表的关键字信息),而且将另外两个表的主键纳入后,形成组合主键。
      需要创建的表:员工表、项目表、员工项目关系表
      6-4-1.创建表:Employees Projects
 1)xhemployees:


 create table xhemployees(
      empId varchar2(50) primary key,
    empName varchar2(50) not null,
    empLevel varchar2(50) check (empLevel in ('Level1','Level2','Level3'))


     );
 2)xhprojects:


     create table xhprojects(
    projId varchar2(50) primary key,
    projName varchar2(200) not null,
    projEmpnum integer check(projEmpnum >= 0),
    projState integer check(projState=0 or projState = 1)
     );
          3)xhemp_proj:员工项目关系表(内容包括另外两个表的主键,并由它们构成关系表的组合主键)
     create table xhemp_proj (
    empId varchar2(50) references xhemployees(empId),
    projId varchar2(50) references xhprojects(projid),
    createTime timestamp not null


     );


     commit;
 修改表结构,定义复合主键
     alter table xhemp_proj add constraints xhep_pk primary key (empId,projId);


 4)向三个表中填写数据:
          insert into xhemployees values('XHJ001','James','Level1');
 insert into xhemployees values('XHJ002','Kobe','Level2');
 insert into xhemployees values('XHJ003','Jordan','Level3');
 commit;
 insert into xhprojects values('PR001','China dragon',50,1);
 insert into xhprojects values('PR002','Big data',100,1);
 insert into xhprojects values('PR003','West development',80,1);


 insert into xhemp_proj values('XHJ001','PR001',sysdate);
 insert into xhemp_proj values('XHJ001','PR002',sysdate);
 insert into xhemp_proj values('XHJ002','PR001',sysdate);
 insert into xhemp_proj values('XHJ003','PR001',sysdate);


 commit;
 5)定义实体类:
    a.定义xhemployees表的实体类-->Employee.java
      public class Employee {
      private String empId;
      private String empName;
      private String empLevel;
// 添加属性的SET和GET方法
      }
    b.定义xhprojects表的实体类-->Project.java
      public class Project {

private String projId;
private String projName;
private int projEmpnum;
private int projState;
// 项目中的多个员工,在向目标的属性中,添加一个员工集合,作为属性,然后,给该集合添加SET和GET方法
private List employees;
      }
    c.定义关系对象?建议尝试
  6)站在Project的角度来看,它相关员工集合如何实现呢?
     a.给Project定义映射文件,在文件中说明关联关系:
映射文件名:ProjectMapper.xml

















项目表 left join 项目员工关系表 on 项目表.项目id = 项目员工关系表.项目id
left join 员工表 on 项目员工关系表.员工id = 员工表.员工id
    

             
7.动态SQL查询: MyBatis的动态SQL是基于OGNL表达式的,它可以帮助我们方便的在SQL语句中实现某些逻辑。
  MyBatis中用于实现动态SQL的元素主要有:
  7-1.SQL指令:
      1)if
 
      2)choose(when,otherwise)
      3)trim
      4)where
      5)set
      6)foreach
8.调用存储过程:procedure,是一种存在于数据库服务器中的对象,一旦创建,就可以多次使用,执行速度快,效率高。
它可以通过输出参数获得多个结果,结果相当于返回值。
  8-1.存储过程
  Synax: 
注意:在定义procedure时候,参数区中的变量类型不要具体化。
     在存储过程中SQL语句中,给变量赋值的手法——采用select into xxxvaribaleName ...
     在存储过程中给变量赋值,可以采用直接赋值:
     xxxvaribaleName := value;

create or replace procedure proc_xxx(
paramName1 in | out | in out Type,
paramName2 in | out | in out Type,
...
)
as 
declare ...
begin
statement...


Exception 
when condition then 
    ... ;
end proc_xxx;

存储过程创建语法: 
        create or replace procedure 存储过程名(param1 in type,param2 out type) 
as 
变量1 类型(值范围); 
变量2 类型(值范围); 
Begin 
    Select count(*) into 变量1 from 表A where列名=param1; 
    If (判断条件) then 
        Select 列名 into 变量2 from 表A where列名=param1; 
        Dbms_output.Put_line(‘打印信息’); 
    Elsif (判断条件) then 
        Dbms_output.Put_line(‘打印信息’); 
    Else 
        Raise 异常名(NO_DATA_FOUND); 
    End if; 
Exception 
    When others then 
        Rollback; 
End; 


Eg:
  create or replace procedure proc_query_userage(
usId in Integer,
uName in Varchar2,
age out integer

  )
  as
rowcount integer;
  begin 
select count(*) into rowcount from users where userId = usId and userName = uName;
if (rowcount > 0) then
select userAge into age from users where userId = usId and userName = uName;
else
age := rowcount;
end if;
  Exception 
when others then
rollback;
  end;
  
在Oracle console控制台调用存储过程的语法:在调用时,给予输入参数值的时候,把赋值放在数据类型之后
declare
      usId  Integer :=9;
      uName  Varchar2(50) :='YaoMing';
      age  integer;
begin
      proc_query_userage(usId,uName,age);
      dbms_output.put_line( age);
end;
  8-2. 在Mybatis中调用存储过程
       往往在一个映射文件中有那么一些增删该查的操作,存储过程的调用就体现在它们里面。
       支持的JDBC类型
       为了未来的参考,MyBatis通过包含的jdbcType枚举型,支持下面的JDBC类型。
BIT
FLOAT
CHAR
TIMESTAMP
OTHER
UNDEFINED
TINYINT
REAL
VARCHAR
BINARY
BLOB
NVARCHAR
SMALLINT
DOUBLE
LONGVARCHAR
VARBINARY
CLOB
NCHAR
INTEGER
NUMERIC
DATE
LONGVARBINARY
BOOLEAN
NCLOB
BIGINT
DECIMAL
TIME
NULL
CURSOR
  1)在映射文件中,调用存储过程语法:
    在某个业务操作中,调用相关的存储过程,调用时,调用语法:call proc_xxxx(?,...),业务操作标签的statementType="CALLABLE",返回值和输入值是同一个参数,参数
    列表是Map集合,该集合的定义采用parameterMap标签实现,其中type取值为java.util.Map,id表示该参数集合的名字,其中的子标签parameter用于说明该存储过程的参数
    要求。
    参数的定义:
    property:是参数的名字
    mode:是参数的类别(取值范围是:IN,OUT,INOUT)
    jdbcType:是指定参数的数据类型,而且是指Mybatis中认可的类别。


   






   2)java程序调用映射文件中的某个业务行为(该行为中有调用存储过程):

     a.准备一个Map对象,用于存储存储过程需要的参数,参数的名字要和定义在映射文件中的参数名一致。添加到Map集合的格式如下:
       Map paramMap = new HashMap();
       paramMap.put("usId", 1);
       paramMap.put("usName", "YaoMing");
       paramMap.put("usAge", 0);
     b.将Map参数集合对象作为参数提交给相关业务方法
       session.selectOne(statement, paramMap);
     c.Map集合对象负责将存储过程输出参数的值取出:
       paramMap.get("输出参数的名字")


  Class Task: 定义一个模拟登录的存储过程,要求提供用户名和密码,经过查询,通过返回值说明验证的结果,在java程序中调用存储过程,获得验证的结果。   

     
9.一级二级缓存:
hibernate 的一级缓存 session 二级缓存 sessionFactory
mybats : 一级缓存:session  二级缓存是对应一个XxxMapper(某个类的映射文件)
一级缓存: 当session多次 调用select 时,如果没有进行修改(更新,修改,删除),则已经持久化到缓存中的对象是同一个
 当session主动调用clearCache()方法时,会清空一级缓存
二级缓存: 使用的时候,在配置文件中添加  实体类必须实现序列化接口
添加一个二级缓存的配置文件
10.Spring和SpringMvc的整合
11.Spring和Mybatis的整合


     log4j   
%d是时间, %l;路径    [%t]线程 P:消息级别 c 类名 m 消息 N 换行

你可能感兴趣的:(mybatis)