1、概念
1.1、什么是mybatis
mybatis是一款orm框架,主要用来操作数据库。
1.2、jdbc、jpa、mybatis三者的区别
jdbc
- 最原生操作数据库,它特点:执行效率高,但是开发效率低。
- jdbc自己手动写sq|语句,所以性能高。
- jdbc自己手动写sq|语句,所以性能高。
jpa
- jpa:它是对jdbc的封装它特点:开发效率高, 执行效率低。
- 开发效率高:直接调用api即可。 就能完成对应的crud。
- 执行效率低:因为sq|语句它是自动生成的, 我们不能很好控制。
mybatis
- mbatis特点:开发效率要比jdc高, 执行效率要比jpa高。
- mybatis是一个orm框架, 它消除了重复代码,
- mybatis是自己手动写sq|语句。
1.3、ORM
概念
ORM:对象关系映射(Object Relational Mapping,简称ORM),是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术。
ORM框架映射方式
常用的有两种:
- Sql操作方式(对jdbc进行封装):把SQL配置到配置文件中,通过不同SQL中完成对象实体和数据库关系相互转换的操作。(mybatis的实现方式)
- 完整映射:直接映射的是对象实体和数据库关系映射。操作数据库关系,不用写SQL有框架自己生成。(JPA、Hibenate实现方式)
映射的好处-原理
1、以一定的映射方式,把实体模型和数据库关系的映射
2、ORM框架启动时加载这些映射和数据库配置文件
3、ORM通过对最原生jdbc的封装提供更加便利的操作API
4、Dao通过ORM提供的便捷API以对象的方式操作数据库关系。
2、Mybatis简单实现domain-dao
整体的结构
2.1、导包
这里使用的是3.2.1的版本,可以从官方直接下载。
mysql-connector为mysql连接驱动包。
其他的为mybatis依赖的包。
2.2、配置mybatis-config.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>
<!--引入数据库配置-->
<properties resource="jdbc.properties"/>
<!--配置全限定对应的别名,为了后面更方面的写sql-->
<typeAliases>
<!--product全限定的别名-->
<typeAlias type="com.xuxusheng.mybatis._01mybatis.domain.Product" alias="product"/>
<typeAlias type="com.xuxusheng.mybatis._02mapper.domain.Employee" alias="employee"/>
</typeAliases>
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/xuxusheng/mybatis/_01mybatis/dao/impl/ProductDaoImpl.xml"/>
<mapper resource="com/xuxusheng/mybatis/_02mapper/mapper/EmployeeMapper.xml"/>
</mappers>
</configuration>
2.3、配置jdbc.properties
方便连接数据库
username=root
password=123456
driver=com.mysql.jdbc.Driver
url=jdbc:mysql:///mybatis
2.4、配置log4j.properties
### 全局配置根配置根 ###
##log4j常见的日志等级,trace, debug, info ,warn, error
log4j.rootLogger = ERROR,console
log4j.logger.com.xuxusheng = trace
### 配置输出到控制台 ###
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
## 打印日志格式
log4j.appender.console.layout = org.apache.log4j.PatternLayout
##日志格式详细
log4j.appender.console.layout.ConversionPattern =%d %p [%c] - %m%n
2.5、domain
数据库建好对应的表
public class Product {
private Long id;
private String productName;
private Long dirId;
private Double salePrice;
private String supplier;
private String brand;
private Double cutoff;
private Double costPrice;
//get set toString
2.6、dao
简单的CRUD
public interface IProductDao {
List<Product> findAll() throws IOException;
Product findById(Long id);
void save(Product product);
void delete(Long id);
void update(Product product);
}
2.7、dao.impl
三大核心对象:
- SqlSessionFactoryBuilder
- SqlSessionFactory
- SqlSession
步骤:
- 新建SqlSessionFactory对象
- 新建SqlSession对象
- 执行
- 关闭
public class ProductDaoImpl implements IProductDao {
private Logger logger = Logger.getLogger(ProductDaoImpl.class);
@Override
public List<Product> findAll() {
logger.trace("trace等级");
logger.debug("debug");
logger.info("info");
logger.warn("warn");
logger.error("error");
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream("mybatis-config.xml");
} catch (IOException e) {
e.printStackTrace();
}
//1、新建SqlSessionFactory对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//2、新建SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//3、执行查询
String statments = "com.xuxusheng.mybatis._01mybatis.dao.IProductDao.findAll";
List<Product> products = sqlSession.selectList(statments);
//4、关闭
sqlSession.close();
return products;
}
@Override
public Product findById(Long id) {
SqlSession sqlSession = null;
try {
sqlSession = MybatisUtil.openSession();
String statments = "com.xuxusheng.mybatis._01mybatis.dao.IProductDao.findById";
Product product = sqlSession.selectOne(statments, id);
return product;
} catch (Exception e) {
e.printStackTrace();
} finally {
if (sqlSession != null) {
sqlSession.close();
}
}
return null;
}
/**
* mysql存储引擎:
* MyISAM: 不支持事务,也不支持事务回滚,性能高,安全性低
* InnoDB: 支持事务,也支持事务回滚,性能低,安全性高
*/
@Override
public void save(Product product) {
SqlSession sqlSession = null;
try {
sqlSession = MybatisUtil.openSession();
String statments = "com.xuxusheng.mybatis._01mybatis.dao.IProductDao.save";
sqlSession.insert(statments,product);
sqlSession.commit();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (sqlSession != null) {
sqlSession.close();
}
}
}
@Override
public void delete(Long id) {
SqlSession sqlSession = null;
try {
sqlSession = MybatisUtil.openSession();
String statments = "com.xuxusheng.mybatis._01mybatis.dao.IProductDao.delete";
sqlSession.insert(statments,id);
sqlSession.commit();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (sqlSession != null) {
sqlSession.close();
}
}
}
@Override
public void update(Product product) {
SqlSession sqlSession = null;
try {
sqlSession = MybatisUtil.openSession();
String statments = "com.xuxusheng.mybatis._01mybatis.dao.IProductDao.update";
sqlSession.insert(statments,product);
sqlSession.commit();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (sqlSession != null) {
sqlSession.close();
}
}
}
}
2.8、配置ProductDaoImpl.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:映射命名空间 一般都是写dao接口的全限定名-->
<mapper namespace="com.xuxusheng.mybatis._01mybatis.dao.IProductDao">
<!--配置自定义映射规则
id :自定义映射规则的别名
type:最终转为指定的类型
-->
<resultMap id="productResultMap" type="product">
<!--主键映射使用id-->
<id column="id" property="sid"/>
<!--普通属性用热塑映射-->
<result column="dir_id" property="dirId"/>
</resultMap>
<select id="findAll" resultMap="productResultMap">
SELECT * FROM product
</select>
<select id="findById" parameterType="long" resultType="product">
SELECT * FROM product WHERE id = #{id}
</select>
<!--
useGeneratedKeys = "true"":要返回主键id
keyColumn="id" 把数据库对应id列的值封装到keyProperty中
keyProperty="id"
-->
<insert id="save" parameterType="product" useGeneratedKeys="true"
keyColumn="id" keyProperty="id">
INSERT INTO product(productName, dir_id, salePrice, supplier, brand, cutoff, costPrice)
VALUES (#{productName},#{dir_id},#{salePrice},#{supplier},#{brand},#{cutoff},#{costPrice})
</insert>
<delete id="delete" parameterType="long">
DELETE FROM product WHERE id = #{id}
</delete>
<update id="update" parameterType="product">
UPDATE product SET productName = #{productName},dir_id=#{dir_id},salePrice=#{salePrice},
supplier=#{supplier}, brand=#{brand}, cutoff=#{cutoff}, costPrice=#{costPrice} WHERE id=#{id}
</update>
</mapper>
2.9、test测试
public class IProductDaoTest {
private IProductDao productDao = new ProductDaoImpl();
@Test
public void findAll() throws IOException {
List<Product> list = productDao.findAll();
list.forEach(product -> System.out.println(product));
}
@Test
public void findById() {
Product product = productDao.findById(1L);
System.out.println(product);
}
@Test
public void save() {
Product product = new Product();
product.setBrand("huahuahua1");
product.setProductName("caocaocao2");
productDao.save(product);
System.out.println(product);
}
@Test
public void delete() {
productDao.delete(23L);
}
@Test
public void update() {
Product product = new Product();
product.setId(21L);
product.setProductName("ddddd");
productDao.update(product);
}
}
2.10、MybatisUtil
public class MybatisUtil {
private static SqlSessionFactory sqlSessionFactory;
//对于一个重量级的对象,Tomcat启动是创建,只有一个,在关闭时才进行销毁
static {
try {
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
System.out.println("解析xml文件失败");
}
}
public static SqlSession openSession() {
return sqlSessionFactory.openSession();
}
}
3、Mybatis映射实现domain-mapper
3.1、domain
public class Employee {
private Long id;
private String name;
private Integer age;
private Boolean sex;
}
//get set toString
3.2、EmployeeMapper
public interface EmployeeMapper {
//基本的CRUD
void save (Employee employee);
void update(Employee employee);
void delete(Long id);
Employee findOneById(Long id);
List<Employee> findAll();
//高级查询
List<Employee> findByQuery(EmploueeQuery query);
//查询数量
Long findCountByQuery(EmploueeQuery query);
//批量删除
void banchDelete(Long [] longs);
void banchDelete2(List<Employee> list);
//批量保存
void batchSave(List<Employee> list);
}
3.3、EmployeeMapper.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:映射命名空间 一般都是写dao接口的全限定名-->
<mapper namespace="com.xuxusheng.mybatis._02mapper.mapper.EmployeeMapper">
<resultMap id="employeeResultMap" type="employee">
</resultMap>
<!--
parameterType 可以省略不写
但是resultMap不能省略
-->
<select id="findAll" resultMap="employeeResultMap">
SELECT * FROM employee
</select>
<select id="findOneById" resultType="employee">
SELECT * FROM employee WHERE id = #{id}
</select>
<!--
useGeneratedKeys = "true"":要返回主键id
keyColumn="id" 把数据库对应id列的值封装到keyProperty中
keyProperty="id"
-->
<insert id="save">
INSERT INTO employee(name, age, sex)
VALUES (#{name},#{age},#{sex})
</insert>
<delete id="delete">
DELETE FROM employee WHERE id = #{id}
</delete>
<update id="update">
UPDATE employee SET name=#{name},age=#{age},sex=#{sex} WHERE id=${id}
</update>
<!--模糊查询
方式1 :SELECT * FROM employee WHERE name LIKE "%"#{name}"%"
方式2:SELECT * FROM employee WHERE name LIKE CONCAT("%",#{name},"%")
大于等于没有问题,但是小于号属于特殊符号,可以写两种方式:
方式1 <
如:AND age <= #{maxAge}
方式2 CDATA
如<![CDATA[AND age<=#{maxAge}]]>
-->
<!--
抽取公共sql语句
能抽sql语句哪些部分呢?
1.where条件
2.sql查询的列
-->
<sql id="whereSql">
<where>
<if test="name!=null and name!=''">
name LIKE CONCAT("%",#{name},"%")
</if>
<if test="mixAge!=null">
AND age >= #{mixAge}
</if>
<if test="maxAge!=null">
<![CDATA[AND age<=#{maxAge}]]>
</if>
</where>
</sql>
<select id="findByQuery" resultMap="employeeResultMap">
SELECT * FROM employee
<include refid="whereSql"/>
</select>
<!--查询数量-->
<select id="findCountByQuery" resultType="long">
SELECT COUNT(*) FROM employee
<include refid="whereSql"/>
</select>
<!--批量删除 有两种类型,array与list-->
<!--array-->
<delete id="banchDelete" parameterType="long[]">
DELETE FROM employee
WHERE id in
<foreach collection="array" open="(" item="x" separator="," close=")">
#{x}
</foreach>
</delete>
<!--list-->
<delete id="banchDelete2" parameterType="list">
DELETE FROM employee
WHERE id IN
<foreach collection="list" open="(" item="x" separator="," close=")">
#{x.id}
</foreach>
</delete>
<!--批量保存-->
<insert id="batchSave">
INSERT INTO employee(name, age, sex) VALUES
<foreach collection="list" item="x" separator=",">
(#{x.name},#{x.age},#{x.sex})
</foreach>
</insert>
</mapper>
3.4、EmploueeQuery
public class EmploueeQuery {
private String name;
private Integer mixAge;
private Integer maxAge;
}
//get set toString
3.5、EmployeeMapperTest
public class EmployeeMapperTest {
@Test
public void save() {
//获取SqlSession
SqlSession sqlSession = MybatisUtil.openSession();
//获取映射器
EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
Employee employee =null;
for (int i = 0; i <50 ; i++) {
employee = new Employee();
employee.setName("huahua"+i);
employee.setAge(i);
employee.setSex(i%2==0?true:false);
employeeMapper.save(employee);
sqlSession.commit();
}
}
@Test
public void update() {
SqlSession sqlSession = MybatisUtil.openSession();
EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
Employee employee = new Employee();
employee.setId(55L);
employee.setAge(222);
employeeMapper.update(employee);
sqlSession.commit();
}
@Test
public void delete() {
SqlSession sqlSession = MybatisUtil.openSession();
EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
employeeMapper.delete(104L);
sqlSession.commit();
}
@Test
public void findOneById() {
SqlSession sqlSession = MybatisUtil.openSession();
EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
Employee employee = employeeMapper.findOneById(104L);
System.out.println(employee);
}
@Test
public void findAll() {
SqlSession sqlSession = MybatisUtil.openSession();
EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
List<Employee> employees = employeeMapper.findAll();
employees.forEach(employee -> System.out.println(employee));
}
@Test
public void findByQuery(){
SqlSession sqlSession = MybatisUtil.openSession();
EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
EmploueeQuery emploueeQuery = new EmploueeQuery();
emploueeQuery.setName("2");
emploueeQuery.setMixAge(18);
emploueeQuery.setMaxAge(23);
List<Employee> employees = employeeMapper.findByQuery(emploueeQuery);
employees.forEach(employee -> System.out.println(employees));
}
@Test
public void findCountByQuery() throws Exception{
SqlSession sqlSession = MybatisUtil.openSession();
EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
EmploueeQuery emploueeQuery = new EmploueeQuery();
// emploueeQuery.setName("2");
// emploueeQuery.setMixAge(18);
// emploueeQuery.setMaxAge(23);
Long count = employeeMapper.findCountByQuery(emploueeQuery);
System.out.println(count);
}
@Test
public void banchDelete() throws Exception{
SqlSession sqlSession = MybatisUtil.openSession();
EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
Long [] longs = {101L,102L,103L};
employeeMapper.banchDelete(longs);
sqlSession.commit();
}
@Test
public void banchDelete2() throws Exception{
SqlSession sqlSession = MybatisUtil.openSession();
EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
List<Employee> list = new ArrayList<>();
Employee employee1 = new Employee();
employee1.setId(100L);
Employee employee2 = new Employee();
employee2.setId(99L);
list.add(employee1);
list.add(employee2);
employeeMapper.banchDelete2(list);
sqlSession.commit();
}
@Test
public void batchSave() throws Exception{
SqlSession sqlSession = MybatisUtil.openSession();
EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
List<Employee> list = new ArrayList<>();
Employee employee1 = new Employee();
employee1.setName("huahuahau");
employee1.setAge(111111);
employee1.setSex(true);
Employee employee2 = new Employee();
employee2.setName("huahuahaucacaca");
list.add(employee1);
list.add(employee2);
employeeMapper.batchSave(list);
sqlSession.commit();
}
}