JavaEE Day05 Mybatis
Day05 Mybatis
目录
软件开发三层架构
sun提出分层开发(经典三层)
表示层
与用户进行交互的组件和容器组成。
实现:Servlet
框架:action/web
业务逻辑层
由业务处理组件构成。
实现:Service/biz
框架:srping framwork
数据持久层
实现与数据库直接交互。
实现:Jdbc dao
框架:mybatis/hibernate
什么是框架
将重复性的,繁琐的内容封装起来一套程序,是开发人员能够将更多的精力放在业务分析和理解上;
框架的好处
- 简化开发(配置)
- 屏蔽细节
- 提高开发效率
传统jdbc的不足
- 驱动注册和连接获取硬编码问题(配置文件)
- 赋值和结果封装繁琐(反射 orm)
- 频繁的打开和释放连接消耗资源(连接池)
什么是mybatis
-
mybatis是一款有效的持久层框架,
-
mybatis需要关注sql,输入参数和输出结果的映射
-
mybatis是一个orm框架
orm:对象关系映射,解决面向对象编程蘑菇型和关系型数据库模型之间的映射问题。
入门案例
准备工作
需要jar:mysql驱动包,mybatis相关jar
- apache项目:ibatis
- 移植google code:mybatis
- github:开源软件托管平台
- 下载:https://github.com/mybatis/mybatis-3/releases
- 如果需要查看mybatis的debug信息,则需要log4j-1.2.17.jar(一般位于mybatis目录的lib目录下,是mybatis的日志程序),另外将log4j.properties配置文件导入到配置中即可;
log4j.properties
# Global logging configuration
log4j.rootLogger=DEBUG, stdout
# MyBatis logging configuration...
log4j.logger.org.mybatis.example=DEBUG
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
创建实体类
在src下创建pojo程序包,在程序包中创建对应的实体类,
package pojo;
public class UserInfo {
private int uid;
private String username;
private String password;
public int getUid() {
return uid;
}
public void setUid(int uid) {
this.uid = uid;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "UserInfo{" +
"uid=" + uid +
", username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
编写java项目
两种配置文件
-
创建在项目目录下创建源码目录(ecplise中,是source folder,idea中创建普通目录,然后在modules中修改)
-
全局配置:四个参数(连接池) 事务管理
<?xml version="1.0" encoding="UTF-8"?> <!-- xml描述文件:dtd/schema(约束标签) --> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <!--加载外部属性文件--> <properties resource="java.properties"> <!--<property name="" value=""/>--> </properties> <!-- 类型别名 --> <typeAliases> <!-- 单个类型别名 --> <!--<typeAlias type="pojo.UserInfo" alias="UserInfo"></typeAlias>--> <!-- 批量级别 :别名就是类型,不区分大小写--> <package name="pojo"/> </typeAliases> <!-- 环境 context :复数 mysql、oracle、db2 本地环境 预上线平台 线上环境 default: 默认使用环境 --> <environments default="development"> <!-- 环境:id:唯一标识 --> <environment id="development"> <!-- 事务管理器 :JDBC --> <transactionManager type="JDBC"/> <!-- 数据源:连接池(存储的连接) dpcp/c3p0/droid/jdbcTemplate --> <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> <mappers> <mapper resource="UserMapper.xml"/> </mappers> </configuration> -
映射配置:定制化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"> <!-- namespace:命名空间(字符串) 隔离sql --> <mapper namespace="adhs"> <!-- <insert id=""></insert> <update id=""></update> <delete id=""></delete> --> <!-- 根据uid查询userinfo的对象 一个标签代表一个Statement对象 #{}:代表占位符 关键字:输入参数类型 简单类型:可任意 对象:属性名称 id:标签的唯一标识 parameterType:输入参数的类型(可选) resultType:输出结果类型 --> <select id="selectUser" resultType="UserInfo"> select * from userinfo where uid = #{uid} </select> </mapper>
读取配置运行测试
- SqlSession:面向开发者的接口。提供发送sql命令的方法
- SqlSessionFactory:session工厂,创建和管理session对象。
package test;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import pojo.UserInfo;
import java.io.IOException;
import java.io.Reader;
public class Test {
public static void main(String[] args) throws IOException{
// 读取配置文件
Reader reader = Resources.getResourceAsReader("mybatis.xml");
SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(reader);
// 发送定制化sql
SqlSession session = ssf.openSession();
UserInfo info = session.selectOne("adhs.selectUser", 1);
System.out.println(info);
session.close();
}
}
增删改查案例
mybaties中 默认将autocommit关闭了,所以插入,修改和删除的操作,默认都是不成功的,为了开启autocommit,有两种方法:
- 直接在opensssion中设置true属性(查看源码,idea快捷点 ctrl+alt+B 查看所有的继承类;)
- 直接手工事务提交;
注意: 如果传入的参数是对象类,那么#{}里面的参数,就是属性名;
UserMapper.xml
<?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">
<!-- namespace:命名空间(字符串)
隔离sql
-->
<mapper namespace="adhs">
<!-- <insert id=""></insert>
<update id=""></update>
<delete id=""></delete> -->
<!-- 根据uid查询userinfo的对象
一个标签代表一个Statement对象
#{}:代表占位符
关键字:输入参数类型
简单类型:可任意
对象:属性名称
id:标签的唯一标识
parameterType:输入参数的类型(可选)
resultType:输出结果类型(单个结果的类型)
-->
<select id="selectUser" resultType="UserInfo">
select * from userinfo where uid = #{uid}
</select>
<!-- 查询所有 -->
<select id="selectAll" resultType="userinfo">
select * from userinfo;
</select>
<!-- 模糊查询 String
${}:表示连接"+"
关键字:与输入参数类型有关
简单类型:value
对象类型:属性名称
-->
<select id="selectLikeName" resultType="userinfo">
select * from userinfo where username like "%${value}%"
</select>
<!-- 插入数据 输入参数是对象,因此在调用#{}时,写属性名称-->
<insert id="insert">
insert into userinfo(username,password) values(#{username},#{password})
</insert>
<update id="update">
update userinfo set username=#{username},password=#{password} where uid=#{uid}
</update>
<delete id="delete">
delete from userinfo where uid=#{uid}
</delete>
</mapper>
测试代码:
package test;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import pojo.UserInfo;
import java.io.IOException;
import java.io.Reader;
import java.util.List;
public class Test {
public static void main(String[] args) throws IOException{
// 读取配置文件
Reader reader = Resources.getResourceAsReader("mybatis.xml");
SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(reader);
// 发送定制化sql
SqlSession session = ssf.openSession();
// 自动事务提交
// SqlSession session = ssf.openSession(true);
/* UserInfo info = session.selectOne("adhs.selectUser", 1);
System.out.println(info);*/
// List<UserInfo> users = session.selectList("adhs.selectAll");
/*List<UserInfo> users = session.selectList("adhs.selectLikeName", "s");
System.out.println(users.toString());*/
UserInfo info = new UserInfo();
info.setUid(7);
info.setUsername("zl");
info.setPassword("567");
// int rows = session.insert("adhs.insert", info);
// int rows = session.update("adhs.update",info);
int rows = session.delete("adhs.delete",7);
// 手动事务提交
session.commit();
System.out.println(rows);
session.close();
}
}
mapper代理实现dao的开发
mapper的接口+mapper映射
要求:
- mapper接口和mapper映射同包同名(注册映射方便)
- mapper映射文件的namespace和接口的完全限定名保持一致
- 标签的id和方法的名称保持一致
- 标签的输入参数类型和方法的参数类型一致
- 标签的输出结果类型(单个类型)和方法的返回值类型一致;
目录结构
.
├─config
│ ├─java.properties
│ ├─log4j.properties
│ └─mybatis.xml
├─lib
│ ├─log4j-1.2.17.jar
│ ├─mybatis-3.4.6.jar
│ └─mysql-connector-java-5.1.45-bin.jar
├─bin
└─src
├─mapper
│ ├─UserMapper.java
│ └─UserMapper.xml
├─pojo
│ └─UserInfo.java
└─test
└─Test.java
mybatis.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- xml描述文件:dtd/schema(约束标签) -->
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--加载java属性文件-->
<properties resource="java.properties"></properties>
<!-- 类型别名 -->
<typeAliases>
<package name="pojo"/>
</typeAliases>
<!-- 配置环境 -->
<environments default="dev">
<!-- 环境:id:唯一标识 -->
<environment id="dev">
<!-- 事务管理器 :JDBC -->
<transactionManager type="JDBC"/>
<!-- 数据源:连接池(存储的连接) dpcp/c3p0/droid/jdbcTemplate -->
<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>
<mappers>
<!--批量注册映射文件:mapper接口和映射文件必须同包同名 -->
<package name="mapper"/>
</mappers>
</configuration>
UserMapper.java
package mapper;
import pojo.UserInfo;
import java.util.List;
public interface UserMapper {
List<UserInfo> queryAll();
UserInfo queryById(int uid);
}
UserMapper.xml
<?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="mapper.UserMapper">
<select id="queryAll" resultType="userinfo" >
select * from userinfo
</select>
<select id="queryById" resultType="userinfo">
select * from userinfo where uid = #{uid};
</select>
</mapper>
使用注解
也就是不用写UserMapper.xml,修改UserMapper.java即可
package mapper;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Update;
import pojo.UserInfo;
import java.util.*;
import org.apache.ibatis.annotations.Select;
public interface UserMapper {
@Select("select * from userinfo")
List<UserInfo> queryAll();
@Select("select * from userinfo where uid=#{uid}")
UserInfo queryById(int uid);
@Insert("insert into userinfo(username,password) values(#{username},#{password})")
int insert(UserInfo info);
@Update("update userinfo set username=#{username},password=#{passwrod} where uid=#{uid}")
int update(UserInfo info);
@Delete("delete from userinfo where uid=#{uid} ")
int delete(int uid);
}
高级映射
一对多问题
resultType特点:
- 结果集 中的字段名称和类属性名称完全一致,此时将映射成功。
- 结果集中的字段名称和类属性名称部分一致,部分映射成功-可以在sql中起别名解决;
- 结果集中的字段名称和雷属性的名称完全不一致,此时不会创建对象
emp实体
package pojo;
import java.math.BigDecimal;
import java.sql.Date;
public class Emp {
private int empno;
private String ename;
private String job;
private int mgr;
private java.sql.Date hiredate;
private BigDecimal sal;
private BigDecimal comm;
private int deptno;
private Dept dept;
public Dept getDept() {
return dept;
}
public void setDept(Dept dept) {
this.dept = dept;
}
public int getEmpno() {
return empno;
}
public void setEmpno(int empno) {
this.empno = empno;
}
public String getEname() {
return ename;
}
public void setEname(String ename) {
this.ename = ename;
}
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
public int getMgr() {
return mgr;
}
public void setMgr(int mgr) {
this.mgr = mgr;
}
public Date getHiredate() {
return hiredate;
}
public void setHiredate(Date hiredate) {
this.hiredate = hiredate;
}
public BigDecimal getSal() {
return sal;
}
public void setSal(BigDecimal sal) {
this.sal = sal;
}
public BigDecimal getComm() {
return comm;
}
public void setComm(BigDecimal comm) {
this.comm = comm;
}
public int getDeptno() {
return deptno;
}
public void setDeptno(int deptno) {
this.deptno = deptno;
}
@Override
public String toString() {
return "Emp{" +
"empno=" + empno +
", ename='" + ename + '\'' +
", job='" + job + '\'' +
", mgr=" + mgr +
", hiredate=" + hiredate +
", sal=" + sal +
", comm=" + comm +
", deptno=" + deptno +
", dept=" + dept +
'}';
}
}
dept实体
package pojo;
import java.util.List;
public class Dept {
private int deptno;
private String dname;
private String loc;
private List<Emp> emps;
public int getDeptno() {
return deptno;
}
public void setDeptno(int deptno) {
this.deptno = deptno;
}
public String getDname() {
return dname;
}
public void setDname(String dname) {
this.dname = dname;
}
public String getLoc() {
return loc;
}
public void setLoc(String loc) {
this.loc = loc;
}
public List<Emp> getEmps() {
return emps;
}
public void setEmps(List<Emp> emps) {
this.emps = emps;
}
@Override
public String toString() {
return "Dept{" +
"deptno=" + deptno +
", dname='" + dname + '\'' +
", loc='" + loc + '\'' +
", emps=" + emps +
'}';
}
}
resultMap(orm)
使用collection标签, ofType属性;
查询dept表中所有员工和所在部门
DeptMapper.java
package mapper;
import pojo.Dept;
import java.util.List;
public interface DeptMapper {
List<Dept> findDeptAndEmps();
}
DeptMapper.xml
<?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="mapper.DeptMapper">
<!--id:唯一标识 type:封装类型 -->
<resultMap type="dept" id="deptMap">
<!-- 主键字段的映射 property:属性名称 column:结果集中字段名称-->
<id property="deptno" column="deptno"/>
<result column="dname" property="dname"/>
<result column="loc" property="loc"/>
<!-- 将表中数据封装到集合中 ofType:集合中的类型 -->
<collection property="emps" ofType="emp" column="deptno">
<id property="empno" column="empno"/>
<result column="ename" property="ename"/>
<result column="job" property="job"/>
<result column="mgr" property="mgr"/>
<result column="hiredate" property="hiredate"/>
<result column="sal" property="sal"/>
<result column="comm" property="comm"/>
<result column="deptno" property="deptno"/>
</collection>
</resultMap>
<select id="findDeptAndEmps" resultMap="deptMap">
select * from dept left join emp on dept.deptno = emp.deptno
</select>
</mapper>
一对一问题
使用association 标签,javaType属性
EmpMapper.java
package mapper;
import pojo.Emp;
import java.util.List;
public interface EmpMapper {
List<Emp> findEmpAndDept();
}
EmpMapper.xml
<?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="mapper.EmpMapper">
<!-- id: 唯一标识, type:封装的类型-->
<resultMap id="empMap" type="emp">
<!-- 主键字段的映射 property:属性名称 column:结果集中的字段名称 -->
<id property="empno" column="empno"/>
<result column="ename" property="ename"/>
<result column="job" property="job"/>
<result column="mgr" property="mgr"/>
<result column="hiredate" property="hiredate"/>
<result column="sal" property="sal"/>
<result column="comm" property="comm"/>
<result column="deptno" property="deptno"/>
<!--将结果封装到对象中-->
<association property="dept" column="deptno" javaType="dept">
<id property="deptno" column="deptno"/>
<result column="dname" property="dname"/>
<result column="loc" property="loc"/>
</association>
</resultMap>
<select id="findEmpAndDept" resultMap="empMap" >
select * from emp left join dept
on dept.deptno = emp.deptno
</select>
</mapper>
测试代码
package test;
import mapper.DeptMapper;
import mapper.EmpMapper;
import mapper.UserMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.Reader;
public class Test {
public static void main(String[] args) {
Reader reader = null;
try {
reader = Resources.getResourceAsReader("mybatis.xml");
SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(reader);
SqlSession session = ssf.openSession();
// DeptMapper mapper = session.getMapper(DeptMapper.class);
// System.out.println(mapper.findDeptAndEmps());
EmpMapper mapper = session.getMapper(EmpMapper.class);
System.out.println(mapper.findEmpAndDept());
session.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}


浙公网安备 33010602011771号