目录
概念
Mybatis是解决数据的持久化问题的框架。开发者只需要关注sql语句本身,不需要花费精力去加载驱动、创建连接等繁杂的过程。
该框架采用了ORM思想解决了实体和数据库的映射问题,对jdbc进行封装,屏蔽了jdbc api底层访问细节,是我们不用与jdbc api打交道,就可以完成对数据库的持久化操作。
总结:Mybatis框架可以替你完成dao层实现类的编写
Mybatis的特点
- 在总配置文件中配置数据连接池,使用连接池管理数据库连接,从而提高了性能
- 实现了SQL语句和Java代码的分离,可以更好的维护
- Mybatis自动将java对象映射到SQL语句中,通过parameterType属性确定输入内容
- Mybatis自动将SQL执行结果映射到java对象中。通过resultType属性确定输出结果的类型
Mybatis 的原理
自定义Mybatis
具体流程思路
- 读取配置文件,将数据封装至Configuration核心对象中(连接的四个信息,sql语句,语句返回类型)
- 创建者类SqlSessionFactoryBuilder 通过buid方法创建工厂类SqlSessionFactory对象
- SqlSessionFactory对象通过方法openSession方法创建SqlSession对象
- SqlSession对象:创建代理对象
- 通过传入的核心类,可以对数据库进行连接,并且可以对其接口的方法进行增强
Mybatis入门
总配置文件:SqlMapConfig.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--Mybatis-->
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 默认环境id-->
<environments default="mysql">
<environment id="mysql">
<!-- 配置事务-->
<transactionManager type="JDBC"/>
<!-- 配置连接池-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///db_6"/>
<property name="username" value=""/>
<property name="password" value=""/>
</dataSource>
</environment>
</environments>
<!-- 配置映射文件的位置-->
<mappers>
<mapper resource="dome1/UserMapper.xml"/>
</mappers>
</configuration>
映射配置文件
<?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=dao层接口的全限定类名-->
<mapper namespace="dome1.dao.Iuser">
<!-- id=方法名 resultType=返回值的全限定类名 -->
<select id="findAll" resultType="dome1.dmain.user">
select * from user2
</select>
</mapper>
接口
public interface Iuser {
List<user>findAll();
}
测试代码
public static void main(String[] args) throws IOException {
// 读取配置文件
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
// 创建SqlSessionFactory的创建者对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
// 使用创建者对象创建工厂对象
SqlSessionFactory factory = builder.build(in);
// 使用工厂对象生产SqlSession对象
SqlSession sqlSession = factory.openSession();
// 使用sqlsession对象 创建dao接口的代理对象
Iuser mapper = sqlSession.getMapper(Iuser.class);
List<user> all = mapper.findAll();
System.out.println(all);
// 释放资源
sqlSession.close();
in.close();
}
案例:实现数据库的增删改查
接口
public interface Iuser {
// 增
void add(user user);
// 删
void delete(int id);
// 修改(更新)
void update(user user);
// 查询:查询所有
List<user> findAll();
// 查询:根据id进行查询
user findById(int id);
// 查询:根据name进行模糊查询
List<user> findByNameLike(String name);
// 查询一共多少条记录
int count();
}
映射配置文件
<?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=dao层接口的全限定类名-->
<mapper namespace="dome1.dao.Iuser">
<insert id="add" parameterType="dome1.dmain.user">
insert into test_dao(username,password) values (#{username},#{password})
</insert>
<delete id="delete" parameterType="java.lang.Integer">
delete from test_dao where id=#{uid}
</delete>
<update id="update" parameterType="dome1.dmain.user">
update test_dao set username=#{username},password=#{password} where username=#{username}
</update>
<select id="findAll" resultType="dome1.dmain.user">
select * from test_dao
</select>
<select id="findById" parameterType="java.lang.Integer" resultType="dome1.dmain.user">
select * from test_dao where id=#{uid}
</select>
<select id="findByNameLike" parameterType="java.lang.String" resultType="dome1.dmain.user">
select * from test_dao where username like #{uname}
</select>
<select id="count" resultType="java.lang.Integer">
select count(id) from test_dao
</select>
</mapper>
模糊查询两种方法
1、#{}:使用的是预编译方式 动态执行sql语句
<select id="findByNameLike" parameterType="java.lang.String" resultType="dome1.dmain.user">
select * from test_dao where username like #{uname}
</select>
2、${value}:使用的是字符串拼接的方式,执行sql语句
在使用的时候,直接传入文字即可
<select id="findByNameLike" parameterType="java.lang.String" resultType="dome1.dmain.user">
select * from test_dao where username like '%${value}%'
</select>
返回新增用户的id
<insert id="add" parameterType="dome1.dmain.user">
<selectKey keyColumn="id" keyProperty="id" resultType="int">
select last_insert_id()
</selectKey>
insert into test_dao(username,password) values (#{username},#{password})
</insert>
参数深入
parameterType配置参数
parameterType:传入基本数据类型、引用类型、POJO类、实体类的包装类,在sql语句使用的是#{}字符,使用的是ognl表达式
ognl表达式:语法就是#{对象.对象}
例如:#{user.name}先找到user对象,然后在user对象中找到name属性,并调用getName(),我们在parameterType属性上指定了实体类名称,所以可以省略user. 直接写成#{name}即可
传递POJO包装对象(POJO类中包含POJO)
POJO类
public class Peoper {
private user user;
public dome1.dmain.user getUser() {
return user;
}
public void setUser(dome1.dmain.user user) {
this.user = user;
}
}
接口方法
// 实体类的包装对象作为参数
List<user> findByName_Peoper(Peoper peoper);
映射配置文件
<select id="findByName_Peoper" parameterType="dome1.dmain.Peoper" resultType="dome1.dmain.user">
select * from test_dao where username like #{user.username}
</select>
resultType配置结果类型
该属性支持基本类型、实体类型
参照上方的代码即可
特殊情况:实体类的属性名称与数据库列名不符(2种解决方法)
1、在SQL语句中加别名 给数据表的列名通过设置别名的方法改成实体类的属性名
<select id="findAll" resultType="dome1.dmain.user1">
select id,username as name,password as pwd from test_dao
</select>
2、使用resultMap标签
功能:当列名和属性名不一致时建立对应关系,从而实现封装
<resultMap id="result" type="dome1.dmain.user1">
<!-- 设置主键的方法-->
<!-- <id column="" property=""/>-->
<result column="username" property="name"/>
<result column="password" property="pwd"/>
</resultMap>
<select id="findAll" resultMap="result">
select * from test_dao
</select>
Mybatis传统的DAO层开发
接口实现类:daoimpl
public class userimpl implements Iuser {
private SqlSessionFactory factory;
//通过工厂类对象创建这个是实现类
public userimpl(SqlSessionFactory factory) {
this.factory = factory;
}
public void add(user user) {
SqlSession sqlSession = factory.openSession();
sqlSession.insert("dome1.dao.Iuser.add", user);
sqlSession.commit();
sqlSession.close();
}
public void delete(int id) {
SqlSession sqlSession = factory.openSession();
sqlSession.delete("dome1.dao.Iuser.delete",id);
sqlSession.commit();
sqlSession.close();
}
public void update(user user) {
SqlSession sqlSession = factory.openSession();
sqlSession.update("dome1.dao.Iuser.update",user);
sqlSession.commit();
sqlSession.close();
}
public List<user> findAll() {
SqlSession sqlSession = factory.openSession();
List<user> userList = sqlSession.selectList("dome1.dao.Iuser.findAll");
return userList;
}
public user findById(int id) {
SqlSession sqlSession = factory.openSession();
user user = sqlSession.selectOne("dome1.dao.Iuser.findById", id);
return user;
}
}
映射文件与上个案例相同
测试代码
public class t1 {
private InputStream in;
private Iuser iuser;
@Before
public void init() throws IOException {
in = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
iuser = new userimpl(factory);
}
@After
public void after() throws IOException {
in.close();
}
@Test
public void add(){
user user = new user();
user.setUsername("赵六");
user.setPassword("123");
iuser.add(user);
}
@Test
public void delete(){
iuser.delete(1);
}
@Test
public void update(){
user user = new user();
user.setUsername("tony");
user.setPassword("111111");
iuser.update(user);
}
@Test
public void findall(){
System.out.println(iuser.findAll());
}
@Test
public void findid(){
System.out.println(iuser.findById(3));
}
}
结论:这种传统的开发方式及其繁琐,推荐使用接口的方式实现,Mybatis会替咱创建dao层实现类,Mybatis实现的方式也是调用SqlSession对象的方法来实现的。
SqlMapConfig.xml配置文件
配置的内容及其顺序
properties属性
<properties resource="jdbc.properties"/>
<!-- 默认环境id-->
<environments default="mysql">
<environment id="mysql">
<!-- 配置事务-->
<transactionManager type="JDBC"/>
<!-- 配置连接池-->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.name}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
URL:统一资源定位符
格式: 协议 主机 端口号 URI
例如:http://localhost:8080/a/as.html
typeAliases:类型别名
<typeAliases>
<!-- 单个别名定义-->
<typeAlias type="dome1.dmain.user" alias="user"/>
<!-- 批量别名定义,扫描整个包下的类,别名为类名-->
<package name="dome1.dmain"/>
</typeAliases>
mappers:映射器
<mapper resource=""/>:指定相对于类路径的xml资源
<mapper class=""/>:适用于注解的方式
<package name=""/>:注册包下的所有接口 name是dao接口所在的包
基于映射文件的接口与映射文件必须在同一个包下