1.创建项目
groupid和artifactId被统称为“坐标”是为了保证项目唯一性而提出的,如果你要把你项目弄到maven本地仓库去,你想要找到你的项目就必须根据这两个id去查找。 groupId和artifactId是maven管理项目包时用作区分的字段,就像是地图上的坐标。 artifactId:artifactId一般是项目名或者模块名。 groupId:groupId分为几个字段,例如cn.com.fullstack,前面的com叫【域】,后面的是你自己起的域名。 groupId一般分为多个段,这里我只说两段,第一段为域,第二段为公司名称。域又分为org、com、cn等等许多,其中org为非营利组织,com为商业组织。举个apache公司的tomcat项目例子:这个项目的groupId是org.apache,它的域是org(因为tomcat是非营利项目),公司名称是apache,artigactId是tomcat。
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.2</version>
<relativePath/>
</parent>
<groupId>com.dai</groupId>
<artifactId>springboot-web</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot-web</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.6</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-autoconfigure</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.7</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.9</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
<include>**/*.yml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
</project>
2.配置文件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">
<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/mybatis?userSSL=false&useUnicode=true&characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/dai/mapper/UserMapper.xml"/>
</mappers>
</configuration>
将UserMapper.xml配置到mybatis-config.xml文件中
<mappers>
<mapper resource="com/dai/mapper/UserMapper.xml"/>
</mappers>
2.1映射器mappers
方式一
<mappers>
<mapper resource="com/dai/mapper/UserMapper.xml"/>
</mappers>
方式二
<mppers>
<mpper class="com.dai.mapper.UserMapper"/>
</mppers>
注意
接口和他的Mapper配置文件必须同名!! 接口和他的Mapper配置文件必须要在同一个包下!! 方式三
<mppers>
<package name="com.dai.mapper"/>
</mppers>
接口和他的Mapper配置文件必须同名!! 接口和他的Mapper配置文件必须要在同一个包下!!
3.MybatisUtils工具类
从mybatis-config.xml文件中获取数据源,创建sqlSessionFactory中获取sqlSession实例。
package com.dai.utils;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
public class MybatisUtils {
private static SqlSessionFactory sqlSessionFactory;
static{
try {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession();
}
}
3.1、作用域(Scope)和生命周期
生命周期,和作用域,是至关重要的,因为错误的使用会导致非常严重的并发问题。 SqlSessionFactoryBuilder 一旦创建了SqlSessionFactory,就不需要他了 局部变量 SqlSessionFactory 说白了就是可以想象为:数据库连接池 SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例 因此 SqlSessionFactory 的最佳作用域是应用作用域 最简单的就是使用单例模式或者静态单例模式。 SqlSession 连接到连接池的一个请求 SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。 用完之后要赶紧关闭,否则资源被占用
4.entity类
package com.dai.entity;
public class User {
Integer id;
String name;
String pwd;
public User() {
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", pwd='" + pwd + '\'' +
'}';
}
}
5.UserMapper接口
package com.dai.mapper;
import com.dai.entity.User;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface UserMapper {
User getUserInfo(int id);
int save (User user);
int update (User user);
int deleteById (int id);
List<User> selectAll ();
List<User> getUserList();
}
6.UserMapper.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.dai.mapper.UserMapper">
<-----接口方法------返回数据类型>
<select id="getUserList" resultType="com.dai.entity.User">
select * from mybatis.user
</select>
<select id="getUserById" parameterType="int" resultType="com.dai.entity.User" >
select * from mybatis.user where id = #{id};
</select>
<select id="getUserById" parameterType="int" resultType="com.dai.entity.User" >
select * from mybatis.user where id = #{id};
</select>
<update id="updateUSer" parameterType="com.dai.entity.User">
update mybatis.user set name=#{name},pwd=#{pwd} where id=#{id};
</update>
<delete id="delUser" parameterType="int">
delete from mybatis.user where id = #{id};
</delete>
7. MyTest测试类
package com.dai;
import com.dai.entity.User;
import com.dai.mapper.UserMapper;
import com.dai.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.List;
public class MyTest {
@Test
public void test(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper userDao = sqlSession.getMapper(UserMapper.class);
List<User> userList = userDao.getUserList();
for(User user : userList){
System.out.println(user);
}
sqlSession.close();
}
}
8.易错点
配置文件没有注册 绑定接口错误 方法名不对 返回类型不对 resultType Maven导出资源问题
标签不匹配的错误 resource绑定mapper,需要使用路径 程序配置文件必须符合规范! NullPointerException,没有注册资源 例作用域问题 输出的xml文件中存在中文乱码问题 maven资源没有导出问题!
9.resultMap 结果集映射
<resultMap id="UserMap" type="user">
<result column="id" property="id"/>
<result column="name" property="name"/>
<result column="pwd" property="password"/>
</resultMap>
<select id="getUserById" parameterType="int" resultMap="UserMap" >
select * from mybatis.user where id = #{id};
</select>
resultMap元素是MyBatis中最重要最强大的元素 ResultMap的设计思想是,对于简单的语句根本不需要配置显示的结果映射,而对于复杂一点的语句只需要描述他们的关系就行了 ResultMap 最优秀的地方在于,虽然你已经对他相当了解了,但你根本就不需要显示的用到他们 如果世界总是这么简单就好了
10.日志工厂
SLEF4 LOG4J 【掌握】 LOG4J2 JDK_LOGGING COMMONS_LOGGING STDOUT_LOGGING【掌握】 NO_LOGGING
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
导包
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
日志格式配置log4j.properties
#将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码
log4j.rootLogger = DEBUG,console ,file
#控制台输出的相关设置
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.Threshold = DEBUG
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern = [%c]-%m%n
#文件输出的相关设置
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File = ./log/kun.log
log4j.appender.file.MaxFileSize = 10mb
log4j.appender.file.Threshold = DEBUG
log4j.appender.file.layout = org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern = [%p][%d{yy-MM-dd}][%c]%m%n
#日志输出级别
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
<settings>
<setting name="logImpl" value="LOG4J"/>
</settings>
使用log4j日志 1.在要使用Log4j的类中,导入包import org.apache.log4j.Logger; 2.日志对象,参数为当前类的class
static Logger logger = Logger.getLogger(UserMapper.class);
3.日志级别
logger.info("info:进入了testLog4j");
logger.debug("debug:进入了testLog4j");
logger.error("error:进入了testLog4j");
11.多对一结果映射
多个学生,对应老师 对于这边而言,关联。。 多个学生,关联一个老师【多对一】 对于老师而言,集合。。 一个老师,有很多学生 【一对多】
11.1按照查询嵌套处理
<select id="getStudent" resultMap="StudentTeacher">
select * from student
</select>
<resultMap id="StudentTeacher" type="student">
<result property="id" column="id"/>
<result property="name" column="name"/>
<collection property="teacher" column="tid" javaType="teacher" select="getTeacher"/>
</resultMap>
<select id="getTeacher" resultType="teacher">
select * from teacher where id = #{id}
</select>
11.2按照结果嵌套 处理
<select id="getStudent2" resultMap="StudentTeacher2">
select s.id sid , s.name sname, t.name tname
from student s,teacher t
where s.tid=t.id
</select>
<resultMap id="StudentTeacher2" type="student">
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<association property="teacher" javaType="teacher">
<result property="name" column="tname"></result>
</association>
</resultMap>
12.一对多处理
12.1按照查询嵌套处理
<select id="getTeacher2" resultMap="TeacherStudent2">
select * from mybatis.teacher where id=#{tid};
</select>
<resultMap id="TeacherStudent2" type="Teacher">
<collection property="students" javaType="ArrayList" ofType="Student" select="getStudent" column="id"/>
</resultMap>
<select id="getStudent" resultType="Student">
select * from mybatis.student where tid=#{tid};
</select>
12.2按照结果嵌套查询
<select id="getTeacher" resultMap="TeacherStudent">
select s.id sid, s.name sname, t.name tname, t.id tid
from student s, teacher t
where s.tid = t.id and t.id=#{tid}
</select>
<resultMap id="TeacherStudent" type="Teacher">
<result property="id" column="tid"/>
<result property="name" column="tname"/>
<collection property="students" ofType="Student">
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<result property="tid" column="tid"/>
</collection>
</resultMap>
总结
小结: 关联 - association 【多对一】 集合 - collection 【对多】 JavaType & ofType JavaType 用来指定实体类中属性的类型 ofType 用来指定映射到List或者集合中的pojo类型,泛型中的约束类型 注意点: 尽量保证SQL的可读性,尽量保证通俗易懂 注意一对多、多对一中,属性名和字段问题!! 如果问题不好排除,可以使用日志~ 建议Log4j 【其实默认的也够用了】
13.动态SQL
13.1if
<select id="queryBlogIF" parameterType="map" resultType="blog">
select * from mybatis.blog where 1=1
<if test="title != null">
and title = #{title}
</if>
<if test="author != null">
and author = #{author}
</if>
</select>
13.2choose (when,otherwise)
<select id="queryBlogChoose" parameterType="map" resultType="blog">
select * from mybatis.blog
<where>
<choose>
<when test="title != null">
title = #{title}
</when>
<when test="author != null">
and author = #{author}
</when>
<otherwise>
and views=#{views}
</otherwise>
</choose>
</where>
</select>
13.3trim (where, set)
<select id="queryBlogIF" parameterType="map" resultType="blog">
select * from mybatis.blog
<where>
<if test="title != null">
and title = #{title}
</if>
<if test="author != null">
and author = #{author}
</if>
</where>
</select>
所谓的动态SQL,本质还是SQL语句,只是我们可以在SQL层面,去执行一个逻辑代码
13.4sql片段
1.使用SQL标签抽取公共部分
<sql id="sql-if-title-author">
<if test="title != null">
title = #{title}
</if>
<if test="author != null">
and author = #{author}
</if>
</sql>
2.在需要使用的地方使用Include标签引用即可
<select id="queryBlogIF" parameterType="map" resultType="blog">
select * from mybatis.blog
<where>
<include refid="sql-if-title-author"/>
</where>
</select>
注意: 最好基于单表定义SQL片段!! sql标签不要存在where标签 因为他是动态的
13.5Foreach
select * from user where 1=1 and
<foreach item="id" collection="ids" open="(" separator="or" close=")">
#{id}
</foreach>
(id=1 or id=2 or id=3)
<select id="queryBlogForeach" parameterType="map" resultType="blog">
select * from mybatis.blog
<where>
<foreach item="id" collection="ids" open="and (" separator="or" close=")">
id=#{id}
</foreach>
</where>
</select>
|