MyBatis
MyBatis
- 1.ORM思想
- 2.MyBatis中的事务
- 3.在MyBatis中引入JUnit单元测试
- 4.MyBatis集成日志框架logback
- 5.使用mybatis完成CRUD业务
- 6.SQLMapper映射文件中namespace的作用
- 7.MyBatis核心配置文件
- 7.1 数据库连接池
- 7.2
1.ORM思想
ORM:对象 关系 映射
O(Object):JVM中的java对象,R(Relational):关系型数据库,M(Mapping):映射
2.MyBatis中的事务
(1)
在mybatis-config.xml文件中,可以通过以下配置进行mybatis的事务管理
<transactionManager type="JDBC"/> JDBC|MANAGED不区分大小写)
JDBC:mybatis框架自己管理事务,自己采用原生的JDBC代码去管理事务
conn.setAutoCommit(false);开启事务
...
conn.commit();提交事务
MANAGED:mybatis不在负责事务的管理,事务管理交给其他容器来负责,如Spring
如果没有其他容器管理的话,就默认没有事务
3.在MyBatis中引入JUnit单元测试
<!--junit依赖-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
4.MyBatis集成日志框架logback
(1)引入logback依赖
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.4.3</version>
</dependency>
(2)引入logback所必必须的xml配置文件
命名必须为:logback.xml或者logback-test.xml,这个配置文件必须放在类的根路径下
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
<!--控制台输出-->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度,%msg:日志消息,%n换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%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>${LOG_HOME}/TestWeb.log.%d{yyyy-MM-dd}.log</FileNamePattern>
<!--日志文件保留天数-->
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度,%msg:日志消息,%n换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
<!--日志文件最大的大小-->
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>100MB</MaxFileSize>
</triggeringPolicy>
</appender>
<!--mybatis log configure-->
<logger name="com.apache.ibatis" level="TRACE"/>
<logger name="java.sql.Connection" level="DEBUG"/>
<logger name="java.sql.Statement" level="DEBUG"/>
<logger name="java.sql.PreparedStatement" level="DEBUG"/>
<!--日志输出级别,logback日志级别包括五个:TRACE<DEBUG<INFO<WARN<ERROR-->
<root level="DEBUG">
<appender-ref ref="STDOUT"/>
<appender-ref ref="FILE"/>
</root>
</configuration>
5.使用mybatis完成CRUD业务
(1)将SqlSession对象的得到过程封装成一个util
public class SqlSessionUtil {
//工具类的构造方法一般是私有化的
private SqlSessionUtil(){}
private static SqlSessionFactory sqlSessionFactory;
//类加载时执行 工具类第一次加载的时候,解析mybatis-config.xml文件,创建一个SqlSessionFactory对象
static {
try {
sqlSessionFactory=new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
//工具类中所有的方法都是静态的,直接采用类名就可以调用,不需要new对象
public static SqlSession openSession(){
//返回会话对象
return sqlSessionFactory.openSession();
}
}
(2)写一个封装汽车信息的类
public class Car {
//数据库表中的字段应该和类中的属性一一对应
private Long id;//使用包装类Long防止null的问题
private String carNum;
private String brand;
private Double guidePrice;
private String produceTime;
private String carType;
public Car(){}
public Car(Long id, String carNum, String brand, Double guidePrice, String produceTime, String carType) {
this.id = id;
this.carNum = carNum;
this.brand = brand;
this.guidePrice = guidePrice;
this.produceTime = produceTime;
this.carType = carType;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getCarNum() {
return carNum;
}
public void setCarNum(String carNum) {
this.carNum = carNum;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public Double getGuidePrice() {
return guidePrice;
}
public void setGuidePrice(Double guidePrice) {
this.guidePrice = guidePrice;
}
public String getProduceTime() {
return produceTime;
}
public void setProduceTime(String produceTime) {
this.produceTime = produceTime;
}
public String getCarType() {
return carType;
}
public void setCarType(String carType) {
this.carType = carType;
}
@Override
public String toString() {
return "Car{" +
"id=" + id +
", carNum='" + carNum + '\'' +
", brand='" + brand + '\'' +
", guidePrice=" + guidePrice +
", produceTime='" + produceTime + '\'' +
", carType='" + carType + '\'' +
'}';
}
}
(3)Mapper文件中写SQL语句
<?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="org.mybatis.example.BlogMapper">
<!--提供一个插入语句,id是这条SQL语句的唯一标识-->
<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>
<delete id="deleteById">
delete from t_car where id=#{num}
</delete>
<update id="updateById">
update t_car set car_num=#{carNum},
brand=#{brand},
guide_price=#{guidePrice},
produce_time=#{produceTime},
car_type=#{carType}
where id=#{id}
</update>
<select id="selectById" resultType="com.mybatis.bean.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>
<select id="selectAll" resultType="com.mybatis.bean.Car">
select id,car_num as carNum,brand,guide_price as guidePrice,
produce_time as produceTime,car_type as carType
from t_car
</select>
</mapper>
(4)写测试程序
public class CapMapperTest {
@Test
public void testInsertCar(){
SqlSession sqlSession= SqlSessionUtil.openSession();
//封装数据
Car car = new Car(null,"1002","兰博基尼",800.0,"2020-12-21","跑车");
//执行语句
//insert方法的参数
//(1)sqlId,在CarMapper文件中复制
//(2)对象,封装要传入的数据
int count = sqlSession.insert("insertCar",car);
System.out.println(count);
sqlSession.commit();
sqlSession.close();
}
@Test
public void testDeleteById(){
SqlSession sqlSession=SqlSessionUtil.openSession();
//执行sql语句
int count = sqlSession.delete("deleteById", 1);
System.out.println(count);
sqlSession.commit();
sqlSession.close();
}
@Test
public void testUpdateById(){
Car car = new Car(2L,"1000","劳斯莱斯",789.0,"2021-03-23","跑车");
SqlSession sqlSession = SqlSessionUtil.openSession();
//执行sql语句
int count = sqlSession.update("updateById", car);
System.out.println(count);
sqlSession.commit();
sqlSession.close();
}
@Test
public void testSelectById(){
SqlSession sqlSession = SqlSessionUtil.openSession();
Object car = sqlSession.selectOne("selectById", 1);
System.out.println(car);
sqlSession.close();
}
@Test
public void testSelectAll(){
SqlSession sqlSession = SqlSessionUtil.openSession();
List<Object> cars = sqlSession.selectList("selectAll");
cars.forEach(car -> System.out.println(car));
sqlSession.close();
}
}
6.SQLMapper映射文件中namespace的作用
(1)
namespace是用来指定命名空间,防止id冲突
<mapper namespace="car">
<mapper namespace="user">
(2)写id的时候,需要
//List<Object> cars = sqlSession.selectList("selectAll");
//正确的写法 namespace+id
List<Object> cars = sqlSession.selectList("user.selectAll");
7.MyBatis核心配置文件
7.1 数据库连接池
优点:
(1)提升效率
(2)防止创建对象过来,导致数据库宕机
7.2
<?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表示默认使用的环境,当使用mybatis创建SqlSessionFactory对象没有指定环境的话
,默认使用development-->
<environments default="development">
<!--其中一个环境,连接的数据库是test-->
<!--一般一个数据库对应一个SqlSessionFactory对象-->
<environment id="development">
<!--transactionManager
作用:配置事务管理器,指定mybatis具体使用什么方式去管理事务
type属性有两个值:
JDBC:使用原生的JDBC代码管理事务
MANAGED:mybatis不再负责事务管理,交给其他容器管理
-->
<transactionManager type="JDBC"/>
<!--dataSource
1.dataSource被称为数据源
2.作用:为程序提供Connection对象(凡是给程序提供Connection对象,都是数据源)
3.数据源实际上是一套规范,JDK有这套规范:javax.sql.DataSource(这个接口是JDK规定的)
4.我们可以实现这个接口,编写数据源组件(数据库连接池是连接对象的,所以数据库连接池是一个数据源)
5.常见的数据源有哪些(常见的数据库连接池):druid,c3p0,dbcp
6.type属性:用来指定数据源的类型,用来指定具体使用什么方式来获取Connection对象
type有三个属性值:
UNPOOLED:不使用数据库连接池技术,每一次请求过来都新建新的Connection对象
POOLED:使用mybatis自己实现的数据库连接池
JNDI:集成其他第三方的数据库连接池
-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test"/>
<property name="username" value="root"/>
<property name="password" value="cw20010212"/>
<!--正常使用连接池的话,池中很多参数需要设置,设置好参数,可以让连接池发挥的更好-->
<!--连接池当中最多正在使用的连接对象的数量上限,默认值是10-->
<property name="poolMaximumActiveConnections" value="3"/>
<!--每隔两秒打印日志,并尝试获取连接对象-->
<property name="poolTimeToWait" value="2000"/>
<!--强行让某个连接空闲,设置超时时间-->
<property name="poolMaximumCheckoutTime" value="10000"/>
<!--设置连接池中最多空闲数量-->
<property name="poolMaximumIdleConnections" value="5"/>
</dataSource>
</environment>
<!--令一个环境,连接的数据库是cm-->
<environment id="abc">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/cm"/>
<property name="username" value="root"/>
<property name="password" value="cw20010212"/>
</dataSource>
</environment>
</environments>
<mappers>
<!--指定XxxMapper.xml文件的路径-->
<!--resource属性默认从类的根路径下查找文件-->
<mapper resource="CarMapper.xml"/>
<mapper resource="UserMapper.xml"/>
</mappers>
</configuration>