MyBatis框架
作为操作数据库的框架,相对于JPA来说,稍微要麻烦许多,因为需要自己写Sql查询语句。不过在国内使用率更高,因为它上手简单,性能更高,因为自己写sql,效率几乎等同于底层jdbc,但是开发效率对比起Jpa来说就要低很多了,毕竟写sql是一件很痛苦的事情。
Jpa作为ORM的规范,我使用的是hibernate对它的实现,可以替我们准备好很多查询方法,几乎不用写sql,开发效率极高,但是运行效率相对于MyBatis就要低许多了,而且上手程度要高很多,没有MyBatis简单。
使用MyBatis
导包
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
mybatis-3.2.1.jar
mysql-connector-java-5.1.26-bin.jar
slf4j-api-1.7.2.jar
slf4j-log4j12-1.7.2.jar
配置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>
<!--引入配置文件,用resource-->
<properties resource="jdbc.properties"></properties>
<!--取别名,使后面传对象可以不用写完全限定名,type是我们的全限定名,alias是我们取的别名,它是不区分大小写的
可以直接开启某个包的别名使用,名字就是类名
-->
<typeAliases>
<!--<typeAlias type="cn.itsource.domain.Product" alias="product"></typeAlias>-->
<package name="cn.itsource.domain"></package>
</typeAliases>
<!--环境门,可能有很多个,默认选中一个-->
<environments default="development">
<!--开发环境-->
<environment id="development">
<!--事物 选择JDBC-->
<transactionManager type="JDBC"/>
<!--配置四大金刚-->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<!--引入我们写的sql配置文件,精确找到要查询那个类,记得看路径,还有后缀等问题-->
<mappers>
<mapper resource="cn/itsource/domain/ProductMapper.xml"/>
</mappers>
</configuration>
创建Domain,然后创建一个类,并配置XxxMapper.xml
package cn.itsource.domain;
public class Product {
private Long id;
private String productName;
private Double salePrice;
private String supplier;
private String brand;
private Double cutoff;
private Double costPrice;
private Long dirId;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public Double getSalePrice() {
return salePrice;
}
public void setSalePrice(Double salePrice) {
this.salePrice = salePrice;
}
public String getSupplier() {
return supplier;
}
public void setSupplier(String supplier) {
this.supplier = supplier;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public Double getCutoff() {
return cutoff;
}
public void setCutoff(Double cutoff) {
this.cutoff = cutoff;
}
public Double getCostPrice() {
return costPrice;
}
public void setCostPrice(Double costPrice) {
this.costPrice = costPrice;
}
public Long getDirId() {
return dirId;
}
public void setDirId(Long dirId) {
this.dirId = dirId;
}
@Override
public String toString() {
return "Product{" +
"id=" + id +
", productName='" + productName + '\'' +
", salePrice=" + salePrice +
", supplier='" + supplier + '\'' +
", brand='" + brand + '\'' +
", cutoff=" + cutoff +
", costPrice=" + costPrice +
", dirId=" + dirId +
'}';
}
}
<?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,命名,完全限定名,然后再通过查询的id来精确定位要调用哪个方法-->
<mapper namespace="cn.itsource.domain.Product">
<!--当前类跟数据库里字段对应不上时配置这个,下面的返回result记得换成Map
设置主键跟类一致
-->
<resultMap id="ProductMap" type="Product">
<id column="id" property="id" />
<result column="dir_id" property="dirId" />
</resultMap>
<!--parameterType传入的类型,不同的类型 有专门写好的 名字,参考文档里面,尤其要注意这里
resultType:返回的类型 就是一条该类的数据,不是指返回List什么的
-->
<select id="findOne" parameterType="long" resultMap="ProductMap">
select * from product where id = #{id}
</select>
<!--查询全部不需要传参 ,返回的还是该类的一条数据-->
<select id="findAll" resultMap="ProductMap">
select * from product
</select>
<!--是否开启主键调用,数据库里的id 对应 我们类里面的id-->
<insert id="save" parameterType="cn.itsource.domain.Product"
useGeneratedKeys="true" keyColumn="id" keyProperty="id">
insert into product(productName,dir_id,salePrice,supplier,brand,cutoff,costPrice)
values (#{productName},#{dirId},#{salePrice},#{supplier},#{brand},#{cutoff},#{costPrice})
</insert>
<update id="update" parameterType="cn.itsource.domain.Product" >
update product set productName=#{productName},dir_id=#{dirId},salePrice=#{salePrice},supplier=#{supplier},
brand=#{brand},cutoff=#{cutoff},costPrice=#{costPrice} where id = #{id}
</update>
<delete id="delete" parameterType="long">
delete from product where id = #{id}
</delete>
<!--$和#的区别
$需要的是对象,里面装的是这个对象的属性 $是直接拼接字符串,需要自己加""
#使用的是占位符(预编译模式) 预编译性能更好,更安全,防止sql注入
-->
<select id="findOne2" parameterType="cn.itsource.domain.ProductQuery" resultMap="ProductMap">
select * from product where productName = "${name}"
</select>
</mapper>
然后就可以开始测试了
public class MyBatisTest {
@Test
public void testFindOne() throws Exception {
//通过数据源来获取我们的核心配置文件,记得选择ibatis的包
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
//然后通过sql会话工厂创建对象来创建工厂对象,传入我们的核心读取对象,记得要new出来
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
//打开会话,获取sqlsession对象
SqlSession session = factory.openSession();
//然后就可以调取查询方法了,前面传入精准定位的路径和需要查询的id,然后传入参数
Product product = session.selectOne("cn.itsource.domain.Product.findOne", 1L);
System.out.println(product);
//关闭流
session.close();
}
}
将获取sqlsession的代码抽取成工具类
package cn.itsource.util;
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;
public class MybatisUtil {
private static SqlSessionFactory sessionFactory;
static {
try {
sessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsReader("mybatis-config.xml"));
} catch (Exception e) {
e.printStackTrace();
}
}
public static SqlSession openSession(){
return sessionFactory.openSession();
}
}
然后完成Dao层,Impl层
package cn.itsource.dao;
import cn.itsource.domain.Product;
import java.util.List;
public interface IProductDao {
void save(Product product);
void update(Product product);
void delete(Long id);
Product findOne(Long id);
List<Product> findAll();
}
package cn.itsource.dao.impl;
import cn.itsource.dao.IProductDao;
import cn.itsource.domain.Product;
import cn.itsource.util.MybatisUtil;
import org.apache.ibatis.session.SqlSession;
import java.util.List;
public class ProductDaoImpl implements IProductDao {
@Override
public void save(Product product) {
SqlSession session = null;
try {
session = MybatisUtil.openSession();
session.insert("cn.itsource.domain.Product.save",product);
session.commit();
} catch (Exception e) {
session.rollback();
e.printStackTrace();
} finally {
session.close();
}
}
@Override
public void update(Product product) {
SqlSession session = null;
try {
session = MybatisUtil.openSession();
session.update("cn.itsource.domain.Product.update",product);
session.commit();
} catch (Exception e) {
session.rollback();
e.printStackTrace();
} finally {
session.close();
}
}
@Override
public void delete(Long id) {
SqlSession session = null;
try {
session = MybatisUtil.openSession();
session.delete("cn.itsource.domain.Product.delete",id);
session.commit();
} catch (Exception e) {
session.rollback();
e.printStackTrace();
} finally {
session.close();
}
}
@Override
public Product findOne(Long id) {
SqlSession session = null;
try {
session = MybatisUtil.openSession();
return session.selectOne("cn.itsource.domain.Product.findOne",id);
} catch (Exception e) {
e.printStackTrace();
} finally {
session.close();
}
return null;
}
@Override
public List<Product> findAll() {
SqlSession session = null;
try {
session = MybatisUtil.openSession();
return session.selectList("cn.itsource.domain.Product.findAll");
} catch (Exception e) {
e.printStackTrace();
} finally {
session.close();
}
return null;
}
}
最后测试所有方法
package cn.itsource.test;
import cn.itsource.dao.IProductDao;
import cn.itsource.dao.impl.ProductDaoImpl;
import cn.itsource.domain.Product;
import org.junit.Test;
public class ProductDaoImplTest {
IProductDao iProductDao = new ProductDaoImpl();
@Test
public void save() {
Product product = iProductDao.findOne(1L);
product.setId(null);
product.setProductName("雷蛇曼巴蛇");
iProductDao.save(product);
System.out.println(product);
}
@Test
public void update() {
Product product = iProductDao.findOne(21L);
product.setProductName("憨憨牌鼠标");
iProductDao.update(product);
}
@Test
public void delete() {
iProductDao.delete(25L);
}
@Test
public void findOne() {
Product product = iProductDao.findOne(1L);
System.out.println(product);
}
@Test
public void findAll() {
iProductDao.findAll().forEach(p-> System.out.println(p));
}
}