了解Mybatis
Mybatis是一个持久层框架,半自动化ORM(Hibernate属于全自动化ORM)。
Mybatis的特点:
- 支持定制化sql、存储过程、基本映射以及高级映射
- 避免了几乎所有的JDBC代码中手动设置参数以及获取结果集
- 支持XML开发,也支持注解式开发
- 将接口和Java的pojo映射成数据库中的记录
- 体积小,易上手
- 完全做到sql解耦
- 提供了基本映射标签和高级映射标签
- 提供XML标签、支持动态sql
Mybatis入门程序
-
引入依赖
xml<!-- mybatis依赖--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.14</version> </dependency> <!-- MySQL驱动依赖--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.30</version> </dependency> -
从XML中构建SqlSessionFactory
SqlSessionFactory是mybatis中一个重要的对象。
SqlSessionFactory对象的创建需要xml
编写mybatis-config.xml文件(mybatis的核心配置文件)
文件不是必须叫mybatis-config.xml,可以采用其他名字
文件存放路径不是固定的,一般放在类的根路径下,一般放在resources文件夹下
mybatis中有两个主要的配置文件:
-
mybatis-config.xml是核心配置文件,主要配置连接数据库的信息
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.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/spring6"/> <property name="username" value="root"/> <property name="password" value="root"/> </dataSource> </environment> </environments> <mappers> <!-- 执行xxxMapper.xml文件中的SQL语句--> <!-- resource属性自动从类的路径下加载xxxMapper.xml文件--> <mapper resource="CarMapper.xml"/> <!-- url属性直接从文件系统绝对路径加载xxxMapper.xml文件(不推荐)--> <!-- <mapper url="file:///D:/JavaProject/mybatis-001/src/main/resources/CarMapper.xml"/>--> </mappers> </configuration> -
xxxxMapper.xml是用来编写SQL的配置文件
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"> <mapper namespace="carMapper"> <insert id="insertCar" > INSERT INTO t_car (id, car_num, brand,guide_price,produce_time,car_type) VALUES (null, '1003', '丰田霸道',30.0,'2000-10-11','燃油车') </insert> </mapper>
在mybatis当中,负责执行sql语句的那个对象叫做SqlSession。
SqlSession是专门执行sql语句的,是一个Java程序和数据库之间的一次会话。
要想获取SqlSession对象,需要先获取SqlSessionFactory对象,通过SqlSessionFactory来创建SqlSession对象。
怎么获取SqlSessionFactory对象?
需要先获取SqlSessionFactoryBuilder对象。
通过SqlSessionFactoryBuilder对象的build方法来获取SqlSessionFactory对象。
所以mybatis的核心对象包括:
- SqlSessionFactoryBuilder
- SqlSessionFactory
- SqlSession
SqlSessionFactoryBuilder--》SqlSessionFactory--》SqlSession
编写测试程序:
javapublic class MyBatisTes { public static void main(String[] args) throws IOException { // 获取 SqlSessionFactoryBuilder 对象 SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder(); // 获取 SqlSessionFactory 对象 // Resources.getResourceAsStream默认从类路径下加载资源文件 InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml"); // 一般情况下,一个数据库对应一个SqlSessionFactory对象 SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(resourceAsStream); // 获取 SqlSession 对象 SqlSession sqlSession = sqlSessionFactory.openSession(); int insertCar = sqlSession.insert("insertCar"); System.out.println("插入了" + insertCar + "条数据"); sqlSession.commit(); } } -
mybatis的事务管理机制
-
在mybatis-config.xml文件中,可以通过以下配置进行mybatis的事务管理
type属性值包括JDBC和MANAGED
在mybatis中提供了2中事务管理机制
-
jdbc事务管理器:mybatis框架自己管理事务,自己采用原生的jdbc代码去管理事务
conn.setAutoCommit(false); // 开启事务
。。。。业务处理。。。。
conn.commit();// 手动提交事务
如果设置了自动提交(sqlSessionFactory.openSession(true);)。那么就没有开启事务,这是不推荐的
如果没有开启事务,那么就会自动提交
-
MANAGED事务管理器:mybatis不负责事务管理,事务管理交给其他容器来负责,例如Spring
-
mybatis程序完善版:
java
public static void main(String[] args) {
SqlSession sqlSession = null;
try {
// 获取 SqlSessionFactoryBuilder 对象
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
// 获取 SqlSessionFactory 对象
// Resources.getResourceAsStream默认从类路径下加载资源文件
InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(resourceAsStream);
// 获取 SqlSession 对象,底层会开启事务
sqlSession = sqlSessionFactory.openSession();
int insertUser = sqlSession.insert("insertCar");
System.out.println("插入了" + insertUser + "条数据");
sqlSession.commit();
} catch (IOException e) {
if (sqlSession != null) {
sqlSession.rollback();
}
throw new RuntimeException(e);
}finally {
if (sqlSession != null) {
sqlSession.close();
}
}
}
mybatis开启日志
在mybatis-config.xml中配置如下:
xml
<settings>
<!-- 开启日志:STDOUT_LOGGING是标准日志实现,mybatis已经实现了这个标准日志
settings标签必须出现在environments标签之前-->
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
集成logback日志框架
logback实现了slf4j标准。
- 引入logback依赖
xml
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.4.5</version>
</dependency>
- 引入logback的xml配置文件
配置文件名字必须叫做logback.xml或者logback-test.xml,不能是其他名字。
配置文件必须放在类的根路径下,不能是其他位置。
内容如下:
xml
<configuration debug="false">
<!-- 控制台输出-->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
</appender>
<!-- 每天生成日志文件-->
<!-- <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!– 日志文件按日期滚动生成的文件名 –>
<fileNamePattern>mybatis-%d{yyyy-MM-dd}.log</fileNamePattern>
<!– 保留最近30天的日志文件 –>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<!– 当日志文件大小超过100MB时触发滚动 –>
<maxFileSize>100MB</maxFileSize>
</triggeringPolicy>
</appender>-->
<logger name="com.ali" level="trace" />
<logger name="java.sql.Connection" level="debug" />
<logger name="java.sql.Statement" level="debug" />
<logger name="java.sql.PreparedStatement" level="debug" />
<root level="debug">
<appender-ref ref="STDOUT" />
<!-- <appender-ref ref="FILE" /> -->
</root>
</configuration>
MyBatis工具类
java
public class SqlSessionUtil {
// 构造方法私有化,防止外部创建实例
private SqlSessionUtil(){}
private static SqlSessionFactory sqlSessionFactory;
// 类加载时执行,初始化 SqlSessionFactory
static {
try {
sqlSessionFactory =new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
} catch (Exception e) {
throw new RuntimeException("初始化 SqlSessionFactory 失败", e);
}
}
// 提供一个公共的静态方法,获取 SqlSession 对象
public static SqlSession openSqlSession(){
return sqlSessionFactory.openSession();
}
}
mybatis中增删改查
新增
在mybatis中使用#{}来代替jdbc当中?占位符
java
@Test
public void TestInsertCar() {
SqlSession sqlSession = SqlSessionUtil.openSqlSession();
Map<String, Object> map = new HashMap<String, Object>();
map.put("k1", "1111");
map.put("k2", "比亚迪汉");
map.put("k3", 10.0);
map.put("k4", "2024-06-01");
map.put("k5", "新能源");
sqlSession.insert("insertCar", map);
sqlSession.commit();
sqlSession.close();
}
xml
<insert id="insertCar" >
INSERT INTO t_car (id, car_num, brand,guide_price,produce_time,car_type)
VALUES (null, #{k1}, #{k2},#{k3},#{k4},#{k5})
</insert>
使用pojo类传值
java
@Test
public void TestInsertCarByPojo() {
SqlSession sqlSession = SqlSessionUtil.openSqlSession();
Car car = new Car(null, "3333", "比亚迪秦", 30.0,"2020-10-11","新能源");
sqlSession.insert("insertCar", car);
sqlSession.commit();
sqlSession.close();
}
xml
<insert id="insertCar" >
INSERT INTO t_car (id, car_num, brand,guide_price,produce_time,car_type)
VALUES (null, #{carNum}, #{brand},#{guidePrice},#{produceTime},#{carType})
</insert>
#{carNum}中的carNum实际上是pojo类中的get方法getCarNum() 的方法名去掉get,然后首字母小写的字符串。不是属性名
删除
java
@Test
public void testDeleteCarById() {
SqlSession sqlSession = SqlSessionUtil.openSqlSession();
sqlSession.delete("deleteCarById", 1);
sqlSession.commit();
sqlSession.close();
}
xml
<delete id="deleteCarById" >
DELETE FROM t_car WHERE id = #{id}
</delete>
如果占位符只有一个。那么#{}里面可以随意写,最好见名知意
更新
java
@Test
public void testUpdateCarById() {
SqlSession sqlSession = SqlSessionUtil.openSqlSession();
Car car = new Car(2L, "3333", "比亚迪秦Pro", 30.0, "2020-10-11", "新能源");
sqlSession.update("updateCarById", car);
sqlSession.commit();
sqlSession.close();
}
xml
<update id="updateCarById" >
UPDATE t_car SET car_num = #{carNum}, brand = #{brand},guide_price = #{guidePrice},produce_time = #{produceTime},car_type = #{carType} WHERE id = #{id}
</update>
查一个
java
@Test
public void testSelectCarById() {
SqlSession sqlSession = SqlSessionUtil.openSqlSession();
// mybatis底层执行select后,会返回一个结果集对象:ResultSet
// jdbc中叫做ResultSet,在mybatis中叫做ResultMap
Car car = sqlSession.selectOne("selectCarById", 2);
System.out.println(car);
sqlSession.close();
}
xml
<!-- resultType表示要将查询结果封装成哪个类的对象-->
<select id="selectCarById" resultType="com.ali.pojo.Car">
SELECT id, car_num AS carNum, brand, guide_price AS guidePrice, produce_time AS produceTime, car_type AS carType
FROM t_car
WHERE id = #{id}
</select>
查所有
java
@Test
public void testSelectAllCar() {
SqlSession sqlSession = SqlSessionUtil.openSqlSession();
// mybatis底层执行select后,会返回一个结果集对象:ResultSet
// jdbc中叫做ResultSet,在mybatis中叫做ResultMap
List<Car> cars = sqlSession.selectList("selectAllCar");
for (Car car : cars) {
System.out.println(car);
}
sqlSession.close();
}
xml
<select id="selectAllCar" resultType="com.ali.pojo.Car">
SELECT id, car_num AS carNum, brand, guide_price AS guidePrice, produce_time AS produceTime, car_type AS carType
FROM t_car
</select>
关于sql Mapper中的namespace
标签中的namespace 用来指定命名空间。用来防止id重复。
在Java程序中的写法( . ):
List cars = sqlSession.selectList("carMapper.selectAllCar");