什么是mybatis
- 持久层框架
- 支持定制化SQL,存储过程和高级映射
- 几乎避免了所有的JDBC代码
如何获取mybatis
- maven仓库
- Github
持久层
数据持久化
- 持久化就是将程序的数据从瞬时状态,转化成持久状态
- 内存数据:断电即失
- 数据库,io文件持久化
mybatis优点:
- sql和代码分离,提高了程序的可维护性
- 提供了映射标签,支持对象与数据库的orm字段关系映射
- 支持动态sql
编写程序
-
导依赖包,mybatis、mysql、junit、注意静态资源到处问题
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId> <artifactId>MyPractice</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <!--版本锁定--> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.7</maven.compiler.source> <maven.compiler.target>1.7</maven.compiler.target> <spring.version>5.2.2.RELEASE</spring.version> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.16.10</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.22</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.1</version> </dependency> </dependencies> <!-- 静态资源导出问题--> <build> <resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>true</filtering> </resource> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>true</filtering> </resource> </resources> </build> </project>
-
mybatis配置文件,sqlSesisionConfig.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> <!-- 配置包的别名,这样我们在mapper中定义时,就不需要使用类的全限定名称,只需要使用类名即可 --> <typeAliases> <package name="mybatis.pojo"/> </typeAliases> <!-- 数据库配置 --> <environments default="mysql"> <environment id="mysql"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/my?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8"/> <property name="username" value="root"/> <property name="password" value="666666"/> </dataSource> </environment> </environments> <!-- mybatis的映射配置文件 --> <mappers> <mapper resource="mybatis/dao/adminMapper.xml"/> </mappers> </configuration>
-
pojo实体类
package mybatis.pojo; /** *作者: 柯神_ *时间: 15:09 *日期: 2020/11/9 *User: 蜘蛛啊全是腿儿 **/ public class Admin { private long adminId; private String adminName; private String adminPassword; public long getAdminId() { return adminId; } public void setAdminId(long adminId) { this.adminId = adminId; } public String getAdminName() { return adminName; } public void setAdminName(String adminName) { this.adminName = adminName; } public String getAdminPassword() { return adminPassword; } public void setAdminPassword(String adminPassword) { this.adminPassword = adminPassword; } @Override public String toString() { return "Admin{" + "adminId=" + adminId + ", adminName='" + adminName + '\'' + ", adminPassword='" + adminPassword + '\'' + '}'; } }
-
dao接口
public interface AdminDao { List<Admin> find(); }
-
mapper映射文件
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="mybatis.dao.AdminDao"> <select id="find" resultType="admin" > select * from admins </select> </mapper>
-
测试
@Test public void mybatis(){ try { //通过Resources读取配置文件 InputStream inputStream = Resources.getResourceAsStream("sqlSessionConfig.xml"); //通过配置文件去建立一个SqlSessionFactory工厂 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //SqlSessionFactory工厂生产SqlSession对象 SqlSession sqlSession = sqlSessionFactory.openSession(true); //通过SqlSession对象,拿到动态代理对象 AdminDao adminDao = sqlSession.getMapper(AdminDao.class); List<Admin> admins = adminDao.find(); System.out.println(admins); } catch (IOException e) { e.printStackTrace(); }
在编写程序的过程中可能遇到的问题
-
映射文件没有注册在mybatis的配置文件中
<!-- mybatis的映射配置文件 --> <mappers> <mapper resource="mybatis/dao/adminMapper.xml"/> </mappers>
-
绑定接口错误
<mapper namespace="mybatis.dao.AdminDao">
-
方法名不对
<!--id对应dao接口中的方法名--> <select id="find" resultType="admin" >
-
maven资源导出问题
<!-- 静态资源导出问题--> <build> <resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>true</filtering> </resource> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>true</filtering> </resource> </resources> </build>
万能map
当数据库中的字段过多,应该优先考虑使用Map,key可以不必和类中的属性名一致
int addByMap(Map<String,Object> map);
<insert id="addByMap" parameterType="map">
insert into admins (adminId,adminName,adminPassword) values(#{a},#{b},#{c})
</insert>
Map<String,Object> map = new HashMap<>();
map.put("a","6");
map.put("b","强强");
map.put("c","999999");
int add = adminDao.addByMap(map);
if (add>0){
System.out.println(map.get("b") + "插入成功!");
}
模糊查询
1.在执行代码的时候传递通配符% %
List<Admins> admins = adminDao.getLike("%神%");
<select id="getLike" resultType="admins" >
select * from admins where adminName like #{value}
</select>
2.在sql拼接中使用通配符
List<Admins> admins = adminDao.getLike("神");
<select id="getLike" resultType="admins" >
select * from admins where adminName like "%"#{value}"%"
</select>
配置文件中
环境配置(environments),可以配置多个环境,但是只能选取一个
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/my?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8"/>
<property name="username" value="root"/>
<property name="password" value="666666"/>
</dataSource>
</environment>
<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/my?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8"/>
<property name="username" value="admin"/>
<property name="password" value="99999"/>
</dataSource>
</environment>
</environments>
属性(properties),可以引入外部文件,优先使用外部文件
<properties resource="db.properties">
<property name="username" value="root"/>
<property name="password" value="666666"/>
</properties>
取别名(typeAliases)
- package,为这个包下的所有类取别名,默认当前类名并且首字母变为小写
<typeAliases>
<package name="mybatis.pojo"/>
</typeAliases>
- typeAlias, 为当前类取别名
<typeAliases>
<typeAlias type="admin" alias="com.my.pojo.Admin"/>
<typeAlias type="admin2" alias="com.my.pojo.Admin2"/>
</typeAliases>
3.注解,Alias(" ")标注在类上,为当前类取别名
@Alias("adc")
public class Admin{
___________
}
设置(settings)
<settings>
<!-- 缓存是否开启,默认是开启的-->
<setting name="cacheEnable" value="true"/>
<!-- 懒加载,默认为false-->
<setting name="lazyLoadingEnable" value="false"/>
<!-- 开启驼峰命名规则,默认为false-->
<setting name="mapUnderscoreToCamelCase" value="false"/>
<!-- 指定mybatis日志的具体实现-->
<setting name="logImpl" value="LOG4J"/>
</settings>
映射器(mappers),用来注册绑定mapper映射文件
-
资源路径,resource路径(推荐使用,可以随意用!)
<mappers> <mapper resource="mybatis/dao/adminMapper.xml"/> <mapper resource="mybatis/dao/adminMapper1.xml"/> <mapper resource="mybatis/dao/adminMapper2.xml"/> </mappers>
-
url(可以说已经被淘汰,太繁琐)
<mappers> <mapper url="D:///Users/mybatis/dao/adminMapper.xml"/> <mapper url="D:///Users/mybatis/dao/adminMapper1.xml"/> <mapper url="D:///Users/mybatis/dao/adminMapper2.xml"/> </mappers>
-
class,全限定类名(最好也不要使用,接口名和映射文件必须同名,否则会出现一些问题)
<mappers> <mapper class="mybatis.dao.adminMapper"/> <mapper class="mybatis.dao.adminMapper1"/> <mapper class="mybatis.dao.adminMapper2"/> </mappers>
-
package,将包内的都注册为映射器 (最好也不要使用,接口名和映射文件必须同名,否则会出现一些问题)
<mappers> <package name="com.my.dao"/> </mappers>
resultMap,结果集映射
解决实体类的属性名,和数据库中的字段名不一致问题
1.简单结果映射
<resultMap id="adminMap" type="admins">
<!--column->数据库字段名,property->实体类的属性名。-->
<result column="adminId" property="adminId"/>
<result column="adminName" property="adminName"/>
<result column="adminPassword" property="password"/>
</resultMap>
<select id="getLike" resultMap="adminMap">
select * from admins where adminName like "%"#{value}"%"
</select>
2.复杂结果映射
2.1. association,一个复杂类型的关联(一个对象使用这个关联)。适用于一对一和多对一的关系
<!--按查询嵌套处理 ①查询所有人的信息 ②根据查询出来的外键id,寻找对应的书籍信息
(有点。。。太绕了,莫名其妙的null问题)-->
<select id="find" resultMap="AB" >
select * from admins
</select>
<resultMap id="AB" type="admins">
<result column="adminId" property="adminId"/>
<result column="adminName" property="adminName"/>
<result column="adminPassword" property="password"/>
<association property="bookes" column="bookesId"
javaType="bookes" select="getB">
</association>
</resultMap>
<select id="getB" resultType="bookes">
select * from bookes where bookID=#{id}
</select>
<!-- 按结果嵌套处理-->
<select id="find" resultMap="AB" >
select a.adminId,a.adminName,b.bookName,b.detail from admins a,bookes b
where a.bookesId=b.bookID
</select>
<resultMap id="AB" type="admins">
<result column="adminId" property="adminId"/>
<result column="adminName" property="adminName"/>
<result column="adminPassword" property="password"/>
<association property="bookes" javaType="bookes">
<result column="bookId" property="bookId"/>
<result column="bookName" property="bookName"/>
<result column="bookCounts" property="bookCounts"/>
<result column="detail" property="detail"/>
</association>
2.2. collection,一个复杂类型的集合(一个集合使用这个关联),适用于一对多和多对多的关系
<!-- 按结果嵌套处理-->
<select id="findU" resultMap="BA" >
select * from admins a,bookes b
where a.bookesId=b.bookID and b.bookID=#{id}
</select>
<resultMap id="BA" type="bookes">
<result column="bookId" property="bookId"/>
<result column="bookName" property="bookName"/>
<result column="bookCounts" property="bookCounts"/>
<result column="detail" property="detail"/>
<collection property="admins" ofType="admins">
<result column="adminId" property="adminId"/>
<result column="adminName" property="adminName"/>
<result column="adminPassword" property="password"/>
</collection>
</resultMap>
<!--按照查询嵌套处理 (有点。。。太绕了,莫名其妙的null问题)-->
<select id="findU" resultMap="BA">
select * from bookes b
where b.bookID=#{id}
</select>
<resultMap id="BA" type="bookes">
<result column="bookId" property="bookId"/>
<result column="bookName" property="bookName"/>
<result column="bookCounts" property="bookCounts"/>
<result column="detail" property="detail"/>
<collection property="admins"
ofType="admins" select="getAById" column="bookId"/>
</resultMap>
<select id="getAById" resultType="admins">
select * from admins where bookesId=#{bookId}
</select>