myBatis是一个小巧玲珑的orm框架,使用myBatis前应该先创建数据库和表,然后在写对应的Javabean和映射文件。
使用myBatis前准备:
1.所需的jar包包括:【必须】
mybatis-3.2.0.jar
asm-3.3.1.jar
cglib-2.2.2.jar
commons-logging-1.1.1.jar
javassist-3.17.1-GA.jar
log4j-1.2.17.jar
slf4j-api-1.7.2.jar
slf4j-log4j12-1.7.2.jar
mybatis-3.2.0-javadoc.jar
mybatis-3.2.0-sources.jar
mysql-connector-java-5.1.7-bin.jar
2.在官方案例中拷贝一个log4j.properties配置文件到src下,日志文件【必须】
3.在官方案例中拷贝一个Configuration.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">
<configuration>
<typeAliases>
<!--
别名:
给类com.mxf.bean.User设置一个别名 ‘User’,以后再使用到 com.mxf.bean.User的时候都可以使用别名
-->
<typeAlias type="com.mxf.bean.User" alias="User"/>
</typeAliases>
<environments default="development">
<environment />
</mappers>
</configuration>
1.HelloWorld第一个程序
1.1 在前期准备工作做完以后,开始写我们的Javabean,和hibernate一样,要与数据库基本对应:
public class User implements Serializable{
private static final long serialVersionUID = 1L;
private int id;
private String userName;
private String userAddress;
private int userAge;
此处省略get、set方法
}
1.2 Javabean对应的数据库表
Create Table
CREATE TABLE `user` (
`id` int(11) NOT NULL auto_increment,
`username` varchar(50) default NULL,
`userage` int(11) default NULL,
`useraddress` varchar(200) default NULL,
PRIMARY KEY (`id`)
)
1.3 做好前几步后,我们需要创建UserMapper.xml(Javabean对应的配置文件,该配置文件主要写对数据库的操作(SQL语句))
<?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.mxf.mapper.UserMap"><!--如果采用接口编程,命名空间就是接口的全路径 -->
<!--
resultType="User"中的User表示别名,见Configuration.xml中的别名配置
parameterType="int" 参数类型,指sql语句中的参数 id
-->
<select >
select * from user where id = #{id}
</select>
</mapper>
该配置文件要在Configuration.xml中声明,如果不声明,程序找不到Javabean和Javabean对应的映射文件,就无法操作数据库
1.4 验证配置信息是否正确
1.4.1 创建工具类
package com.mxf.dao;
public class MybatisUtil {
private InputStream in;
private static SqlSessionFactory sqlSessionFactory = null;
private static MybatisUtil instance = null;
private MybatisUtil() {
try {
in = Resources.getResourceAsStream("Configuration.xml");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static MybatisUtil getInstance() {
if (null == instance) {
instance = new MybatisUtil();
}
return instance;
}
public SqlSession getSession(){
return sqlSessionFactory.openSession();
}
public void closeSession(SqlSession session){
if(null!=session){
session.close();
}
}
}
因为程序运行需要加载Configuration.xml来获得SqlSessionFactory,才能得到SqlSession来操作数据库,并且SqlSessionFactory是一个重量级的SqlSession
的工厂,所以程序中只保留一个即可,故采用单例模式
1.4.2 myBatis提倡接口编程,这样会非常方便。所以我们来为User对数据库的操作来创建一个接口
因为接口和User的映射文件有某种特殊关系,所以我们为接口取名为UserMap.java(一般情况下我们将UserMapper.xml和UserMap.java放在一个包内进行管理)
接口内的代码:
package com.mxf.mapper;
import com.mxf.bean.User;
public interface UserMap {
/**
* UserMapper.xml文件中的id对应接口中的 方法名;
* parameterType对应接口方法中的参数 id;
* resultType对应接口中的返回值User
* <select >
*
* @param id
* @return
*/
public User selectUserById(int id);
}
1.4.3 验证信息:
package com.mxf.test;
/**
* 面向接口编程
* @author mxf
*
*/
public class Test2 {
public static void main(String[] args) throws IOException {
SqlSession session = MybatisUtil.getInstance().getSession();
//获取接口
UserMap map = session.getMapper(UserMap.class);//将接口的字节码给getMapper
//执行接口中的方法,因为接口中的方法和映射文件相对应
User user = map.selectUserById(1);
System.out.println(user.getUserName() + "\t" + user.getUserAge());
MybatisUtil.getInstance().closeSession(session);
}
}
这样我们就能轻松查询到数据库的指定信息了
1.50 总结
从HelloWorld就可以看出为什么myBatis为什么这么受人们青睐了。
1.小巧
2.程序员任意写SQL来操作数据库
3.相比hibernate工作量相对小一点
2.增删改查
2.1 查找
2.1.1 查询全部信息
<!-- id和映射文件对应的接口的方法名相同 -->
<select >
delete from user where
id=#{id}
</delete>
参数类型User mybatis会到User类中查找值并赋给id
该删除语句对应的接口方法:
public void deleteUserById(User user);
测试代码:
User user = new User();
user.setId(4);
usermap.deleteUserById(user );
3.表之间的关联关系
3.1 一对一
我们选择Person(人)和Idcard(身份证)来完成一对一的关联关系
数据库表:
Create Table
CREATE TABLE `idcard` (
`id` int(11) NOT NULL auto_increment,
`idnum` varchar(20) character set utf8 default NULL,
PRIMARY KEY (`id`)
)
Create Table
CREATE TABLE `person` (
`id` int(11) NOT NULL auto_increment,
`age` int(11) default NULL,
`name` varchar(20) character set utf8 default NULL,
`idcard` int(11) default NULL,
PRIMARY KEY (`id`),
KEY `person_fk` (`idcard`),
CONSTRAINT `person_fk` FOREIGN KEY (`idcard`) REFERENCES `idcard` (`id`)
)
数据表对应的Java实体类:
public class Idcard implements Serializable{
private static final long serialVersionUID = 1L;
private int cid;
private String idnum;
省略get、set方法
}
public class Person implements Serializable{
private static final long serialVersionUID = 1L;
private int pid;
private String name;
private int age;
private Idcard idcard;
省略get、set方法
}
由实体类和数据库表可以看出,表idcard为主表,person为从表
3.1.1 一对一查询 (注意SQL语句的面向对象传入参数)
mybatis中没有级联的概念,所以在表与表关联关系操作的时候是这样实现的:
表A对应的实体类写自己的SQL操作A;
表B对应的实体类写自己的SQL操作B;
它们之间的联系在于外键,外键不能实现级联操作。
PersonMapper.xml内的配置:
****第一种通过person查出所有人包括idcard的办法
<!-- 查询所有人 -->
<select >
select p.id,p.name,p.age,p.idcard from person p,idcard c where p.idcard=c.id
</select>
<select >
delete from idcard where id=#{cid}面向对象操作
</delete>
测试代码:
Idcard idcard = new Idcard();
idcard.setCid(12);
Person person = new Person();
person.setIdcard(idcard);
personMap.deletePerson(person);要先删除person,后删除idcard
personMap.deleteIdcard(idcard);
3.2 一对多
数据库表:部门表、雇员表
部门表:
Create Table
CREATE TABLE `department` (
`deptid` int(11) NOT NULL auto_increment,
`deptname` varchar(20) character set utf8 NOT NULL default '',
PRIMARY KEY (`deptid`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=gbk
雇员表:
Create Table
CREATE TABLE `employee` (
`empid` int(11) NOT NULL auto_increment,
`empname` varchar(20) character set utf8 NOT NULL default '',
`deptid` int(11) NOT NULL,
PRIMARY KEY (`empid`),
KEY `deptid` (`deptid`),
CONSTRAINT `employee_fk` FOREIGN KEY (`deptid`) REFERENCES `department` (`deptid`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=gbk
对应实体类:
public class Department {
private int deptId;
private String deptName;
private Set<Employee> emps;
}
public class Employee {
private int empId;
private String empName;
private Department department;
}
部门和雇员的关系是一对多的关系。下面来看对部门表的映射文件的操作。
查询:
<resultMap type="Department" );
e2.setDepartment(d1);
departmentMap.addDept(d1);
departmentMap.addEmp(e1);
departmentMap.addEmp(e2);
在添加数据的时候要注意添加的先后数据。
3.3 多对多
用户和组是多对多的关系:
经过分析,数据库表应该设计为:用户表(user)、组信息表(group_info)、用户组组合表(user_group);
user_group为辅助表,不需要设置主键。详细信息:
Create Table
CREATE TABLE `user` (
`id` int(11) NOT NULL auto_increment,
`name` varchar(40) default NULL,
`password` varchar(20) default NULL,
`createtime` timestamp NULL default CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
)
Create Table
CREATE TABLE `group_info` (
`id` int(11) NOT NULL auto_increment,
`name` varchar(40) default NULL,
`createdate` timestamp NULL default CURRENT_TIMESTAMP,
`state` int(1) default '0' COMMENT '0:可见;1:不可见',
PRIMARY KEY (`id`)
)
CREATE TABLE `user_group` (
`user_id` int(11) NOT NULL,
`group_id` int(11) NOT NULL,
`createdate` timestamp NULL default CURRENT_TIMESTAMP,
KEY `FK_user_group_user_id` (`user_id`),
KEY `FK_user_group_group_id` (`group_id`),
CONSTRAINT `FK_user_group_group_id` FOREIGN KEY (`group_id`) REFERENCES `group_info` (`id`),
CONSTRAINT `FK_user_group_user_id` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`)
)
3.3.1 插入操作
<!-- 插入 -->
<insert >
<![CDATA[
select g.id as groupId,g.name as groupName,u.id as userId,u.name as userName from group_info g
INNER JOIN user_group ug on g.id = ug.group_id
INNER JOIN user u on ug.user_id=u.id where g.id=#{id};
]]>
</select>
4.注解
注解完成单表的CRUD,mybatis的注解是写在接口上的,这样比较方便开发,不用来回切换文件,还有就是避免了接口和XML文件中的id名相同等问题。
不过,即使使用注解,*Mapper.xml文件还是要配置在Configuration.xml中的。因为后面有一对多的注解操作,如果返回值为集合的时候,
使用注解不太方便,将集合的映射关系配置在XML文件中比较方便,不容易出错。
********使用注解的时候要小心SQL语句内的参数的正确性!!
【注意】:
使用注解前,应当先把接口配置在Configuration.xml中,如下:
<mappers>
<mapper resource="com/mxf/mapper/UserMapper.xml" />
<mapper class="com.mxf.mapper.UserMap"/> ***
</mappers>
4.1.1 添加:
@Insert("INSERT into user(name,password) values(#{userName},#{password})")
@Options(useGeneratedKeys=true,keyProperty="userId")
public void addUser(User user);
注意:keyProperty、values内的参数应该和对象的属性名保持一致
4.1.2 删除:
@Delete("delete from user where id=#{userId}")
public void deleteUserById(@Param("userId")int userId);
注意:SQL中id的参数名称应该和@Param("userId")内的参数名保持一致
4.1.3 更新:
@Update("update user set name=#{userName},password=#{password} where id =#{userId}")
public void updateUser(User user);
4.1.4 查询所有人:
@Select("select id as userId,name as userName from user")
public List<User> selectAllUser();
注意:select id as userId,name as userName from user 如果select语句中的id as userId,name as userName不这样写,查询不出来数据,null
查询中要求和属性名相同
4.1.5 分页查询:
@Select("select u.id as userId,u.name as userName,u.password as password from user u where u.name like #{user.userName} LIMIT #{firstResult},#{maxResult}")
public List<User> selectUser(@Param("user") User user,
@Param("firstResult") int firstResult,
@Param("maxResult") int maxResult);