还没毕业做过跟着 学姐做了两个月的增删改查,然后就做了一年的爬虫。现在领导让我开始做web方面的开发。
现在只能重新学习,哈哈哈。。。
MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。
Mybatis通过xml或注解的方式将要执行的各种statement(statement、preparedStatemnt、CallableStatement)配置起来,并通过java对象和statement中的sql进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射成java对象并返回。
架构设计图如下:
mybatis配置:
SqlMapConfig.xml,此文件作为mybatis的全局配置文件,配置了mybatis的运行环境等信息。
mapper.xml文件即sql映射文件,文件中配置了操作数据库的sql语句。此文件需要在SqlMapConfig.xml中加载。
创建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">
<configuration>
<!-- 初始化环境,和spring整合以后,这个将会被废除 -->
<environments default="development">
<environment id="development">
<!-- 使用jdbc管理事务,事务控制是由mybatis来执行 -->
<transactionManager type="JDBC"/>
<!-- 数据源 也是由mybatis来进行管理-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8"/>
<property name="username" value="root"/>
<property name="password" value="admin"/>
</dataSource>
</environment>
</environments>
<mappers>
<!-- 引入映射文件 -->
<!-- <mapper resource="org/mybatis/example/BlogMapper.xml"/> -->
</mappers>
</configuration>
sqlMapConfig是mybatis的核心配置文件,包含数据源,事务管理等等
创建用户类:
public class User{
private int id;
private String username;
private String sex;
................
}
Namespace:命名空间 用来隔离sql语句,在mybatis代理模式具有特殊的含义
详细的mapper文件如下:
<?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="test">
<!-- 首先明确:mybatis的所有sql语句都存放在xml的映射文件中,也就是说有多个sql -->
<!-- id:id就是我们唯一标识一个sql语句的地址
mybatis会将sql语句封装到mappedStatement对象中,id就是statement的id
注意:我们需要根据ID进行查询,需要接受参数使用parameterType进行接受参数
#,$都用来接受参数,就是占位符接受参数,注意:如果传递的是基本类型的参数,#{??}里面可以任意
parameterType:传递参数
resultType:结果集映射 -->
<select id="selectUserByID" parameterType="int" resultType="cn.itcast.bean.User">
select * from user where id=#{id}
</select>
</mapper>
具体对应的代码如下:
public class MybatisTest{
//通过mybatis环境等配置信息构造SqlSessionFactory,即会话工厂
//由会话工厂创建sqlSession即会话,操作数据库需要通过sqlSession进行
private SqlSessionFactory sessionFactory;
@Before
public void createSessionFactory() throws Exception{
String res="sqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(res);
sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void test02(){
//获取Session
SqlSession session = sessionFactory.openSession();
//与配置文件里面的select标签相对应
User user = session.selectOne("test.selectUserByID", 1);
System.out.println(user);
session.close();
}
@Test
public void test01() throws Exception{
String resources="sqlMapConfig.xml";
//读取文件资源流
InputStream inputStream = Resources.getResourceAsStream(resources);
//创建一个SessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//获取Session
SqlSession session = sessionFactory.openSession();
User user = session.selectOne("test.selectUserByID", 1);
System.out.println(user);
session.close();
}
}
根据姓名username进行模糊查询
映射文件
<!--需求:根据用户姓名进行模糊查询,可能返回多条记录
resultType:指定返回单条记录,映射成Java单个对象
${}拼接sql语句,对参数不加任何修饰的拼接在sql语句中
${value}:如果传入的参数类型是基本类型,那么${}内只能是value -->
<select id="selectUserByUsername" parameterType="string" resultType="cn.itcast.bean.User">
select * from user where username like '%${value}%'
</select>
测试代码如下:
@Test
public void selectUserByUsername(){
SqlSession session = sessionFactory.openSession();
//第一个参数:statement的id,根据id找到需要执行的sql
//第二个参数:指定匹配parameterType的参数类型
List<User> list = session.selectList("test.selectUserByUsername", "张");
System.out.println(list);
}
注意两个的区别:
不管查询结果对应的是一个还是多个,我们只需要resultType写上对应的类的路径就可以,两者是没有区别的。
占位符的处理:
#{}表示一个占位符,通过#{}可以实现preparedStatement向占位符中设置值,自动进行Java
类型和jdbc类型转换,#{}可以有效防止sql注入。#{}可以接受简单类型值或pojo属性值。
如果parameterType传输单个类型的值,#{}括号中可以是value或者其他任意值。
${}表示拼接sql串,通过${}可以通过patameterType传入的内容拼接在sql中且不进行jdbc类型转换。${}可以接受简单类型值或pojo属性值,如果parameterType传输单个类型值,${}括号中只能是value.
parameterType和resultType
patameterType:指定传递参数类型,mybatis通过ognl获取参数拼接在sql语句中
resultType:指定返回结果类型,mybatis可以把查询结果封装成Java对象,这里就是把结果集映射成resultType指定的对象。
selectOne和selectList
selectOne查询一条记录,如果使用selectOne查询多条记录则抛出异常:
org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 3
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:70)
selectList可以查询一条或多条记录。
映射文件
POJO(Plain Ordinary Java Object)简单的Java对象,实际就是普通JavaBeans
映射文件 user.xml
<!-- parameterType:指定输入参数类型pojo,就是javabean对象
#{}口号中是Javabean的属性名,mybatis通过ognl来获取javabean的属性值 -->
<insert id="insertUser" parameterType="cn.itcast.bean.User">
<!--使用sql函数生成主键ID 注意:mysql主键是在执行完成insert语句后才增加主键,所以使用after -->
<selectKey keyProperty="id" order="AFTER" resultType="int">
SELECT LAST_INSERT_ID()
</selectKey>
insert into user(id,username,birthday,sex,address)
values(#{id},#{username},#{birthday},#{sex},#{address})
</insert>
Mysql自增主键返回:
selectKey实现自增主键返回:
keyProperty:返回值对应pojo里面的那个属性。
Order:表示id生成的顺序,由于mysql主键生成是在sql语句执行之后在进行设置,所以我们设置成after。
ResultType:主键返回类型
LAST_INSERT_ID()是mysql函数,返回auto_increament自增id值
也可以使用useGeneratedKeys来返回主键
测试代码
@Test
public void test01() throws Exception{
SqlSession sqlSession = sessionFactory.openSession();
User user = new User();
user.setUsername("张三");
user.setSex("男");
user.setBirthday(new Date());
user.setAddress("陕西");
sqlSession.insert("test.insertUser", user);
System.out.print(user.getId);//使用last_insert_Id返回ID
sqlSession.commit();
sqlSession.close();
}
mysql使用uuid实现主键自增
注意:mysql的uuid生成必须在执行insert之前进行,因为后面需要获取uuid的属性值进行表的插入。
删除:
测试代码:
@Test
public void deleteUserByID(){
SqlSession session = sessionFactory.openSession();
//删除单表,没有外键关联才能被删除
session.delete("test.deleteUserByID", 32);
session.commit();
session.close();
}
修改:
映射文件
测试代码
parameterType
指定传递参数类型,前台传入参数和后台获取参数类型必须匹配
resultType
指定返回值类型,执行sql结果映射Java对象
mybatis和hibernate区别
Hibernate:hibernate是一个标准的ORM框架,不需要写sql语句,维护关系不叫复杂,sql语句自动生成,对sql语句优化,修改比较困难。
Hibernate的优缺点:
优点:面向对象开发,不需要自己写sql语句。如果进行数据库迁移不需要修改sql语句,只需要修改一下方言。
缺点:hibernate维护数据表关系比较复杂。完全是有hibernate来管理数据表的关系,对于我们来说完全是透明的,不易维护。
Hibernate自动生成sql语句,生成sql语句比较复杂,比较难挑错。
Hibernate由于是面向对象开发,不能开发比较复杂的业务。
应用场景:
适合需求变化较少的项目,比如ERP,CRM等等
Mybatis框架对jdbc框架进行封装,屏蔽了jdbc的缺点,开发简单。
Mybatis只需要程序员关注sql本身,不需要过多的关注业务。对sql的优化,修改比较容易
适应场景:
适合需求变化多端的项目,比如:互联网项目