Mybatis01
1.什么是MyBatis ?
MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。
iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAOs)
概述
MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Ordinary Java Object,普通的 Java对象)映射成数据库中的记录。
Hibernate (很强大,重量级,不灵活,复杂)
特点
- 简单易学:本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现。
- 灵活:mybatis不会对应用程序或者数据库的现有设计强加任何影响。 sql写在xml里,便于统一管理和优化。通过sql语句可以满足操作数据库的所有需求。
- 解除sql与程序代码的耦合:通过提供DAO层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。
- 提供映射标签,支持对象与数据库的orm字段关系映射
- 提供对象关系映射标签,支持对象关系组建维护
- 提供xml标签,支持编写动态sql。
中文官网
2快速入门
1.创建maven工程
2.在pom.xml文件下引入依赖
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
</dependency>
</dependencies>
3.引入实体类
/**
* 学生实体类 与 student_tb一一对应
*/
public class Student implements Serializable {
private int id;
private String name;
private String sex;
private int age;
private float height;
private Date birthday;
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 String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public float getHeight() {
return height;
}
public void setHeight(float height) {
this.height = height;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", sex='" + sex + '\'' +
", age=" + age +
", height=" + height +
", birthday=" + birthday +
'}';
}
}
4.编写持久层IStudentDao接口
import com.wgz.entity.Student;
import java.util.List;
public interface IStudentDao {
/**
* 查找所有学生
* @return
*/
List<Student> findAllStudent();
}
5.编写持久层配置文件IStudentDao.xml
注意:
- 1.配置文件的名称必须以 接口名+.xml命名
- 2.文件的位置必须放在main目录下resources\com\wgz\dao对应目录
<?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 namespace="com.wgz.dao.IStudentDao">
<!--配置查询所有学生的 方法
id:为对应的方法方法名
resultType:返回数据类型的全限定名
-->
<select id="findAllStudent" resultType="com.wgz.entity.Student">
select * from student_tb
</select>
</mapper>
6.在 创建sqlMapConfig.xml
<?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">
<!--
mybatis主配置
-->
<configuration >
<!--配置mybatis环境-->
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC"></transactionManager>
<!--配置数据源-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/szqy08"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/wgz/dao/IStudentDao.xml"></mapper>
</mappers>
</configuration>
7.创建测试类
public class TestMybatis {
public static void main(String[] args) {
try {
// 1.读取配置文件
InputStream in = Resources.getResourceAsStream("sqlMapConfig.xml");
// 2.创建session工厂
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(in);
// 3.获取session
SqlSession sqlSession = sqlSessionFactory.openSession();
// 4.使用sqlSession 创建代理对象
// 方式一 通过代理:
// IStudentDao studentDao = sqlSession.getMapper(IStudentDao.class);
// List<Student> studentList = studentDao.findAllStudent();
// 方式二:方式儿直接指明方法名
List<Student> studentList = sqlSession.selectList("com.wgz.dao.IStudentDao.findAllStudent");
for (Student student:studentList){
System.out.println(student);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
8.配置mybatis的日志,在resouces目录下创建log4j.properties
# Set root category priority to INFO and its only appender to CONSOLE.
#log4j.rootCategory=INFO, CONSOLE debug info warn error fatal
log4j.rootCategory=debug, CONSOLE, LOGFILE
# Set the enterprise logger category to FATAL and its only appender to CONSOLE.
log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE
# CONSOLE is set to be a ConsoleAppender using a PatternLayout.
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n
# LOGFILE is set to be a File appender using a PatternLayout.
log4j.appender.LOGFILE=org.apache.log4j.FileAppender
log4j.appender.LOGFILE.File=mybatis.log
log4j.appender.LOGFILE.Append=true
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.LOGFILE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n
3.基于mybatis实现curd
根据id查询学生
1.IStudentDao接口中增加
/**
* 根据 查询学生
* @param id
* @return
*/
Student findStudentById(int id);
2.在IStudentDao.xml中增加
<select id="findStudentById" parameterType="java.lang.Integer" resultType="com.wgz.entity.Student">
select * from student_tb where id=#{id}
</select>
说明:
-
parameterType:为传入参数的类型
-
resultType:为输出参数的类型
-
#{id} 为占位符 获取接口中的参数
3.测试
private static void findStudentById(IStudentDao studentDao) {
Student student = studentDao.findStudentById(42);
System.out.println("student:"+student);
}
增加学生
1.IStudentDao接口中增加
/**
* 保存学生
* @param student
*/
void saveStudent(Student student);
2.在IStudentDao.xml中增加
<insert id="saveStudent" parameterType="com.wgz.entity.Student" >
insert into student_tb (name,age,sex,height,birthday)values (#{name},#{age},#{sex},#{height},#{birthday})
</insert>
说明
- #{name} 为获取参数中student 对象中的属性值
3.测试
/**
* 增加学生
* @param studentDao
*/
private static void addStudent(IStudentDao studentDao) {
Student student = new Student();
student.setAge(19);
student.setName("zhangsan");
student.setHeight(178);
student.setBirthday(Date.valueOf("2007-02-23"));
studentDao.saveStudent(student);
}
删除学生
1.IStudentDao接口中增加
/**
* 删除学生
* @param id
* @return
*/
int deleteStudentById(int id);
2.在IStudentDao.xml中增加
<delete id="deleteStudentById" parameterType="java.lang.Integer">
delete from student_tb where id = #{id}
</delete>
3.测试
private static void deleteStudent(IStudentDao studentDao) {
// 获取影响 修改的数量
int num= studentDao.deleteStudentById(44);
System.out.println("num:"+num);
}
修改学生
1.IStudentDao接口中增加
/**
* 更新学生
* @param student
* @return
*/
int updateStudent(Student student);
2.在IStudentDao.xml中增加
<update id="updateStudent" parameterType="com.wgz.entity.Student">
update student_tb set name=#{name},age=#{age},height=#{height},sex=#{sex},birthday=#{birthday} where id=#{id}
</update>
3.测试
private static void updateStudent(IStudentDao studentDao) {
Student student = new Student();
student.setAge(20);
student.setName("zhangsan");
student.setHeight(178);
student.setBirthday(Date.valueOf("2007-02-23"));
student.setId(46);
int num = studentDao.updateStudent(student);
System.out.println("num:"+num);
}
4.获取自增id
- 使用selectKey方式获取
<!--产生自增ID-->
<insert id="saveStudent" parameterType="com.wgz.entity.Student" >
insert into student_tb (name,age,sex,height,birthday)values (#{name},#{age},#{sex},#{height},#{birthday})
<selectKey keyColumn="id" keyProperty="id" resultType="java.lang.Integer" order="AFTER">
select last_insert_id()
</selectKey>
</insert>
useGeneratedKeys=“true” 设置使用自增主键;
keyProperty=“id” 设置自增主键返回字段(用户在插入数据之后获取相应主键);
order=“AFTER” 设置在insert之前执行查询序列操作,然后在insert时候引用查询的序列#{id}
- 使用useGeneratedKeys方式获取
<insert id="saveStudent" parameterType="com.wgz.entity.Student" useGeneratedKeys="true" keyProperty="id" keyColumn="id" >
insert into student_tb (name,age,sex,height,birthday)values (#{name},#{age},#{sex},#{height},#{birthday})
</insert>
测试
/**
* 增加学生
* @param studentDao
*/
private static void addStudent(IStudentDao studentDao) {
Student student = new Student();
student.setAge(19);
student.setName("zhangsan");
student.setHeight(178);
student.setBirthday(Date.valueOf("2007-02-23"));
int num = studentDao.saveStudent(student);
System.out.println("num:"+num);
// 可以得到学生的id
System.out.println("student:"+student);
}
5.模糊查询
- 方式一
1.IStudentDao接口中增加
/**
* 根据名称模糊查询
* @param likeName
* @return
*/
List<Student> findStudentListByName(String likeName);
2.在IStudentDao.xml中增加
<select id="findStudentListByName" parameterType="string" resultType="com.wgz.entity.Student">
select * from student_tb where name like #{likeName}
</select>
3.测试
List<Student> studentList = studentDao.findStudentListByName("%an%");
for (Student student:studentList){
System.out.println(student);
}
- 方式2
修改IStudentDao.xml
<select id="findStudentListByName" parameterType="string" resultType="com.wgz.entity.Student">
select * from student_tb where name like '%${value}%'
</select>
v a l u e 为 s q l 语 句 的 拼 接 , 以 {value} 为sql语句的拼接,以 value为sql语句的拼接,以{value} 的形式获取likeName的值,并拼接,注意${value}必须是value字段
测试
private static void findStudentByName(IStudentDao studentDao) {
List<Student> studentList = studentDao.findStudentListByName("an");
for (Student student:studentList){
System.out.println(student);
}
}
#{}vs${}区别?
#{}是获取参数中的属性值,并讲java中的类型转化为数据库中的类型
为 s q l 语 句 拼 接 , 以 {} 为sql语句拼接,以 为sql语句拼接,以{value} 获取参数中的值
6别名的配置
在mybatis中使用parameterType或者resultType 是必须写全限定名,其实在mybatis已经为我们配置好了一些类型别名,我们也可以自定配置别名
系统别名
在mybatis中TypeAliasRegistry已经为我们配置的默认别名
registerAlias("string", String.class);
registerAlias("byte", Byte.class);
registerAlias("long", Long.class);
registerAlias("short", Short.class);
registerAlias("int", Integer.class);
registerAlias("integer", Integer.class);
registerAlias("double", Double.class);
registerAlias("float", Float.class);
registerAlias("boolean", Boolean.class);
registerAlias("byte[]", Byte[].class);
registerAlias("long[]", Long[].class);
registerAlias("short[]", Short[].class);
registerAlias("int[]", Integer[].class);
registerAlias("integer[]", Integer[].class);
registerAlias("double[]", Double[].class);
registerAlias("float[]", Float[].class);
registerAlias("boolean[]", Boolean[].class);
registerAlias("_byte", byte.class);
registerAlias("_long", long.class);
registerAlias("_short", short.class);
registerAlias("_int", int.class);
registerAlias("_integer", int.class);
registerAlias("_double", double.class);
registerAlias("_float", float.class);
registerAlias("_boolean", boolean.class);
registerAlias("_byte[]", byte[].class);
registerAlias("_long[]", long[].class);
registerAlias("_short[]", short[].class);
registerAlias("_int[]", int[].class);
registerAlias("_integer[]", int[].class);
registerAlias("_double[]", double[].class);
registerAlias("_float[]", float[].class);
registerAlias("_boolean[]", boolean[].class);
registerAlias("date", Date.class);
registerAlias("decimal", BigDecimal.class);
registerAlias("bigdecimal", BigDecimal.class);
registerAlias("biginteger", BigInteger.class);
registerAlias("object", Object.class);
registerAlias("date[]", Date[].class);
registerAlias("decimal[]", BigDecimal[].class);
registerAlias("bigdecimal[]", BigDecimal[].class);
registerAlias("biginteger[]", BigInteger[].class);
registerAlias("object[]", Object[].class);
registerAlias("map", Map.class);
registerAlias("hashmap", HashMap.class);
registerAlias("list", List.class);
registerAlias("arraylist", ArrayList.class);
registerAlias("collection", Collection.class);
registerAlias("iterator", Iterator.class);
registerAlias("ResultSet", ResultSet.class);
自定义别名
在mybatis配置文件sqlMapConfig.xml配置,注意typeAliases要写在environments标签之前
<typeAliases>
<!--声明单个别名 使用时忽略大小写-->
<!-- <typeAlias type="com.wgz.entity.MiddleStudent" alias="middleStudent"></typeAlias>-->
<!--扫描包声明别名-->
<package name="com.wgz.entity"/>
</typeAliases>
0
使用
<select id="findStudentListByName" parameterType="string" resultType="Student">
select * from student_tb where name like '%${value}%'
</select>
- 当sql 语句需要参数 时,就要指定对应 参数类型 parameter(基本类型可以不指定),
当sql语句是查询时 需要指定resultType 增删改返回的的时影响到的行数 不需要指定
7.resultMap 配置结果类型
当实体类中的字段和数据库中的字段不匹配时,我们可以有两种方式解决
- 1.使用sql语句的 as 修改查询结果的名称
- 2.使用resultType,可以实现多个sql语句共用
<resultMap id="studentMap" type="student">
<id property="id" column="id"/>
<result property="name" column="name"/>
<result property="sex" column="sex"/>
<result property="age" column="age"/>
<result property="height" column="height"/>
<result property="birthday" column="birthday"/>
</resultMap>
<select id="findStudentById" parameterType="java.lang.Integer" resultMap="studentMap">
select * from student_tb where id=#{id}
</select>
说明
为sql语句结果的主键与实体类的映射,property为实体类字段,column为数据表主键字段
为普通sql语句字段实体类的属性映射,property为实体类字段,column为数据表主键字段
resultMap=“studentMap” 使用resultMap作为查询结果
8.SqlMapConfig.xml配置文件
SqlMapConfig.xml 中配置的内容和顺序 ,必须为以下顺序,否则会出现错误
<configuration><!--配置-->
<properties/><!--属性-->
<settings/><!--设置-->
<typeAliases/><!--类型别名-->
<typeHandlers/><!--类型处理器-->
<objectFactory/><!--对象工厂-->
<plugins/><!--插件-->
<environments><!--配置环境-->
<environment><!--环境变量-->
<transactionManager/><!--事务管理器-->
<dataSource/><!--数据源-->
</environment>
</environments>
<databaseidProvider/><!--数据库厂商标识-->
<mappers/><!--映射器-->
</configuration>
properties
使用properties作为数据库资源配置
<properties resource="jdbc.properties"/>
<typeAliases>
<!--声明单个别名 使用时忽略大小写-->
<!-- <typeAlias type="com.wgz.entity.MiddleStudent" alias="middleStudent"></typeAlias>-->
<!--扫描包声明别名-->
<package name="com.wgz.entity"/>
</typeAliases>
<!--配置mybatis环境-->
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC"></transactionManager>
<!--配置数据源-->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
jdbc.properties配置文件
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/szqy08
jdbc.username=root
jdbc.password=123456
typeAliases别名
<typeAliases>
<!--声明单个别名 使用时忽略大小写-->
<!-- <typeAlias type="com.wgz.entity.MiddleStudent" alias="middleStudent"></typeAlias>-->
<!--扫描包声明别名-->
<package name="com.wgz.entity"/>
</typeAliases>
mappers映射器配置
<mappers>
<!--在map 中声明 映射文件 两种方式 -->
<!--方式一:resource声明xml-->
<!-- <mapper resource="com/wgz/dao/IStudentDao.xml"></mapper>-->
<!--方式二:class 声明类名-->
<!--<mapper class="com.wgz.dao.IStudentDao"></mapper>-->
<!-- <mapper class="com.wgz.dao.IStudentDao2"/>
<mapper class="com.wgz.dao.IMiddleStudentDao"></mapper>-->
<!--方式三:扫描包名-->
<package name="com.wgz.dao"/>
</mappers>
mapUnderscoreToCamelCase 开启驼峰映射
<!-- 开启驼峰映射 ,为自定义的SQL语句服务-->
<!--设置启用数据库字段下划线映射到java对象的驼峰式命名属性,默认为false
user_name ---userName
-->
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<!--
多请求参数时:
parameterType 可以不写
参数较少
findStudentByAgeAndSex(int age,String sex) 配置文件 select * from student_tb where age >= #{arg0} and sex = #{arg1}
select * from student_tb where age >= #{param1} and sex = #{param2}
findStudentByAgeAndSex(@Param("age") int age,@Param("sex") String sex);
配置文件 select * from student_tb where age >= #{age} and sex = #{sex}
多参数
1.将参数封装为 实体类
2.将参数封装为map
List<Student> findStudentByAgeAndSexMap(Map<String,Object> map);
配置文件 select * from student_tb where age >= #{age} and sex = #{sex}
-->
<select id="findStudentByAgeAndSex" resultType="student">
select * from student_tb where age >= #{age} and sex = #{sex}
</select>
<select id="findStudentByAgeAndSexMap" resultType="student">
select * from student_tb where age >= #{age} and sex = #{sex}
</select>