秋招准备-后台框架-Mybatis

Mybatis

    Mybatis是一个支持普通SQL查询存储过程高级映射持久层框架。

    Mybatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装。

    Mybatis可以使用简单的XML注解用于配置和原始映射,将接口和Java的pojo映射成数据库的记录。

 

  •     简单介绍

    1.mybatis-config.xml

    在该xml文件中配置连接数据库的一些信息,如数据库驱动(driver),路径(url),账号密码等。该文件一般处于项目最外层。

    之后将该xml文件作为resource来一步步实例化SqlSession。

    别名标签下,定义该包下的pojo类型可以在写resultType时直接写类名而不用写全限定名。

    用来注册mapper.xml。

    2.接下来,应该有一个pojo的包(也可以说是model层。)里面还有pojo类。

    pojo对象主要是自己想要读取的内容,将其封装成一个对象,到时候在读取时再将数据库中读取到的内容映射到该类的属性变量中。写好pojo类的属性,自动生成get()set()方法,按情况重写toString()equal()hashCode()方法。

    3.然后,需要一个dao层,一般一个pojo对应一个mapper。在dao层里,写mapper.xml和mapper接口。

    4.然后,可以在需要访问数据的地方,通过config.xml一步步构建SqlSession,然后获得mapper接口的实例,再用其执行定义好的方法来完成SQL语句执行。

 

 

  •    常用对象:

    1.SqlSessionFactory

    SqlSessionFactory的实例可以通过SqlSessionFactoryBuilder获得,而SqlSessionFactoryBuilder则可以从xml配置文件或一个预先定制的Configuration的实例构建出SqlSessionFactory的实例。

    从xml文件构建SqlSessionFactory的实例,一般按如下形式:

String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

    SqlSessionFactory用来获得SqlSession实例。

    2.SqlSession

    SqlSession完全包含了面向数据库执行SQL命令所需的所有方法,可以通过SqlSession实例来执行已映射的SQL语句,也可以通过SqlSession获得mapper接口的实例,然后用该实例来执行SQL方法。

    最常用的形式:

SqlSession session = sqlSessionFactory.openSession();
//直接执行
session.selectOne("全限名.方法名",参数)
//实例化mapper
session.getMapper(全限名.class)

    使用完SqlSession对象,要调用close()方法将其关闭

 

 

  •     使用xml写简单的CURD

    里,最好写namespace,为该mapper的全限名。mapper.xml和mapper接口是同一个较好。

    下,即 select * from product_ where id = #{id} //ProductMapper.java public Product selectById(@param("id") int id); //test.java Product p = mapper.selectById(10); //如果使用#{0}、#{1},则不需要@param注解,#{0}对应第一个参数,依次类推。

 

    2.查找单pojo,用parameterType传对象。

数据库、pojo同上
写查询语句:
//ProductMapper.xml<1>

//ProductMapper.java
public Product selectById(Product product);
//test.java
Product p1 = new Product(); p1.setId(10); 
Product p2 = mapper.selectById(p1);

//根据传入Product对象,自动取得其id。

   

    3.一对一查询

    一对一类似:一个班级只由一个老师负责。一个老师只对应他的那个班级。

    则该类数据存储在数据表中的形式应该为:

classes_(int cid,varchar(20) name,int tid)
teacher_(int tid,varchar(20) name,int cid)

    pojo对象应该如下定义:

class Classes
{
    int cid;
    String name;
    Teacher teacher;
}
class Teacher
{
    int tid;
    String name;
    Classes classes;
}//省略set/get

    mapper.xml写sql:


    
    

    
        
        
    


    实际上,一对一和多对一种,可以理解为一个类包含另一个类的对象。然后在resultMap中作字段名与属性名的映射。在查询语句中,则要把需要的数据都查找出来。

    中,type为对应的pojo类全限名。id为唯一标识该resultMap的值,在之后的sql返回参数resultMap中设定。

    为数据表中主键对应的标签,和差不多,关键是之后的属性,column对应查询字段值,property对应pojo中的属性值。

    用来关联,javaType标识该类全限定名,property一样为pojo相应属性值。

 

    4.一对多,多对一

    模型可以理解成,一个班有多个学生,多个学生对应一个班。

    数据存储在数据表中的形式应该为:

classes_(int id,varchar(20) name);
student_(int id,varchar(20) name,int cid);

    pojo对象应该定义如下:

