学习Mybatis必须得有数据库才行啊,不会的去查看 : Win10 mysql 8.x 安装.否则无法测试
注意看注解,有些东西我都没有写到文章里,但是注解里基本都写了
Mybatis快速上手
1. 创建一个空白的Maven项目
这个没什么说的吧
2. pom.xml所需配置
2.1 引入Mysql所需驱动jar包
<!--Mysql JDBC驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.46</version>
</dependency>
2.2 引入mybatis核心依赖
<!--Mybatis核心依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.0</version>
</dependency>
3. 创建Mybatis配置文件
resources目录下创建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">
<!--头文件以及下面的配置,都可以在官网上找到
地址:https://mybatis.org/mybatis-3/zh/getting-started.html
-->
<configuration>
<settings>
<!--驼峰命名转换-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
<!--开启二级缓存-->
<setting name="cacheEnabled" value="true"/>
</settings>
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<!--使用的是哪个数据库,不写也没有关系会根据jdbc驱动自动判断-->
<property name="helperDialect" value="oracle"/>
<!--分布合理化,开启后,如果查的是第0页则会自动查第一页,
如果查的页面数超过总页数,则会去查最后一页-->
<property name="reasonable" value="true"/>
</plugin>
</plugins>
<!--default="dev" 默认使用dev环境-->
<environments default="dev">
<!--配置数据源,不同的环境不同的id名字-->
<!--可以配置多个环境,比如说本地环境,测试环境,生产环境-->
<environment id="dev">
<!--采用JDBC 方式对数据库事物进行commit/rollback-->
<transactionManager type="JDBC"/>
<!--采用连接池方式管理数据库连接,市面上大部分都是采用连接池-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<!--关于url这里一定不要换行写,会报错的-->
<property name="url" value="jdbc:mysql://localhost:3306/babytun?useUnicode=true&characterEncodeing=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
<!--生产环境数据源一般是product-->
<environment id="pro">
<!--采用JDBC 方式对数据库事物进行commit/rollback-->
<transactionManager type="JDBC"/>
<!--采用连接池方式管理数据库连接,市面上大部分都是采用连接池-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://22.33.44.55:6666/mybatis?useUnicode=true&characterEncodeing=UTF-8"/>
<property name="username" value="root1"/>
<property name="password" value="root1"/>
</dataSource>
</environment>
</environments>
<!--通知SessionFactory对象在初始化Mybatis时加载goods.xml-->
<!--这里要写你自己的xml文件及其所在文件夹,我的是在resources/mappers下
这些文件主要写sql语句,操作数据库
-->
<mappers>
<mapper resource="mappers/goods.xml"/>
<mapper resource="mappers/goods_detail.xml"/>
</mappers>
</configuration>
4. 测试
4.1 写一个测试类MybatisTestor
SessionFactory:数据库操作工厂,每次操作数据库都需要sessionFactory打开与数据库间的会话
sessionFactory.openSeeion(),除了查询操作别的操作都需要commit;不管什么操作最后一定要关闭connect,将连接归还到连接池供其他session使用,session.close();
public class MybatisTestor {
static SqlSessionFactory sessionFactory = null;
//BeforeClass 用于在Junit启用测试用例前执行一次全局初始化工作,来创建sqlSeetionFactory对象
@BeforeClass
public static void init() throws IOException {
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
sessionFactory = new SqlSessionFactoryBuilder().build(reader);
}
@Test
public void testSessionFactory() throws IOException {
SqlSession session = sessionFactory.openSession();//打开会话
Connection connection = session.getConnection();
System.out.println(connection);
}
}
测试如下,获取到jdbc连接成功
5. 增删改查操作
5.1 查询数据
准备工作,创建与数据库对应的实体类与mapper接口类(.xml),我这里暂时只用两个表测试,商品表goods,商品详情表goods_detail,getter,setter 略
public class Goods {
private Integer goodsId;
private String title;
private String subTitle;
private Float originalCost;
private Float currentPrice;
private Float discount;
private Integer isFreeDelivery;
private Integer categoryId;
//为之后多表关联查询准备的数据
private List<GoodsDetail> goodsDetails;
}
public class GoodsDetail {
private Integer gdId;
private Integer goodsId;
private String gdPicUrl;
private Integer gdOrder;
private Goods goods;
}
实体类对应的sql接口文件goods.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">
<!--
sql 映射器
头文件以及下面的SQL语句写法,都可以在官网上找到
地址:https://mybatis.org/mybatis-3/zh/getting-started.html
-->
<!--
namespace:对应数据库里某一张表,不可重名,后面调用此映射时还需要用到此命名
比如说调用此mapper里的查询全部sql映射:goods.findAll
-->
<mapper namespace="goods">
<!--标签select:mybatis的查询语句;id:唯一标识,相当于方法名;resultType:返回结果对象类型-->
<select id="findAll" resultType="com.zhangyx.mybatis.entity.Goods" flushCache="true">
select * from t_goods
</select>
</mapper>
测试
注意:现在只是因为测试才在测试类里写sqlSessionFactory这种方式,实际开发中这些东西都是在配置中的,以后笔记我会更新
注意2:每次操作完记得关闭连接,其实是将其归还给连接池供其他session使用
@Test
public void testFindAll(){
SqlSession session = null;
//openSession创建一个新的Sqlsession对象,Sqlsession提供了增删改查的方法调用
try {
session = sessionFactory.openSession();
//selectList用于查询多条数据
//类.xml里对应的namespace.sqlId
List<Goods> list = session.selectList("goods.findAll");
for (Goods goods : list){
System.out.println(goods.getTitle());
}
}catch (Exception e){
e.printStackTrace();
}finally {
if(session != null){
//将Connection归还到连接池供其他Session重用
session.close();
}
}
}
5.2 数据写(更新)操作
插入操作
注意1:凡是数据写操作,都要进行commit操作,提交到数据库,不然是不生效的
注意2:#{}与${}都可以进行取值操作,但是使用${}有可能造成Sql注入不安全,所以不建议使用${}
注意3:凡是要进入数据库进行操作的,字段都要跟数据库的保持一致,比如我这里带下划线的参数凡是跟表有关的操作都要写属性,比如我这里驼峰似的参数
<!--标签insert:数据插入操作,id:唯一标识,parameterType:传过来的参数类型[class,Integer,String...]-->
<insert id="insert" parameterType="com.zhangyx.mybatis.entity.Goods">
INSERT INTO `babytun`.`t_goods`(`title`, `sub_title`, `original_cost`,
`current_price`, `discount`, `is_free_delivery`, `category_id`)
VALUES ( #{title}, #{subTitle}, #{originalCost}, #{currentPrice}, #{discount}, #{isFreeDelivery}, #{categoryId});
/*最新插入数据回填id,resultType:回填数据类型,keyProperty:回填到实体类的哪个字段,
order:此语句何时执行AFTER[插入数据操作执行完后执行],BEFORE[插入数据操作执行完前执行]
#{},${}两种都是取传过来的参数值,但是${}不建议使用,有可能会造成sql注入,不安全*/
<selectKey resultType="Integer" keyProperty="goodsId" order="AFTER">
select last_insert_id()
</selectKey>
</insert>
<update id="update" parameterType="com.zhangyx.mybatis.entity.Goods">
UPDATE `babytun`.`t_goods`
SET
`title` = #{title},
`sub_title` = #{subTitle},
`original_cost` = #{originalCost},
`current_price` = #{currentPrice},
`discount` = #{discount},
`is_free_delivery` = #{isFreeDelivery},
`category_id` = #{categoryId}
WHERE
`goods_id` = #{goodsId};
</update>
<delete id="delete" parameterType="Integer">
delete from t_goods where goods_id = #{value }
</delete>
测试
@Test
public void testInsert(){
SqlSession session = null;
//openSession创建一个新的Sqlsession对象,Sqlsession提供了增删改查的方法调用
try {
session = sessionFactory.openSession();
Goods goods = new Goods();
goods.setTitle("数据插入测试");
goods.setSubTitle("数据插入测试第二标题");
goods.setCategoryId(1);
goods.setCurrentPrice(1000f);
goods.setDiscount(2f);
goods.setIsFreeDelivery(1);
goods.setOriginalCost(20f);
int result = session.insert("goods.insert", goods);
System.out.println(result);
System.out.println(goods.getGoodsId());
session.commit();
}catch (Exception e){
e.printStackTrace();
session.rollback();
}finally {
if(session != null){
//将Connection归还到连接池供其他Session重用
session.close();
}
}
}
@Test
public void testUpdate(){
SqlSession session = null;
//openSession创建一个新的Sqlsession对象,Sqlsession提供了增删改查的方法调用
try {
session = sessionFactory.openSession();
Goods goods = session.selectOne("goods.findById",2675);
System.out.println(goods);
goods.setTitle("数据更新测试");
goods.setSubTitle("数据更新测试第二标题");
goods.setCategoryId(1);
goods.setCurrentPrice(1000f);
goods.setDiscount(2f);
goods.setIsFreeDelivery(1);
goods.setOriginalCost(20f);
session.update("goods.update", goods);
session.commit();
}catch (Exception e){
e.printStackTrace();
session.rollback();
}finally {
if(session != null){
//将Connection归还到连接池供其他Session重用
session.close();
}
}
try {
session = sessionFactory.openSession();
Goods goods1 = session.selectOne("goods.findById",2675);
System.out.println(goods1);
}catch (Exception e){
e.printStackTrace();
}finally {
if(session != null){
session.close();
}
}
}
@Test
public void testDelete(){
SqlSession session = null;
//openSession创建一个新的Sqlsession对象,Sqlsession提供了增删改查的方法调用
try {
session = sessionFactory.openSession();
int result = session.delete("goods.delete", 2681);
System.out.println(result);
session.commit();
}catch (Exception e){
e.printStackTrace();
session.rollback();
}finally {
if(session != null){
//将Connection归还到连接池供其他Session重用
session.close();
}
}
}