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;}
}

浙公网安备 33010602011771号