class Classes
{
    int id;
    String name;
    List student;
}
class Student
{
    int id;
    String name;
    Classes classes;
}

    ClassesMapper.xml:

 
    
    

    
        
        
    
 

 

    StudentMapper.xml的写法即多对一的写法,和一对一类似。

 

    5.多对多。

    模型:一个学生可以加入多个小组,一个小组可以有多个学生。

    数据存储形式:

Student_(int id,varchar(20) name);
Group_(int id,varchar(20) name);
Join(int sid,int gid,int price);

     pojo定义:

class Student
{
    int id;
    String name;
    List join;
}
class Group
{
    int id;
    String name;
    List join;
}
class Join
{
    int sid;
    int gid;
    int price;
}

    StudentMapper.xml和GroupMapper.xml类似


    
    

    
        
            
            
        
    
 



//取出List后
for(Group g:gl)
{
    int gid = g.getId();    String gname=g.getName();
    List jl = g.getJoin();
    for(Join j : jl)
    {
        int price = j.getPrice();
        List sl = j.getStudent();
        for(Student s : sl)
        {
            int sid = s.getId();     String sname = s.getName();
        }
    }
}

 

 

  •     动态SQL

    1.

    一般可以用来增加条件。如:当有某个参数时,按照这个参数进行某种条件筛选。

    表示#{id}不为空时
        where id > #{id}
    

 

    2.

    如果要写多个时,每个语句都写where,就不能叠加,会造成愈发错误。而一个写where另一个写and追加条件,又会造成只满足and那个时语法错误。如:

    
        where name like concat('%',#{name},'%')
    
    
        and price > #{price}
    

    所以这种情况,可以用

    
        
            and name like concat('%',#{name},'%')
        
    

    如果两个条件都不满足,会自动去掉

 

    3.类似,在update中,也会碰到多字段问题。这种情况可以使用

    
     	name=#{name},
     	price=#{price}
    

 

    4.,,达到if-else效果

    
	    
		  
		    and name like concat('%',#{name},'%')
		  			  
		  
		    and price > #{price}
		  			  		
	  	  
	  	  	and id >1
	  	  
	    
    

    多条件达成时,只会选择最先达成的条件执行接下来的语句。

 

    5.

    标签通常用在in这样的语句中。

    像是再做一次字符串拼接,方便后续使用。如

 

 

  •     Mybatis注解

    1.简单的sql语句,可以直接写成注解形式。如:

@Select("select * from student_") 
public List listStudent();

@Update("update student on name = #{name} where id = #{id}")
public int updateStudent(@Param("name") String name,@Param("id") int id);

@Insert("insert into student_ (name) values (#{name}) ")
public int addStudent(Student student);

@Delete("delete from student_ where id = #{0}")
public void deleteStudent(int id);

 

    2.@Results和@Result类似在xml中写resultMap,作用仍是用来确定字段与属性名的映射关系。

    而在一对多和多对一的情况下,可以使用@Many和@One注解,关联其他表进行查询。可以用column传参。

 

    3.动态SQL的注释用法。

    需要新加一个 SqlProvide类,写好方法后,再用@InsertProvider之类的标签。

 

 

  •     Tips:

    1.代码块,用来代码重用

    2.limit用来分页

 

 

  •     Ques:

    1.#{]和${}的区别是什么

    #{}是预编译处理,${}是字符串替换。

    Mybatis在处理#{}时,会将sql中的#{}替换为?,调用PreparedStatement的set方法来赋值。

    Mybatis在处理${}时,就是把${}替换成变量值。

    #{}防止sql注入,安全性高。

 

    2.实体类中的属性名和表中的字段名不一样时:

    <1>通过在查询的sql中定义字段名的别名,让字段名的别名和实体类的属性名一样。

    <2>通过来映射字段名和实体类属性名的一一对应关系。(column和property)

 

    3.通常一个xml映射文件与一个Dao接口对应。Dao工作原理:

 

    Dao接口,就是人们常说的Mapper接口,接口的全限名,就是映射文件中的namespace的值,接口的方法名,就是映射文件中MappedStatement的id值,接口方法内的参数,就是传递给sql的参数。

   Mapper接口是没有实现类的,当调用接口方法时,接口全限名+方法名拼接字符串作为key值,可唯一定位一个MappedStatement

    在Mybatis中,每一个