一.MyBatis说是什么?
MyBatis是一个持久层框架,其实就是代替了三层架构的Dao的作用,完成对访问数据库之前各种操作,如:封装JDBC,对查询的数据封装到model中,SQL语句动态查询等等。
二.整合MyBatis的步骤
(1)引入mybatis坐标(依赖)
需要连接数据库:
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.31</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.2</version>
</dependency>
mybatis需要引入的依赖:
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.9</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.7</version>
</dependency>
测试相关的依赖:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.3.22</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.2.2.RELEASE</version>
</dependency>
(2) 编写实体类(注意:@Data注解需要引入Lombok依赖)
package com.wx;
import lombok.Data;
import java.math.BigDecimal;
@Data
public class Acount {
private Integer id;
private String name;
private BigDecimal money;
}
(3) 书写接口类mapper类
package com.wx.mapper;
import com.wx.Acount;
import java.util.List;
public interface AcountMapper {
List<Acount> findAll(); //查找所有的记录
}
(4)书写与之接口对应的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="com.wx.mapper.AcountMapper">
<select id="findAll" resultType="com.wx.Acount">
select * from acount;
</select>
</mapper>
注意:两个文件的路径应该相同。
(5)书写jdbc配置文件(properties文件:配置数据库的数据)
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/stage04frontassign?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8
jdbc.username=root
jdbc.password=123456
(6)书写spring配置文件
<!--让下面的配置能够找到properties文件-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!--拿到properties里面的数据-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driver}"></property>
<property name="jdbcUrl" value="${jdbc.url}"></property>
<property name="user" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<!--配置mybatis-->
<!-- 配置SessionFactory的Bean-->
<bean id="sessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 注入数据源(连接池) jdbc 的connection需要使用-->
<property name="dataSource" ref="dataSource"/>
<!-- 指定MyBatis配置文件的位置 -->
<property name="configLocation" value="classpath:mybatis.xml"/>
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--指定的是SqlSessionFactory对象的id-->
<property name="sqlSessionFactoryBeanName" value="sessionFactory"/>
<!--指定包名,包名是dao接口所在的包名
MapperScannerConfigurer会扫描这个包中的所有接口,把每个接口都执行
一次getMapper()方法,得到每个接口的dao对象
创建好的dao对象放入到spring的容器中
dao默认对象的名称:是接口名字的首字母小写
-->
<property name="basePackage" value="com.wx"/>
<!--多个包-->
<!--<property name="basePackage" value="com.md.dao,com.md.dao2"/>-->
</bean>
(7)书写mybatis配置文件
<?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>
<!--settings:控制mybatis全局行为-->
<settings>
<!--设置mybatis输出日志-->
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<!--设置别名 可选-->
<typeAliases>
<!--package:把包下面的所有类名作为别名name:实体类所在的包名-->
<package name="mapper"/>
</typeAliases>
<!-- sql映射文件的位置 -->
<mappers>
<!--name是包名,这个包中所有mapper.xml一次加载-->
<package name="mapper"/>
<!-- <mapper resource="com/zn/day4/IAccountMappert.xml"/>-->
</mappers>
</configuration>
(8)书写测试类
package com.wx.mapper;
import com.wx.Acount;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.List;
import static org.junit.Assert.*;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:application.xml")
public class AcountMapperTest {
@Autowired
AcountMapper acountMapper;
@Test
public void findAllAcountTrue(){
List<Acount> acountMapperAll = acountMapper.findAll();
Assert.assertTrue(acountMapperAll.size() == 2);
}
@Test
public void findAllAcountFalse(){
List<Acount> acountMapperAll = acountMapper.findAll();
Assert.assertFalse(acountMapperAll.size() <= 0);
}
}
(9)运行结果(数据库中只有两条数据,一个检测成功是否正常,一个检测失败是否正常)
二月 15, 2023 3:22:33 下午 com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource
信息: Initializing c3p0 pool... com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 3, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, contextClassLoaderSource -> caller, dataSourceName -> 1hge92qaunal7mc11ctf87|24d4d7c9, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> com.mysql.cj.jdbc.Driver, extensions -> {}, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, forceSynchronousCheckins -> false, forceUseNamedDriverClass -> false, identityToken -> 1hge92qaunal7mc11ctf87|24d4d7c9, idleConnectionTestPeriod -> 0, initialPoolSize -> 3, jdbcUrl -> jdbc:mysql://localhost:3306/stage04frontassign?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 0, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 15, maxStatements -> 0, maxStatementsPerConnection -> 0, minPoolSize -> 3, numHelperThreads -> 3, preferredTestQuery -> null, privilegeSpawnedThreads -> false, properties -> {user=******, password=******}, propertyCycle -> 0, statementCacheNumDeferredCloseThreads -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, userOverrides -> {}, usesTraditionalReflectiveProxies -> false ]
JDBC Connection [com.mchange.v2.c3p0.impl.NewProxyConnection@44afefd5 [wrapping: com.mysql.cj.jdbc.ConnectionImpl@9a7a808]] will not be managed by Spring
==> Preparing: select * from acount;
==> Parameters:
<== Columns: id, name, money
<== Row: 1, zhangsan, 56
<== Row: 2, lisi, 44
<== Total: 2
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5328a9c1]
Disconnected from the target VM, address: '127.0.0.1:54752', transport: 'socket'
Process finished with exit code 0
三.动态SQL
1.解决当SQL的条件语句时字符串拼接很多麻烦的细节,如:字符串的SQL语句拼接是忘记加空格所导致的错误,还有条件的拼接号“+”等等。
四.今日报错总结
重点理解配置文件之间的联系,以及文件中每句代码代表什么意思,有的依赖没有引入因为是IOC、DI和事务时就已经引入的,新建项目后那些包也应该提前引入。
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in class path resource [application.xml]: Error setting property values; nested exception is org.springframework.beans.PropertyBatchUpdateException; nested PropertyAccessExceptions (1) are:
PropertyAccessException 1: org.springframework.beans.MethodInvocationException: Property 'dataSource' threw exception; nested exception is java.lang.NoClassDefFoundError: org/springframework/jdbc/datasource/TransactionAwareDataSourceProxy
解决办法:再次引入缺少的依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.2.2.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.2</version>
</dependency>