看过之前的蜕变系列文章,相信你对springMVC有了一定的认识。对springMVC的常用功能已经有一个整体把握了。今天我们来开启新讨论,讲一讲数据库ORM操作方面的事情——Mybatis。
猿蜕变同样是一个原创系列文章,帮助你从一个普通的小白,开始掌握一些行业内通用的框架技术知识以及锻炼你对系统设计能力的提升,完成属于你的蜕变,更多精彩内容,敬请大家关注公主号猿人工厂,点击猿人养成获取!
还记得我们之前是怎么访问数据库的吗?唉,加载驱动,建立连接,老老实实的写sql,盯着sql里的问号不放, 执行sql,关闭连接……真的是一顿操作猛如虎,一看功能原地杵。
Java发展多年,自然不能老是这样搞了,已经有很多成熟的ORM框架支持我们以对象的方式访问数据库,让我们更加专注于业务逻辑的编写。
ORM,对象关系映射(ObjectRelational Mapping)是通过使用描述对象和数据库之间映射的元数据,将面向对象语言程序中的对象自动持久化到关系数据库中。我们使用ORM框架在关系型数据库和业务实体对象之间作一个映射,这样,我们在具体的操作业务对象的时候,就不需要再去和复杂的SQL语句打交道,只要像平时操作对象一样操作它就可以了。
ORM发展到今天,期间全自动ORM框架Hibernate经过短暂的繁荣(假象,大厂几乎不用,小厂为了开发速度拥抱),已经几乎凉凉,半自动化的Mybatis(之前叫Ibatis),经过多年大厂战火检验,大家还是意识到sql需要谨慎,莫要乱搞自动化生成的事情。Mybatis现在几乎算是如日中天一统江湖啦。嗯,还有JPA这个家伙,大家只当它是个做规范的吧。
接下来我们就用mybatais中使用TravelFavorite对象新增一条记录到数据库中,开启你的ORM的正确姿势。
1.创建一个web的maven项目,新增mybatis相关的依赖。除了mybatis的jar包之外,为了方便调试,这里要使用junit。
<!-- 本文主要是以测试用例的方式来使用 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.2.7</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.26</version>
</dependency>
<!-- 方便查看最终输出的sql -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
2.创建一个TravelRoute实体类:
package com.pz.route.domain;
import java.io.Serializable;
/**
* 线路实体类
* @author pangzi
*
*/
publicclass TravelRoute implements Serializable {
private Long travelRouteId;//线路id,必输
private String travelRouteName;//线路名称,必输
private Double travelRoutePrice;//价格,必输
private String travelRouteIntroduce;//线路介绍
private Integer travelRouteFlag; //是否上架,必输,0代表没有上架,1代表是上架
private String travelRouteDate; //上架时间
private String isThemeTour;//是否主题旅游,必输,0代表不是,1代表是
private Integer travelRouteCount;//收藏数量
private Integer travelRouteCid;//所属分类,必输
private String travelRouteImage;//缩略图
private Long travelRouteSellerId;//所属商家
private Long travelSellerId;
public Long getTravelRouteId() {
returntravelRouteId;
}
public void setTravelRouteId(Long travelRouteId) {
this.travelRouteId =travelRouteId;
}
public String getTravelRouteName() {
returntravelRouteName;
}
publicvoidsetTravelRouteName(String travelRouteName) {
this.travelRouteName =travelRouteName;
}
public Double getTravelRoutePrice() {
returntravelRoutePrice;
}
publicvoidsetTravelRoutePrice(Double travelRoutePrice) {
this.travelRoutePrice = travelRoutePrice;
}
public String getTravelRouteIntroduce() {
returntravelRouteIntroduce;
}
publicvoidsetTravelRouteIntroduce(String travelRouteIntroduce) {
this.travelRouteIntroduce = travelRouteIntroduce;
}
public Integer getTravelRouteFlag() {
returntravelRouteFlag;
}
publicvoidsetTravelRouteFlag(Integer travelRouteFlag) {
this.travelRouteFlag =travelRouteFlag;
}
public String getTravelRouteDate() {
returntravelRouteDate;
}
publicvoidsetTravelRouteDate(String travelRouteDate) {
this.travelRouteDate =travelRouteDate;
}
public String getIsThemeTour() {
returnisThemeTour;
}
publicvoidsetIsThemeTour(String isThemeTour) {
this.isThemeTour =isThemeTour;
}
public Integer getTravelRouteCount() {
returntravelRouteCount;
}
publicvoidsetTravelRouteCount(Integer travelRouteCount) {
this.travelRouteCount = travelRouteCount;
}
public Integer getTravelRouteCid() {
returntravelRouteCid;
}
publicvoidsetTravelRouteCid(Integer travelRouteCid) {
this.travelRouteCid =travelRouteCid;
}
public String getTravelRouteImage() {
returntravelRouteImage;
}
public void setTravelRouteImage(String travelRouteImage) {
this.travelRouteImage = travelRouteImage;
}
public Long getTravelRouteSellerId() {
returntravelRouteSellerId;
}
public void setTravelRouteSellerId(Long travelRouteSellerId) {
this.travelRouteSellerId = travelRouteSellerId;
}
public Long getTravelSellerId() {
returntravelSellerId;
}
public void setTravelSellerId(Long travelSellerId) {
this.travelSellerId = travelSellerId;
}
@Override
public String toString() {
return"TravelRoute [travelRouteId=" + travelRouteId
+ ", travelRouteName=" + travelRouteName
+ ", travelRoutePrice=" + travelRoutePrice
+ ", travelRouteIntroduce=" + travelRouteIntroduce
+ ", travelRouteFlag=" + travelRouteFlag + ", travelRouteDate="
+ travelRouteDate + ", isThemeTour=" + isThemeTour
+ ", travelRouteCount=" + travelRouteCount
+ ", travelRouteCid=" + travelRouteCid + ", travelRouteImage="
+ travelRouteImage + ", travelRouteSellerId="
+ travelRouteSellerId + ",
travelSellerId=" + travelSellerId
+ "]";
}
}
3.创建表travel_route,虽然我们已经创建过了,这里还是给下建表SQL:
CREATE TABLE `travel_route` (
`travel_route_id` int(11) NOT NULL AUTO_INCREMENT,
`travel_route_name` varchar(500) COLLATE utf8_bin NOT NULL,
`travel_route_price` double NOT NULL,
`travel_route_introduce` varchar(1000) COLLATE utf8_bin DEFAULT NULL,
`travel_route_flag` tinyint(1) NOT NULL,
`travel_route_date` varchar(19) COLLATE utf8_bin DEFAULT NULL,
`isThemeTour` tinyint(1) NOT NULL,
`travel_route_count` int(11) DEFAULT '0',
`travel_route_cid` int(11) NOT NULL,
`travel_route_image` varchar(200) COLLATE utf8_bin DEFAULT NULL,
`travel_route_seller_id` int(11) DEFAULT NULL,
PRIMARY KEY (`travel_route_id`),
KEY `FK_category_route` (`travel_route_cid`),
KEY `FK_seller_route` (`travel_route_seller_id`)
) ENGINE=InnoDB AUTO_INCREMENT=515 DEFAULT CHARSET=utf8 COLLATE=utf8_bin
4.编写用于操作数据库的dao的接口:
package com.pz.route.dao;
import com.pz.route.domain.TravelRoute;
/**
*
* @author pangzi
*
*/
publicinterface TravelRouteDao {
/**
* 添加线路
* @param travelRoute
*/
void add(TravelRoute travelRoute);
}
5.编写映射文件,一个又被称为mapper的文件,用于描述对象和数据库表字段的关系,以及编写SQL语句,具体的编写方法,后面会详细讲解。我们在resources目录下新建一个目录mapper, TravelRouteMapper.xml。虽然mapper的文件名没做强制要求,但是在实际开发过程中一般会以类名+Mapper.xml的规则命名。在TravelRouteMapper.xml中加入以下配置:
<?xml version="1.0"encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTDMapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.pz.route.dao.TravelRouteDao">
<insert id="add"parameterType="com.pz.route.domain.TravelRoute">
INSERT
INTO travel_route
(travel_route_name,travel_route_price,travel_route_introduce,travel_route_flag,travel_route_date,isThemeTour,travel_route_count,travel_route_cid,travel_route_image,travel_route_seller_id)
values(#{travelRouteName},#{travelRoutePrice},#{travelRouteIntroduce},#{travelRouteFlag},#{travelRouteDate},#{isThemeTour},#{travelRouteCount},#{travelRouteCid},#{travelRouteImage},#{travelRouteSellerId})
</insert>
</mapper>
6.在resources目录下编写mybatis的主配置文件这里命名为mybatis.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>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver"value="com.mysql.jdbc.Driver"/>
<property name="url"value="jdbc:mysql://127.0.0.1:3306/route?characterEncoding=utf8"/>
<property name="username"value="root"/>
<property name="password"value="123456"/>
</dataSource>
</environment>
</environments>
<mappers>
<!--注册映射文件-->
<mapper resource="mapper/TravelRouteMapper.xml"/>
</mappers>
</configuration>
7.增加日志相关配置在resources目录下新增文件log4j.properties,可以加入以下内容:
log4j.logger.com.pz.route.dao.TravelRouteDao=debug,console
8.创建接口TravelFavoriteDao的实现类:
package TravelFavoriteDao;
import java.io.IOException;
import java.io.InputStream;
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 com.pz.route.dao.TravelFavoriteDao;
import com.pz.route.domain.TravelFavorite;
public class TravelFavoriteDaoImpl implements TravelFavoriteDao {
private SqlSession sqlSession;
@Override
public void add(TravelFavorite travelFavorite) {
try {
//读取主配置文件
InputStream input = Resources.getResourceAsStream("mybatis.xml");
//创建SqlSessionFactory对象
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(input);
//创建SqlSession对象
sqlSession = sessionFactory.openSession();
//新增数据操作
sqlSession.insert("com.pz.route.dao.TravelFavoriteDao.add", travelFavorite);
//提交SqlSession
sqlSession.commit();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (sqlSession != null){
sqlSession.close();
}
}
}
}
9.使用junit编写测试用例,调用程序
package com.pz.route.test;
import org.junit.Test;
import com.pz.route.dao.TravelRouteDao;
import com.pz.route.dao.impl.TravelRouteDaoImpl;
import com.pz.route.domain.TravelRoute;
public class TestTravelRouteDao {
@Test
public void testAdd(){
TravelRouteDao travelFavoriteDao =new TravelRouteDaoImpl();
TravelRoute travelRoute = new TravelRoute();
travelRoute.setTravelRouteName("测试线路");
travelRoute.setTravelRoutePrice(999d);
travelRoute.setTravelRouteDate("2019-10-25");
travelRoute.setTravelRouteFlag(1);
travelRoute.setIsThemeTour("1");
travelRoute.setTravelRouteCount(0);
travelRoute.setTravelRouteCid(1);
travelRoute.setTravelRouteIntroduce("双导游服务,免收服务小费,周全照顾贴心服务随心出游!品尝越南特色国宝美食,升级一餐越式炸鸡火锅宴!");
travelRoute.setTravelRouteImage("img/product/small/m3db4d2277b5df3d98597f79082ef92d6d.jpg");
travelRoute.setTravelRouteSellerId(1L);
travelRouteDao.add(travelRoute);
}
}
10.执行测试用例:执行完毕后可以在数据库中找到新增的记录(注意:执行一次后由于主键的原因,我们需要修改参数才能再次执行程序)
我建了一个群,群里有很多高手,欢迎大家入群探讨。