MyBatis框架

MyBatis简介

MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架。MyBatis 避免了几乎所有的 JDBC 代码和手工设置参数以及抽取结果集。

MyBatis 使用简单的 XML 或注解来配置和映射基本体,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。

用MyBatis写一个简单的例子

1.建一个项目工程  2.在工程下新建一个叫lib的文件夹,里面存放一些jra包,然后把jra包生成路径到本工程下。  3.然后在src文件夹下创建实体类的包来存放放实体类、

创建映射文件的包来存放映射文件。  4.在工程下创建配置文件。  5.在工程下创建单元测试的包里面存放单元测试。

1.生成日志的jar包,能够在控制台观察到Sql语句的,也好找错。2.是mybatis的jar包,想用mybatis的框架就必须添加这个jar包

 

 

3.java与数据库连接的驱动jar包。不管在jdbc中还是mybatis中都需要此jar包。

实体类如下:

package com.zhiyou100.lw.bean;

public class Users {
    private int id;
    private String name;
    private int age;

    public Users() {
        super();
    }

    public Users(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }

    public Users(int id) {
        super();
        this.id = id;
    }

    @Override
    public String toString() {
        return "Users [id=" + id + ", name=" + name + ", age=" + age + "]";
    }

    public Users(int id, String name, int age) {
        super();
        this.id = id;
        this.name = name;
        this.age = age;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

}

映射文件需要插入代码如下:

<?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标签,标签里面写下自己要运行的代码,例如我要写增删改查的功能:

<mapper namespace="com.zhiyou100.lw.mybatis.Mybatis">
    <select id="getUser" parameterType="int" resultType="Users">
        select * from users where id=#{id}
    </select>
    <update id="updateU" parameterType="Users">
        update users set name=#{name},age=#{age} where id=#{id}
    </update>
    <insert id="insertU">
        insert into users(id,name,age) values(#{id},#{name},#{age})
    </insert>
    <delete id="deleteU" parameterType="int">
        delete from users where id=#{id}
    </delete>
    <select id="selectAll" resultType="Users">
        select * from users
    </select>
    <select id="selectD" parameterType="java.util.Map"
        resultType="Users">
    <![CDATA[select * from users where age between #{min} and #{max}]]>

    </select>
</mapper>

mapper标签里的namespace属性是此映射文件在工程下的路径,相当于分配一个空间给这个文件。里面的就是我写的一些功能。其中id就是为了给标签设置了一个名字,

在单元测试里面好查找到此标签。parameterType是参数的类型,在#{a}-a就是引入过来的参数,resultType是结果类型,就是运行结束后程序要返回的类型,

然后就是sql语句了。

配置文件:

<?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>

    <properties resource="db.properties" />

    <typeAliases>
        <typeAlias type="com.zhiyou100.lw.bean.Users" alias="Users" />
    </typeAliases>
    <environments default="development">

        <environment id="development">
            <transactionManager type="JDBC" />

            <dataSource type="POOLED">

                <property name="driver" value="${driver}" />
                <property name="url" value="${url}" />
                <property name="username" value="${username}" />
                <property name="password" value="${password}" />
            </dataSource>
        </environment>
    </environments>
    
</configuration>

这是配置文件中要插入的代码,其中 <properties resource="db.properties" />是我引入的属性文件标签,属性文件叫db.properties,之所以引入是因为,在我们以后的开发中

配置文件不会这么少,那么当有很多代码的时候就不好找到需要修改的地方了,特此才引入这个属性文件的,可以将属性文件放在工程下。

driver=com.mysql.jdbc.Driver

url=jdbc:mysql://localhost:3306/mybatis

username=root

 

password=root

这就是要修改的文件,与配置文件中的

 一一对应,这些与jdbc中的一样是,driver是驱动类,url是驱动链接的地址,username是数据库的用户名,password是密码

 

 

在配置文件中用${}来获得这个属性的值。

想要生成日志,不仅要添加日志的jar包还有添加一个日志的属性文件,直接在工程下添加就完事。里面的内容如下:

log4j.properties,
log4j.rootLogger=DEBUG, Console
#Console
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n
log4j.logger.java.sql.ResultSet=INFO
log4j.logger.org.apache=INFO
log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG

日志名要与jar包的名称要一致。

在测试类里面写:

   static SqlSession session=null;
    private String str="com.zhiyou100.lw.mybatis.Mybatis";
    @BeforeAll
    static void setUpBeforeClass() throws Exception {
        Reader reafer=Resources.getResourceAsReader("conf.xml");
        SqlSessionFactory sessionFactory=new SqlSessionFactoryBuilder().build(reafer);
        session = sessionFactory.openSession();
    }

    @AfterAll
    static void tearDownAfterClass() throws Exception {
    session.commit();
    }
   @Test void Testselect() { Users users = session.selectOne(str+".getUser", 1); System.out.println(users); }

在测试类之前会运行 @BeforeAll 里面的内容,之后会运行 @AfterAll里面的内容,在mybatis中程序是从配置文件中开始运行的所以要引入配置文件

Reader reafer=Resources.getResourceAsReader("conf.xml");括号里面是配置文件的路径,我是直接放在工程下的所以直接写配置文件名,获得要读取的对象
SqlSessionFactory sessionFactory=new SqlSessionFactoryBuilder().build(reafer);是得到SqlSessionFactory的一个对象,从这个对象里面得到session
括号里面的是要读取的一个对象,在测试类中用session调用映射文件中的程序,来实现所需要的功能。

mybatis的优化

接口与映射文件的结合
在src中在创建一个包,来存放接口的。
例如:
package com.zhiyou100.lw.dao;

import com.zhiyou100.lw.bean.Users;

public interface UserDao {
    public Users getUser(int id);
}

接口中的每个方法名要和映射文件中的每个查询标签的id名一样,必须一样才有效。

就是getUser要一样 

 

我们可以把配置文件、连接数据库的文件、日志文件放在新创建的resources文件夹下,比较整洁。

解决列名与属性名不一致的情况

如下:

<mapper namespace="com.zhiyou100.lw.dao.ClazzDao">
    <select id="selectById1" resultMap="ID">
        select * from teacher,class where teacher_id=t_id and c_id=#{cid}
    </select>
    <resultMap type="com.zhiyou100.lw.bean.Clazz" id="ID">
        <id column="c_id" property="cId"/>
        <result column="c_name" property="cName"/>
        <result column="teacher_id" property="teacherId"/>
        <association property="teacher" javaType="com.zhiyou100.lw.bean.Teacher">
            <id column="t_id" property="tId"/>
            <result column="t_name" property="tName"/>
        </association>
    </resultMap>
</mapper>

 

在映射文件中的mapper标签下加入resultMap标签,其中 type是与数据库中的该表所对应的实体类的路径,id是为这个标签起一个名字,让查询标签查找到这个标签,在查询标签中用resultmap

属性来调用这个来改变列名要与属性名一致的问题,改变从数据库中得到的字段名与实体类中的属性名一致。

关联查询

 多对一:就拿班级与教师来做例子,多个班级有一个教师,一个教师可以有多个班级,这个就是多对一的实例

在建实体类的时候,在多的那个实体类中添加以少的那个类为数据类型  起一个名字。如果按照以往的查询方式,各自建各自的实体类,这必然使代码的重复率太高,

效率太慢,没有直接在实体类中添加少的那个数据类型好用。

具体代码如下:

package com.zhiyou100.lw.bean;

import java.util.List;

public class Clazz {
    private int cId;
    private String cName;
    private int teacherId;
    private Teacher teacher;

    public Clazz(int cId, String cName, int teacherId, Teacher teacher) {
        super();
        this.cId = cId;
        this.cName = cName;
        this.teacherId = teacherId;
        this.teacher = teacher;
    }

    public Clazz() {
        super();
    }

    public Clazz(int cId) {
        super();
        this.cId = cId;
    }

    public int getcId() {
        return cId;
    }

    public void setcId(int cId) {
        this.cId = cId;
    }

    public String getcName() {
        return cName;
    }

    public void setcName(String cName) {
        this.cName = cName;
    }

    public int getTeacherId() {
        return teacherId;
    }

    public void setTeacherId(int teacherId) {
        this.teacherId = teacherId;
    }

    public Teacher getTeacher() {
        return teacher;
    }

    public void setTeacher(Teacher teacher) {
        this.teacher = teacher;
    }

    @Override
    public String toString() {
        return "Clazz [cId=" + cId + ", cName=" + cName + ", teacherId=" + teacherId + ", teacher=" + teacher + "]";
    }

}

其中Teacher就是少的那个类的数据类型 teacher是名字,这是一个对象,里面存放的是该对象的字段。在接口中写一个查询的方法返回的是班级类的对象,然后在映射文件中写如下:

接口的内容

public interface ClazzDao {
public Clazz selectById1(int id);
}

映射文件的查询语句

<select id="selectById1" resultMap="ID">
select * from teacher,class where teacher_id=t_id and c_id=#{cid}
</select>

测试类中

void testselect() {

Clazz c = clazz.selectById1(2);
System.out.println(c);
}

用多对一的联表方式也能查询所有满足条件的记录 

一对多:

就是在一的实体类中添加以多的实体类为数据类型的方法,用班级与学生来做例子,班级为一,学生为多,这个就是一个集合的数据类型了

泛型是学生的实体类

 

 接口和映射文件没有什么改变,在做单元测试后,方法返回的是集合。

动态SQL语句

 

所谓的动态sql语句就是,使用拼接的方法来得到SQL语句,为什么要用动态sql语句呢,因为在我们所需要根据不同条件查询出来的记录,如果用普通的方法写sql语句的话
会有大量的代码,而且还不能够满足客户的要求的时候,这个时候就有动态的SQL语句来解决这个问题了,它主要是以where标签,if标签,set标签,trim标签,组成的SQL语句的
动态语句如下:

<sql id="Base_Column_List">
id, NAME, age, sex, datetime
</sql>
<select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
select
<include refid="Base_Column_List" />
from users
where id = #{id,jdbcType=INTEGER}
</select>

这里面的sql标签是为了别的标签能够引用里面的字段。自己就不用写很多重复的代码了。他和include标签配合使用,在sql语句中合适的地方添加include标签

<select id="selectByWhere" resultType="com.zhiyou100.lw.bean.Users">
        select * from users
        <where>
            <if test="name!=null">
                and name=#{name}
            </if>
            <if test="sex!=null and sex!=''">
                and sex=#{sex}
            </if>
        </where>
    </select>

这是用where标签和if标签组成的根据条件查询的语句

<update id="updateBy">
        update users 
        <set>
            <if test="sex!=null">
                sex=#{sex},
            </if>
            <if test="name!=null">
                name=#{name},
            </if>
            <if test="age!=null">
                age=#{age},
            </if>
        </set>
        where id=#{id}
    </update>

这是用set标签和if标签组成的更改语句

 

 

 

 

 

 

 

 

 

 

 

 

package com.zhiyou100.lw.bean;
public class Users {private int id;private String name;private int age;
public Users() {super();}
public Users(String name, int age) {super();this.name = name;this.age = age;}
public Users(int id) {super();this.id = id;}
@Overridepublic String toString() {return "Users [id=" + id + ", name=" + name + ", age=" + age + "]";}
public Users(int id, String name, int age) {super();this.id = id;this.name = name;this.age = age;}
public int getId() {return id;}
public void setId(int id) {this.id = id;}
public String getName() {return name;}
public void setName(String name) {this.name = name;}
public int getAge() {return age;}
public void setAge(int age) {this.age = age;}
}

 

posted @ 2019-08-31 16:17  呦呀哦啦  阅读(186)  评论(0)    收藏  举报