Atypora-root-url: img
一、mybatis初始配置
1、首先配置好maven环境,IDEA的setting等
在IDEA中创建一个Maven工程
new–project,–maven ,不选择任何,创建父工程
创建完成后 看一下setting中的maven设置是否正确
等待maven初始化完成后 删除Src
右键父目录new创建module,maven–
更改新module里面的pom.xml
缺少iml文件
在缺少.iml文件项目下运行mvn idea:module
,完成后将自动生成.iml文件
2、在pom文件中添加mybaits起步依赖和sql驱动
<!-- 添加mybatis组件-->
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<!-- 添加mysql数据库驱动包-->
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.25</version>
</dependency>
3、创建数据库脚本
CREATE DATABASE mydb;
CREATE TABLE admin(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(32) NOT NULL,
PASSWORD VARCHAR(32) NOT NULL,
age INT,
telephone VARCHAR(11)
);
INSERT INTO admin(NAME,PASSWORD,age,telephone)VALUES('ccc','000000',31,'12345678947');
INSERT INTO admin(NAME,PASSWORD,age,telephone)VALUES('ddd','000000',31,'12345678947');
INSERT INTO admin(NAME,PASSWORD,age,telephone)VALUES('bbb','000000',31,'12345678947');
COMMIT;
4、编写mybatis的配置文件
(src/main/resources/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>
<!-- envirorments表示mybatis的运行环境,这里mybatis可以定义多个环境-->
<environments default="mysql">
<environment id="mysql">
<!-- transactionManager表示事务管理器-->
<transactionManager type="JDBC"/>
<!-- dataSource表示数据源-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mydb?useUnicode=true&characterEncoding=UTF8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
</configuration>
5、编写实体对象
根据数据库表的字段来编写
public class Admin {
private int id;
private String name;
private String password;
private int age;
private String telephone;
使用alt+insert键 自动生成 set和get方法 还有tostring方法
6、对于mybatis而言,一张数据库对应一个映射文件,映射文件主要编写的sql语句(AdminMapper.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">
<!-- namespace唯一性 表示命名空间,这里写成唯一的就行-->
<mapper namespace="com.woniuxy.mapper.AdminMapper">
<select id="selectCount" resultType="int">
select count(*) from admin
</select>
</mapper>
编写完mapper文件之后,系统是找不到的,必须要在配置文件中进行注册,具体注册如下
mybatis-config.xml中
<mappers>
<mapper resource="mapper/AdminMapper.xml"></mapper>
</mappers>
7、编写测试文件
package com.woniuxy;
import static org.junit.Assert.assertTrue;
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 org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
public class AppTest
{
@Test
public void testMybatisQuickStart(){
//获取配置文件,根据配置文件获取输入流
InputStream in=null;
try {
in= Resources.getResourceAsStream("mybatis-config.xml");
} catch (IOException e) {
e.printStackTrace();
}
//获取SqlSessionFactory
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(in);
//通过SqlSessionFactory获取SqlSession对象
SqlSession sqlSession=sqlSessionFactory.openSession();
Object obj= sqlSession.selectOne("com.woniuxy.mapper.AdminMapper.selectCount");
if (obj instanceof Integer){
Integer count=(Integer) obj;
System.out.println("查询的个数是"+count);
}
//关闭sqlsession
sqlSession.close();
}
}
8、mybatis工作原理
(1)读取MyBatis配置文件mybatis-config.xml, myoatis-config.xml作为MyBatis的全局配置文件,配置了MyBatis的运行环境等信息,其中主要内容是获取数据库连接.
(2)加载映射文件Mapper.xml。 Mapper.xml文件即SQL映射文件,该文件中配置了操作数据库的SQL语句,需要在myBatis-config.xml中加载才能执行,mybatis-config.xml可以加载多个配置文件,每个配置文件对应数据库中的一张表。
(3 )构建会话工厂。通过MyBatis的环境等配置信息构建会话工SqlSessionFactory.
(4 )创建SqlSession对象。由会话工厂创建SqlSession对象,该对象中包含了执行SQL的所有方法。
(5 ) MyBatis底层定义了一个Executor接口来操作数据库,它会根据SqlSession传递的参数动态地生成需要执行的SQL语句,同时负责查询缓存的维护。
(6)在Executor接口的执行方法中,包含一个 MappedStatement类型的参数,该参数是对映射信息的封装,用于存储要映射的SQL语句的id、参数等。Mapper.xml这文件中一个SQL对应一个MappedStatement对象,SQL的id即是MappedStatement的id。
(7)输入参数映射。在执行方法时,MappedStatement对象会对用户执行SQL语句的输入参数进行定义(可以定义为Map、List类型、基本类型和POJO类型,Executor执行器会通过MappedStatement对象在执行SQL前,将输入的Java对象映射到SQL语句中。这里对输入参数的映射过程就类似于JDBC编程中对preparedStatement对象设置参数的过程.
(8)轮出结果映射。在数据库中执行完SQL语句后,,MappedStatement对象会对SQL执行输出的结果进行定义(可以定义为Mlap和List类型、基本类型、POJO类型)), Executor执行器会通过MappedStatement对象在执行SQL语句后,将输出结果映射至Java对象中。这种将输出结果映射到Java对象的过程就类似于JDBC编程中对结果的解析处理过程。
9、优化代码,编写MybatisUtil.java
package com.woniuxy.util;
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 MyBatisUtil {
private static SqlSessionFactory factory;
static {
//获取配置文件,根据配置文件获取输入流
InputStream in=null;
try {
in= Resources.getResourceAsStream("mybatis-config.xml");
} catch (IOException e) {
e.printStackTrace();
}
//获取SqlSessionFactory
factory=new SqlSessionFactoryBuilder().build(in);
}
//获取Sqlsession对象
public static SqlSession createSession(){
return factory.openSession();
}
//关闭session的方法
public static void closeSession(SqlSession sqlSession){
if (sqlSession!=null){
sqlSession.close();
}
}
}
测试
@Test
public void testMybatisUtil(){
SqlSession sqlSession = MyBatisUtil.createSession();
Object obj=sqlSession.selectOne("com.woniuxy.mapper.AdminMapper.selectCount");
if (obj instanceof Integer){
Integer count=(Integer) obj;
System.out.println("查询的个数是"+count);
}
MyBatisUtil.closeSession(sqlSession);
}
}
二、Mybatis 核心对象
src/main/java/com/woniuxy/mapper/AdminMapper.java
package com.woniuxy.mapper;
public interface AdminMapper {
public int getCount();
}
src/main/resources/mapper/AdminMapper.java
<?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名称就必须和src/main/java接口的名称必须一致-->
<mapper namespace="com.woniuxy.mapper.AdminMapper">
<select id="selectCount" resultType="int">
select count(*) from admin
</select>
</mapper>
编写数据库文件datasource.properties
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mydb?useUnicode=true&characterEncoding=UTF8
username=root
password=123456
引入数据库文件
<configuration>
<properties resource="datasource.properties"></properties>
<!-- envirorments表示mybatis的运行环境,这里mybatis可以定义多个环境-->
<environments default="mysql">
<environment id="mysql">
<!-- transactionManager表示事务管理器-->
<transactionManager type="JDBC"/>
<!-- dataSource表示数据源-->
<dataSource type="POOLED">
<!-- <property name="driver" value="com.mysql.jdbc.Driver"/>-->
<!-- <property name="url" value="jdbc:mysql://localhost:3306/mydb?useUnicode=true&characterEncoding=UTF8"/>-->
<!-- <property name="username" value="root"/>-->
<!-- <property name="password" value="123456"/>-->
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
三、日志记录
日志分类
1、业务日志
2、错误日志
(1)mybatis集成日志
这里用log4j为例
第一步,在pom.xml里添加组件
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
在resources中新建log4j.properties
log4j.rootLogger=DEBUG,stdout,fileAppender
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
#5p中的P代表级别 %m代表输出信息,%n代表换行
log4j.appender.fileAppender = org.apache.log4j.FileAppender
log4j.appender.fileAppender.File = E:/IDEA/log.log
# 日志输出地址
log4j.appender.fileAppender.Append = true
log4j.appender.fileAppender.Threshold = DEBUG
log4j.appender.fileAppender.layout=org.apache.log4j.PatternLayout
log4j.appender.fileAppender.layout.ConversionPattern = %-d{yyyy-MM-dd HH:MM:SS} [%t:%r] - [%p] %m%n
在mabatis中的configuration下新建setting
<settings>
<setting name="logImpl" value="LOG4J"/>
</settings>
测试类中
import static org.junit.Assert.assertTrue;
import com.woniuxy.mapper.AdminMapper;
import com.woniuxy.util.MyBatisUtil;
import org.apache.ibatis.session.SqlSession;
import org.apache.log4j.Logger;
import org.junit.Test;
public class AppTest
{
private Logger logger = Logger.getLogger(getClass());
@Test
public void testOperSqlSessionWithInterface()
{
SqlSession sqlSession= MyBatisUtil.createSession();
AdminMapper adminMapper=sqlSession.getMapper(AdminMapper.class);
int count=adminMapper.getCount();
logger.debug("共有"+count+"条数据");
System.out.println("结果是"+count);
MyBatisUtil.closeSession(sqlSession);
}
}
安装插件 grep console setting–>plugins 对日志分类级别的颜色
插件设置 setting–>左侧底部有grep console
四、配置类型别名
AdminMapper.java
import com.woniuxy.pojo.Admin;
public interface AdminMapper {
public int getCount();
public Admin selectAdminById(int id);
}
AdminMapper.xml
<select id="selectAdminById" parameterType="java.lang.Integer" resultType="com.woniuxy.pojo.Admin">
select * from admin where id=#{id}
</select>
apptest.java
@Test
public void testTypeAlias(){
SqlSession sqlSession= MyBatisUtil.createSession();
AdminMapper adminMapper=sqlSession.getMapper(AdminMapper.class);
Admin admin=adminMapper.selectAdminById(1);
logger.info(admin);
MyBatisUtil.closeSession(sqlSession);
}
五、设置别名
<!-- resulType表示返回类型,这里面一定要写全名,而不要只写类名
如果你觉得类全名不好写太长,可以设置别名,在mybatis-config.xml文件中 <typeAliases>
<typeAlias type="com.woniuxy.pojo.Admin" alias="Admin"></typeAlias>
</typeAliases>-->
<typeAliases><!--设置别名-->
<!-- <typeAlias type="com.woniuxy.pojo.Admin" alias="Admin"></typeAlias>-->
<package name="com.woniuxy.pojo"/>
</typeAliases>
alias定义的名字Admin 用admin也能搜索到
推荐 package方法名字不能随便叫,只能叫原来定义的名字
六、连接池
数据库连接池负责分配管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个
dataSource表示数据源type表示数据源类型
type的取值
pooled:使用连接池的数据源
unpooled:不使用连接池的数据源
JNDI:使用JNDI实现的数据源
mybatis内部定义了实现javax.sql.DataSource接口的UnpooledDataSource 、PooledDataSource类来定义UNPOOLED、Pooled类型的数据源
CTRL+N调出如下对话框进行搜索
七、LomBok学习
1、在pom.xml中添加依赖
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<scope>provided</scope>
</dependency>
<!-- 编译和测试的时候有用-->
2、IDEA中安装lombok插件
重启IDEA后 右下角有个小窗口 点Enable
如果关闭了 在setting中进行设置
4、编写lombok窗口
5、使用lombok的注释声明
@Data生成setter、getter、equal、toString、hasCode、无参构造方法
@Setter 只生成setter方法
@getter只生成getter方法
@AllArgsConstructor生成全参的构造方法
日志台文件变色区分
在IDEA中打开Setting,选中Plugins,输入框里搜索
Grep-Console
点击下载并安装
八、Mybatis单表的增删改查CRUD
AdminMapper.xml 映射文件
<insert id="add" parameterType="admin">
insert into admin(name,age,password,telephone)values (#{name},#{age},#{password},#{telephone})
</insert>
<delete id="delete" parameterType="int">
delete from admin where id=#{id}
</delete>
<update id="update" parameterType="admin">
update admin set name=#{name},password=#{password},age=#{age},telephone=#{telephone} where id=#{id}
</update>
<!-- 如果是list。resultType的值为该List集合中元素的类型-->
<select id="findAll" resultType="admin">
select * from admin
</select>
Apptest.java 测试
private Logger logger = Logger.getLogger(AppTest.class);
@Test
public void testAdd() {
SqlSession sqlSession = MyBatisUtil.createSession();
AdminMapper adminMapper=sqlSession.getMapper(AdminMapper.class);
try {
Admin admin=new Admin();
admin.setName("mocc");
admin.setAge(19);
admin.setPassword("12345678");
admin.setTelephone("13345546374");
adminMapper.add(admin);
sqlSession.commit();//提交
} catch (Exception e) {
sqlSession.rollback();//回滚
e.printStackTrace();
}
MyBatisUtil.closeSession(sqlSession);
}
@Test
public void testdelete(){
SqlSession sqlSession = MyBatisUtil.createSession();
AdminMapper adminMapper=sqlSession.getMapper(AdminMapper.class);
try {
adminMapper.delete(5);
sqlSession.commit();//提交 ctrl+alt+t 弹出try...catch窗口
} catch (Exception e) {
e.printStackTrace();
sqlSession.rollback();
}
MyBatisUtil.closeSession(sqlSession);
}
@Test
public void testupdate(){
SqlSession sqlSession = MyBatisUtil.createSession();
AdminMapper adminMapper=sqlSession.getMapper(AdminMapper.class);
Admin admin=new Admin();
admin.setId(5);
admin.setName("mappp");
admin.setAge(19);
admin.setPassword("12345678");
admin.setTelephone("13345546374");
try {
adminMapper.update(admin);
sqlSession.commit();//提交
} catch (Exception e) {
e.printStackTrace();
sqlSession.rollback();
}
MyBatisUtil.closeSession(sqlSession);
}
@Test
public void testFindAll(){
SqlSession sqlSession = MyBatisUtil.createSession();
AdminMapper adminMapper=sqlSession.getMapper(AdminMapper.class);
List<Admin> all= adminMapper.findAll();
for (Admin admin:all){
logger.info(admin);
}
MyBatisUtil.closeSession(sqlSession);
}
AdminMapper.java 接口
public void add(Admin admin);
public void delete(int id);
public void update(Admin admin);
public List<Admin> findAll();
九、Mybatis参数处理
1、单参数处理
1)接口
package com.woniuxy.mapper;
import com.woniuxy.pojo.Admin;
public interface AdminMapper {
public Admin selectAdminByName(String name);
}
2)映射文件
<mapper namespace="com.woniuxy.mapper.AdminMapper">
<select id="selectAdminByName" resultType="admin" parameterType="string">
-- parameterType="java.lang.String"
select * from admin where name=#{name}
</select>
</mapper>
3)测试文件
private Logger logger = Logger.getLogger(this.getClass());
@Test
public void testSingleParam(){
SqlSession sqlSession=MyBatisUtil.createSession();
AdminMapper adminMapper= sqlSession.getMapper(AdminMapper.class);
Admin admin=adminMapper.selectAdminByName("mocc");
logger.info(admin);
MyBatisUtil.closeSession(sqlSession);
}
4)观察控制台效果
通过控制台观察,输出的SQL语句使用了占位的方式,JDBC中如果要输入参数有两种方法
4.1)可以通过拼接SQL语句方式来完成
4.2)通过?占位的方式来完成
如果在mybatis中 使用了#{}的方式,他就是占位的方式
#{key} key的内容不是和接口中参数名称一致的,
这个key的内容,如果是单参数,mybatis限制的非常宽松,只要类型一样就可以,不管名字取成什么
2、多参数处理
2.1通过@Param方式来指定参数名称
1)接口
public interface AdminMapper {
public Admin selectAdminByNameAndAge(String name,int age);
}
2)映射文件
<select id="selectAdminByNameAndAge" resultType="admin" >
select * from admin where name like concat('%',#{name},'%') AND age>#{age}
</select>
3)测试代码
@Test
public void testMultiParaml(){
SqlSession sqlSession=MyBatisUtil.createSession();
AdminMapper adminMapper= sqlSession.getMapper(AdminMapper.class);
Admin admin=adminMapper.selectAdminByNameAndAge("s",30);
logger.info(admin);
MyBatisUtil.closeSession(sqlSession);
}
测试观察控制台—报错
如果写的多个参数,这时候发现并没有找到
<!-- <select id="selectAdminByNameAndAge" resultType="admin" >-->
<!-- select * from admin where name like concat('%',#{arg0},'%') AND age>#{arg1}-->
<!-- </select>-->
<select id="selectAdminByNameAndAge" resultType="admin" >
select * from admin where name like concat('%',#{param1},'%') AND age>#{param2}
</select>
Mybatis的规定,如果是多个参数,这个时候可以使用arg0,arg1,arg2,arg3,arg4…argn或者使用param1,param2…paramn
如上规定不灵活,如果程序员自己定义名称,需要通过@Param
2.2通过实体对象来传值
通过实体对象来传值,实际上#{key} key的值是和实体对象中的属性名要保持一致的
测试
@Test
public void testMultiParam2(){
SqlSession sqlSession=MyBatisUtil.createSession();
AdminMapper adminMapper= sqlSession.getMapper(AdminMapper.class);
Admin entity = new Admin();
entity.setName("b");
entity.setAge(30);
Admin admin=adminMapper.selectAdminByEntity(entity);
logger.info(admin);
MyBatisUtil.closeSession(sqlSession);
}
2.3通过Map集合来传值
接口
public interface AdminMapper {
public Admin selectAdminByName(String name);
//public Admin selectAdminByNameAndAge(String name,int age);
public Admin selectAdminByNameAndAge(@Param("name") String name,@Param("age") int age);
public Admin selectAdminByEntity(Admin admin);
public Admin selectAdminByMap(Map<String,Object> map);
}
AdminMapper.xml映射
<select id="selectAdminByMap" resultType="admin">
select * from admin where name like concat('%',#{name},'%') AND age>#{age}
</select>
测试
@Test
public void testMultiParam3(){
SqlSession sqlSession=MyBatisUtil.createSession();
AdminMapper adminMapper= sqlSession.getMapper(AdminMapper.class);
Map<String,Object> map=new HashMap<String,Object>();
map.put("name","b");
map.put("age",30);
Admin admin=adminMapper.selectAdminByMap(map);
logger.info(admin);
MyBatisUtil.closeSession(sqlSession);
}
如果使用map作为参数的话,那么#{key} key的值是和map中的键是相同的这样就能绑定到一起了
如上三种方式处理多参数的传值问题,实际上底层都是map集合
这三种实际开发中都有用途。
一般参数不超过三个的请使用第一种,参数超过3种以上可以使用实体或者map对象
3、${}和#{}区别
#{}作为参数来传递数据的,通过控制台观察,我们发现,如果使用#{} 这种操作,相当于JDBC中预处理,使用?来进行站位,如果使用 , 相 当 于 J D B C 中 的 S t a t e m e n t 原 生 J D B C 不 支 持 占 位 符 的 地 方 就 要 使 用 {},相当于JDBC中的Statement 原生JDBC不支持占位符的地方就要使用 ,相当于JDBC中的Statement原生JDBC不支持占位符的地方就要使用{}进行取值,
#{}这就是JDBC中的预处理操作,PreparedStatement来完成预处理语句的执行操作,在预处理操作中使用?来占位,后续再赋值
${}这种方式是JDBC中的拼接方式(字符串)来完成的,
在使用${}完成查询的过程中,需要注意的就是必须要在接口方法中参数前面带@Param(不管是一个参数还是多个参数)
在使用${}过程中会出现SQL注入,安全性低,使用#{}不会出现这个问题(例子 Sm’Th ‘Sm’Th’ 前两个单引号形成闭合)
两种方法都可以使用的情况下,尽量使用#{}
1)例如排序不支持占位就不能使用#{},只能使用${}
2)例如在分表操作中就不能使用#{},只能使用${}
3)${}也可以完成#{}相同的功能,进行参数传递,只不过它需要外面带单引号
注意:${}可能会引发SQL注入,#{}不会
先写pojo普通Java类,再写接口类,再写xml SQL语句,然后在resources把XXX-config文件中的mappers目录地址写进去
4、返回结果
(1)、返回单个结果
<select id="selectStudentBysno" resultType="com.woniuxy.pojo.Student" parameterType="int">
select * from student where sno=#{sno}
</select>
resultType填写类名或者类别名
返回值:表名(键=值,键=值)
(2)、返回List集合
<select id="selectStudents" resultType="com.woniuxy.pojo.Student">
select * from student
</select>
resultType填写类名或别名,没有进行传参
如果返回值类型是List类型,那么在映射配置文件中节点中的resultType的属性值是这个List集合中的元素类型
public List<Student> selectStudents();
public void testselectStudents()
{
SqlSession sqlSession = MyBatisUtil.createSession();
StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
List<Student> students =studentMapper.selectStudents();
for (Student student:students){
logger.info(student);
}
MyBatisUtil.closeSession(sqlSession);
}
(3)、返回Map
3.1返回Map类型的单个对象
接口、xml SQL语句、测试语句
public Map<String,Object> selectStudentno(@Param("sno") int sno);
<select id="selectStudentno" parameterType="int" resultType="java.util.Map">
select * from student where sno=#{sno}
</select>
@Test
public void testsselectStudentno()
{
SqlSession sqlSession = MyBatisUtil.createSession();
StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
Map map=studentMapper.selectStudentno(2007010118);
logger.info(map);
MyBatisUtil.closeSession(sqlSession);
}
map返回值,{键=值,键=值} 逗号分割
3.2返回多条记录以Map类型作为返回值
接口
@MapKey("sname")
public Map selectStudentSnameLike(@Param("sname") String sname);
映射文件
<select id="selectStudentSnameLike" parameterType="String" resultType="com.woniuxy.pojo.Student">
select * from student where sname like concat(#{sname},'%')
</select>
测试
@Test
public void testselectStudentSnameLike()
{
SqlSession sqlSession = MyBatisUtil.createSession();
StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
Map<String,Student> map=studentMapper.selectStudentSnameLike("刘");
logger.info(map);
MyBatisUtil.closeSession(sqlSession);
}
5、数据库字段和实体不一致的解决方法
(1)、使用AS来取别名
(2)、通过在mybatis的配置文件中设置驼峰命名来完成
①如果你的项目采用驼峰命名法,那么可以在mybatis-config.xml文件中进行设置
<settings>
<setting name="mapUnderscoreToCamelCase" value="true" /> </settings>
②数据库字段和属性person_id=========>personId
③通过resultMap的方式完成(推荐使用)
6、类的关联关系
(1)关联关系的分类
①一对一关联
例: 一人一身份证,一个身份证对应一个人
包装类方式(了解)
数据库表
#身份证表
create table tb_card(cid int primary key auto_increment,code varchar(18))
#测试数据
INSERT INTO tb_card(CODE)VALUES('370304199910101234');
#公民表
CREATE TABLE tb_person(pin int primary key auto_increment,
name varchar(50),
age int,
sex varchar(20),
idcard int UNIQUE,
FOREIGN KEY(idcard) REFERENCES tb_card(cid))
#测试数据
insert into tb_person(name,age,sex,idcard)VALUES('张三',32,'男',1)
创建实体类对象
@Data
public class Card {
private int cid;
private String code;
}
@Data
public class Person {
private int pid ;
private String name;
private int age;
private String sex;
private Card card;
}
@Data
public class PersonCard extends Person {
private String code;
}
mapper
public interface PersonMapper {
public List<PersonCard> findAll();
}
映射文件
<resultMap id="personMap" type="PersonCard">
<id column="pid" property="pid"></id>
<result column="name" property="name"></result>
<result column="age" property="age"></result>
<result column="sex" property="sex"></result>
<result column="code" property="code"></result>
</resultMap>
<select id="findAll" resultMap="personMap" >
SELECT p.*,c.code from tb_person as p INNER JOIN tb_card c on p.idcard=c.cid
</select>
测试类
@Test
public void test1()
{
SqlSession sqlSession= MyBatisUtil.createSession();
PersonMapper personMapper= sqlSession.getMapper(PersonMapper.class);
List<PersonCard> all= personMapper.findAll();
for (PersonCard p:all){
logger.info(p.getName()+"-->"+p.getCode());
}
MyBatisUtil.closeSession(sqlSession);
}
resultMap方式
创建实体类对象
package com.woniuxy.pojo;
import lombok.Data;
@Data
public class Card {
private int cid;
private String code;
}
package com.woniuxy.pojo;
import lombok.Data;
@Data
public class Person {
private int pid ;
private String name;
private int age;
private String sex;
private Card card;//关联对象
}
mapper
package com.woniuxy.mapper;
import com.woniuxy.pojo.Person;
import java.util.List;
public interface PersonMapper {
public List<Person> SelectAllPerson();
}
映射文件
<?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名称就必须和src/main/java接口的名称必须一致-->
<mapper namespace="com.woniuxy.mapper.PersonMapper">
<resultMap id="personMap" type="person">
<id column="pid" property="pid"></id>
<result column="name" property="name"></result>
<result column="age" property="age"></result>
<result column="sex" property="sex"></result>
<result column="cid" property="card.cid"></result>
<result column="code" property="card.code"></result>
</resultMap>
<select id="SelectAllPerson" resultMap="personMap" >
SELECT p.*,c.* from tb_person as p INNER JOIN tb_card c on p.idcard=c.cid
</select>
</mapper>
测试类
private Logger logger=Logger.getLogger(this.getClass());
@Test
public void TestSelectAllPerson()
{
SqlSession sqlSession = MyBatisUtil.createSession();
PersonMapper personMapper = sqlSession.getMapper(PersonMapper.class);
List<Person> all = personMapper.SelectAllPerson();
for (Person p:all){
logger.info(p.getName()+"\t"+p.getSex()+"\t"+p.getCard().getCode());
}
MyBatisUtil.closeSession(sqlSession);
}
association嵌套映射
<?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名称就必须和src/main/java接口的名称必须一致-->
<mapper namespace="com.woniuxy.mapper.PersonMapper">
<resultMap id="personMap" type="person">
<id column="pid" property="pid"></id>
<result column="name" property="name"></result>
<result column="age" property="age"></result>
<result column="sex" property="sex"></result>
<!-- association:一对多的节点属性 常用属性如下
property关联对象的名称
javaType关联对象的类型(类全名,别名)
-->
<association property="card" javaType="card">
<id property="cid" column="cid"></id>
<result property="code" column="code"></result>
</association>
</resultMap>
<select id="selectAllPerson" resultMap="personMap" >
SELECT p.*,c.* from tb_person as p INNER JOIN tb_card c on p.idcard=c.cid
</select>
</mapper>
测试
private Logger logger = Logger.getLogger(this.getClass());
@Test
public void shouldAnswerWithTrue()
{
SqlSession sqlSession = MyBatisUtil.createSession();
PersonMapper personMapper=sqlSession.getMapper(PersonMapper.class);
List<Person> all =personMapper.selectAllPerson();
for(Person p:all)
{
logger.info(p.getName()+"\t"+p.getSex()+"\t"+p.getCard().getCode());
}
MyBatisUtil.closeSession(sqlSession);
}
association分步查询
public interface CardMapper {
public Card selectCardByCidWithStep(@Param("cid") int cid);
}
public interface PersonMapper {
public List<Person> selectAllPerson();
}
<mapper namespace="com.woniuxy.mapper.CardMapper">
<select id="selectCardByCidWithStep" parameterType="int" resultType="card">
select * from tb_card where cid=#{cid}
</select>
</mapper>
<mapper namespace="com.woniuxy.mapper.PersonMapper">
<resultMap id="personMap" type="person">
<id column="pid" property="pid"></id>
<result column="name" property="name"></result>
<result column="age" property="age"></result>
<result column="sex" property="sex"></result>
<!-- association:一对多的节点属性 常用属性如下
property关联对象的名称
javaType关联对象的类型(类全名,别名)
select 分布查询的方法
column:外键的值
-->
<association property="card" javaType="card" select="com.woniuxy.mapper.CardMapper.selectCardByCidWithStep" column="idcard">
<id property="cid" column="cid"></id>
<result property="code" column="code"></result>
</association>
</resultMap>
<select id="selectAllPerson" resultMap="personMap" >
SELECT p.*,c.* from tb_person as p INNER JOIN tb_card c on p.idcard=c.cid
</select>
</mapper>
private Logger logger = Logger.getLogger(this.getClass());
@Test
public void shouldAnswerWithTrue()
{
SqlSession sqlSession = MyBatisUtil.createSession();
PersonMapper personMapper=sqlSession.getMapper(PersonMapper.class);
List<Person> all =personMapper.selectAllPerson();
for(Person p:all)
{
logger.info(p.getName()+"\t"+p.getSex()+"\t"+p.getCard().getCode());
}
MyBatisUtil.closeSession(sqlSession);
}
1+n次
分布查询的延迟加载
什么是延迟加载︰俗称懒加载(Lazy )︰需要的才去查询的这种情况。
为什么需要延迟加载:为了提高性能,把需要的信息不立即查出来,需要的时候再查。
如下操作虽然我只是需要人员本身信息,控制台也输出本身自己的信息,但是我们观察SQL语句,大家会发现,依然做的是立即加载
第一种方法:设置mybatis-config.xml
<settings>
<!-- lazyLoadingEnabled 设置全局延迟加载,默认false表示没有开启延迟加载,这里设置为true表示延迟加载-->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 设置按需加载-->
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
第二种方法:通过在association中设置fetchType的值来设置延迟加载(局部)
<association property="card"
javaType="card"
select="com.woniuxy.mapper.CardMapper.selectCardByCidWithStep"
column="idcard"
fetchType="lazy">
<!--lazy延迟加载eager立即加载-->
<id property="cid" column="cid"></id>
<result property="code" column="code"></result>
</association>
②一对多关联
例:一个区对应多个街道
③多对多关联
一个老师对应多个学生,一个学生对应多个老师