只需要写mapper.xml文件,并把mapper.xml文件配置到全局配置文件中,才通过命名空间就可以找到指定的sql语句,并且封装为JavaBean对象
package com.zhw.mybatis.entities;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private Integer id;
private String userName;
private String address;
private Long birthday;
}
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.23</version>
</dependency>
<?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>
<!--通过properties标签加载外部的properties文件-->
<properties resource="db.properties"></properties>
<!-- 自定义别名-->
<typeAliases>
<package name="com.zhw.mybatis.entities"/>
</typeAliases>
<!--配置环境:可以配置多个环境,当defaul指向谁就用哪个环境-->
<environments default="mysql">
<!--配置mysql的环境-->
<environment id="mysql">
<!--配置事务类型-->
<transactionManager type="JDBC"></transactionManager>
<!--数据源-->
<dataSource type="POOLED">
<!--数据库的基本信息-->
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<!--加载映射文件-->
<mappers>
<mapper resource="mapper/UserMapper.xml"/>
</mappers>
</configuration>
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zhw.mybatis.entities.UserMapper">
<select id="selectUser" resultType="User" parameterType="int">
select * from tb_user where id = #{id}
select>
mapper>
#将等级为DEBUG的日志输出到conlose和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/zhw.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
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
#useUnicode是否使用字符集
#characterEncoding设置使用的字符集
#useSSL是否使用SSL协议通信
jdbc.username=root
jdbc.password=123456
/**
* 根据xml配置文件(全局配置文件)创建一个sqlSessionFactory对象
* @throws IOException
*/
@Test
public void test01() throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//不是单例模式
//获取sqlsession实例
SqlSession sqlSession = sqlSessionFactory.openSession();
// SqlSession sqlSession1 = sqlSessionFactory.openSession();
/**
*
sql的唯一标识statement – Unique identifier matching the statement to use.
*/
User user = sqlSession.selectOne("com.zhw.mybatis.entities.UserMapper.selectUser", 55);
System.out.println("用户为:"+user);
sqlSession.close();
}
主要功能是获取一个代理对象,用代理对象来做对数据库的操作
接口与配置文件动态绑定
package com.zhw.mybatis.mapper;
import com.zhw.mybatis.entities.User;
public interface UserMapper {
public User getUserById(Integer id);
}
<?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">
//指定UserMapper.java的全类名
<mapper namespace="com.zhw.mybatis.mapper.UserMapper">
//id为类中的方法
<select id="getUserById" resultType="User" parameterType="int">
select * from tb_user where id = #{id}
</select>
</mapper>
<mappers>
只需要将mapper.xml文件加入到mybatis全局配置文件中,mybatis会自己按照命名空间去找对应的mapper对象
<mapper resource="mybatis/mapper/PersonMapper.xml"/>
<mapper resource="mybatis/mapper/UserMapper.xml"/>
mappers>
package com.zhw.mybatis.test;
public class MyBatisTest {
@Test
public void test01() throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
//获取接口的代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.getUserById(1);
System.out.println(user);
sqlSession.close();
}
}
获取封装的接口对象,调用该方法,会执行映射的mapper.xml文件中的sql语句
DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
configuration>
//在类路径下
<properties resource="db.properties">properties>
<settings>
设置开启驼峰
<setting name="mapUnderscoreToCamelCase" value="true"/>
settings>
<typeAliases>
<typeAlias alias="Author" type="domain.blog.Author"/>
<typeAlias alias="Blog" type="domain.blog.Blog"/>
<typeAlias alias="Comment" type="domain.blog.Comment"/>
<typeAlias alias="Post" type="domain.blog.Post"/>
<typeAlias alias="Section" type="domain.blog.Section"/>
<typeAlias alias="Tag" type="domain.blog.Tag"/>
typeAliases>
<typeAliases>
<package name="domain.blog"/>
typeAliases>
引用的时候可大写,也可以小写
<environments default="dev">
<environment id="dev">
<transactionManager type="JDBC">transactionManager>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
dataSource>
environment>
<environment id="test">
<transactionManager type="JDBC">transactionManager>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
dataSource>
environment>
environments>
将sql映射注册到全局配置中
<mappers>
<mapper resource="mapper/UserMapper.xml"/>
<mapper resource="mapper/PersonMapper.xml"/>
<mapper resource="mapper/UserMapper.xml"/>
<mapper resource="mapper/PersonMapper.xml"/>
mappers>
<mappers>
<mapper class="org.mybatis.builder.AuthorMapper"/>
<mapper class="org.mybatis.builder.BlogMapper"/>
<mapper class="org.mybatis.builder.PostMapper"/>
mappers>
class用于将UserMapper.java接口注册到全局配置文件中,不用注册UserMapper.xml配置文件,但是UserMapper.xml配置文件必须在同一文件下
//注意必须xml文件和接口必须在同一包下
package com.zhw.mybatis.mapper;
public interface UserMapperAnnotation {
@Select("select * from tb_user where id = #{id}")
public User getUserById(Integer id);
}
//在全局配置文件中引入
<mappers>
<mapper class="com.zhw.mybatis.mapper.UserMapperAnnotation"/>
mappers>
@Test
public void test03() throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapperAnnotation mapper = sqlSession.getMapper(UserMapperAnnotation.class);
User user = mapper.getUserById(1);
System.out.println(user);
}
package com.zhw.mybatis2.entities;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private Integer id;
private String userName;
private String address;
private Long birthday;
}
DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties resource="db.properties">properties>
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
settings>
<typeAliases>
<package name="com.zhw.mybatis2"/>
typeAliases>
<environments default="dev">
<environment id="dev">
<transactionManager type="JDBC">transactionManager>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
dataSource>
environment>
<environment id="test">
<transactionManager type="JDBC">transactionManager>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
dataSource>
environment>
environments>
<mappers>
<mapper resource="mybatis/mapper/UserMapper.xml"/>
mappers>
configuration>
package com.zhw.mybatis2.mapper;
import com.zhw.mybatis2.entities.User;
public interface UserMapper1 {
public User getUserById(Integer id);
//mybatis会自动封装返回结果,语句执行成功为true,不成功为false
public Boolean addUser(User user);
public Boolean deleteById(Integer id);
public Boolean updateById(User user);
}
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zhw.mybatis2.mapper.UserMapper1">
<select id="getUserById" resultType="User" parameterType="int">
select * from tb_user where id = #{id}
select>
<insert id="addUser" parameterType="user">
insert into tb_user values (#{id},#{userName},#{address},#{birthday})
insert>
<delete id="deleteById" parameterType="int">
delete from tb_user where id = #{id}
delete>
<update id="updateById" parameterType="user">
update tb_user set username = #{userName},address = #{address},birthday = #{birthday} where id = #{id}
update>
mapper>
package com.zhw.mybatis.test;
public class MybatisTest {
//查询方法
@Test
public void test01() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = factory.openSession();
UserMapper1 mapper = sqlSession.getMapper(UserMapper1.class);
User userById = mapper.getUserById(1);
System.out.println(userById);
}
//增加用户
@Test
public void test02() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = factory.openSession(true);
UserMapper1 mapper = sqlSession.getMapper(UserMapper1.class);
User user = new User();
user.setId(23);
user.setAddress("uiui");
user.setBirthday(12344l);
user.setUserName("zzzz");
mapper.addUser(user);
}
//删除用户
@Test
public void test03() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = factory.openSession(true);
UserMapper1 mapper = sqlSession.getMapper(UserMapper1.class);
int i = mapper.deleteById(23);
System.out.println(i);
}
//修改用户
@Test
public void test04() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = factory.openSession(true);
UserMapper1 mapper = sqlSession.getMapper(UserMapper1.class);
User user = new User(1, "zhengshihao", "zhengzhaicun", 19991112l);
mapper.updateById(user);
}
}
mybatis对数据进行改动不会提交数据需要手动提交
@Test
public void test04() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = factory.openSession();
UserMapper1 mapper = sqlSession.getMapper(UserMapper1.class);
User user = new User(1, "zhengshihao", "zhengzhaicun", 19991112l);
mapper.updateById(user);
//手动提交
sqlSession.commit();
}
或者自动提交
@Test
public void test04() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(resourceAsStream);
//自动提交数据
SqlSession sqlSession = factory.openSession(true);
UserMapper1 mapper = sqlSession.getMapper(UserMapper1.class);
User user = new User(1, "zhengshihao", "zhengzhaicun", 19991112l);
mapper.updateById(user);
}
语句的返回值
//mybatis会自动封装返回结果,语句执行成功为true,不成功为false
public Boolean addUser(User user);
使用主键自增策略,添加数据的时候不需要,添加主键的值
<insert id="addUser" parameterType="user" keyProperty="id" useGeneratedKeys="true">
insert into tb_user(username,address,birthday) values (#{userName},#{address},#{birthday})
insert>
keyProperty="id" 将获取的主键封装到javaBean的哪个属性
useGeneratedKeys="true" 是否获取加入的数据的主键
@Test
public void test02() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = factory.openSession(true);
UserMapper1 mapper = sqlSession.getMapper(UserMapper1.class);
User user = new User();
user.setAddress("uiui");
user.setBirthday(12344L);
user.setUserName("zzzz");
Boolean aBoolean = mapper.addUser(user);
if (aBoolean){
Integer id = user.getId();
System.out.println(id);
}else {
System.out.println("没有封装到");
}
}
#{参数名}:取出参数名,不做特殊处理,直接将参数封装到给定的#{参数名}中,参数名可以任意,不用和参数名相同
<select id="getUserByIdWithName" resultType="User" >
select * from tb_user where id = #{id} and username = #{userName}
select>
public User getUserByIdWithName(Integer id,String userName);
出现异常:
Cause: org.apache.ibatis.binding.BindingException: Parameter ‘id’ not found. Available parameters are [arg1, arg0, param1, param2]
当遇到多个参数mybatis会做特殊处理
多个参数封装成一个map
key:param1…paramN 或者参数的arg0…argN也可以
value :传入的参数值
<select id="getUserByIdWithName" resultType="User" >
select * from tb_user where id = #{param1} and username = #{param2}
select>
<select id="getUserByIdWithName" resultType="User" >
select * from tb_user where id = #{arg0} and username = #{arg1}
select>
结果
在接口的参数上使用@Param注解就可以指定多个参数的命名,测试在xml中就可以使用了
public User getUserByIdWithName(@Param("id") Integer id,@Param("userName") String userName);
<select id="getUserByIdWithName" resultType="User" >
select * from tb_user where id = #{id} and username = #{userName}
select>
结果
#{key}:取出对应的值,直接用这种方式可以获取map的对应的值
//传入一个map
public User getUserByMap(Map<String,Object> map);
<select id="getUserByMap" resultType="user">
select * from tb_user where id = #{id} and username = #{userName}
select>
/**
* 根据id和用户名查询 多个参数封装的map
* @throws IOException
*/
@Test
public void test06() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = factory.openSession(true);
UserMapper1 userMapper = sqlSession.getMapper(UserMapper1.class);
Map<String, Object> stringObjectMap = new HashMap<>();
stringObjectMap.put("id",1);
stringObjectMap.put("userName","zhengshihao");
User userByMap = userMapper.getUserByMap(stringObjectMap);
System.out.println(userByMap);
}
#{}:可以获取map中的值或者pojo对象属性的值
${}:可以获取map中的值或者pojo对象属性的值
<select id="getUserByMap" resultType="user">
select * from tb_user where id = ${id} and username = #{userName}
select>
成功
区别:
#{}:是以预编译的形式,将参数设置到sql语句中,PreparedStatement;防止sql注入
${}:取出的值直接拼接在sql语句中;会有安全问题
大多情况下,我们取参数的值都应该使用#{}
原生jdbc不支持占位符的地方问哦们可以使用${}进行取值
比如分表:按照年份分表拆分
select * from ${year}_salary where xxx;
select * from tbl_employee order by ${f_name} ${order}
//接口
//查询所有的数据
public List<User> getAllUser();
xml文件
<select id="getAllUser" resultType="user">
select * from tb_user
select>
//指定查询语句的resultType类型,为集合中的泛型
//接口
//查询所有的数据
public List<User> getAllUser(String userName);
<select id="getAllUser" resultType="user" >
select * from tb_user where username like #{userName}
select>
UserMapper1 mapper = sqlSession.getMapper(UserMapper1.class);
List<User> allUser = mapper.getAllUser("%zheng%");
System.out.println(allUser);
//将对象封装成一个map返回
public Map<String,Object> getUserByIdReturnMap(Integer id);
<select id="getUserByIdReturnMap" parameterType="int" resultType="map">
select * from tb_user where id = #{id}
select>
/**
* 返回对象封装的map
* @throws IOException
*/
@Test
public void test08() throws IOException {
UserMapper1 mapper = sqlSession.getMapper(UserMapper1.class);
Map<String, Object> userByIdReturnMap = mapper.getUserByIdReturnMap(1);
Set<Map.Entry<String, Object>> entries = userByIdReturnMap.entrySet();
entries.forEach(e -> {
System.out.println(e.getKey()+e.getValue());
});
}
//将多个对象封装成一个map返回
//添加一个注解用作可以,来自数据库中的id
@MapKey("id")
public Map<Integer,User> getAllUserReturnMap();
<select id="getAllUserReturnMap" resultType="user">
select * from tb_user
select>
//只需要指定value的类型就可以了
/**
* 返回多个对象封装的map
* @throws IOException
*/
@Test
public void test09() throws IOException {
UserMapper1 mapper = sqlSession.getMapper(UserMapper1.class);
Map<Integer, User> allUserReturnMap = mapper.getAllUserReturnMap();
System.out.println(allUserReturnMap);
System.out.println(allUserReturnMap.get(1));
}
//Vo类
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package com.zhw.mybatis2.entities;
public class UserVo {
private String name;
private String userName;
public String getName() {
return this.name;
}
public String getUserName() {
return this.userName;
}
public void setName(String name) {
this.name = name;
}
public void setUserName(String userName) {
this.userName = userName;
}
public boolean equals(Object o) {
if (o == this) {
return true;
} else if (!(o instanceof UserVo)) {
return false;
} else {
UserVo other = (UserVo)o;
if (!other.canEqual(this)) {
return false;
} else {
Object this$name = this.getName();
Object other$name = other.getName();
if (this$name == null) {
if (other$name != null) {
return false;
}
} else if (!this$name.equals(other$name)) {
return false;
}
Object this$userName = this.getUserName();
Object other$userName = other.getUserName();
if (this$userName == null) {
if (other$userName != null) {
return false;
}
} else if (!this$userName.equals(other$userName)) {
return false;
}
return true;
}
}
}
protected boolean canEqual(Object other) {
return other instanceof UserVo;
}
public int hashCode() {
int PRIME = true;
int result = 1;
Object $name = this.getName();
int result = result * 59 + ($name == null ? 43 : $name.hashCode());
Object $userName = this.getUserName();
result = result * 59 + ($userName == null ? 43 : $userName.hashCode());
return result;
}
public String toString() {
return "UserVo(name=" + this.getName() + ", userName=" + this.getUserName() + ")";
}
public UserVo() {
}
public UserVo(String name, String userName) {
this.name = name;
this.userName = userName;
}
}
//接口
//多表查询resultMap结果集映射
public UserVo getUserWithPersonById(Integer id);
//xml文件
<resultMap id="UserWithPerson" type="userVo">
<result column="username" property="userName"/>
<result column="name" property="name"/>
resultMap>
<select id="getUserWithPersonById" resultMap="UserWithPerson">
select u.username,p.name from tb_user u,tb_person p where u.id = p.id and u.id = #{id}
select>
//测试
/**
* 返回resultmap映射
* @throws IOException
*/
@Test
public void test10() throws IOException {
UserMapper1 mapper = sqlSession.getMapper(UserMapper1.class);
UserVo userWithPersonById = mapper.getUserWithPersonById(2);
System.out.println(userWithPersonById);
}
//结果成功
规则:
id:映射器的唯一标识 映射器的类型
<resultMap id="UserWithPerson" type="userVo">
id标签:主键
<id column="username" property="userName"/>
result:字段
column:数据库的字段
property:javabea的属性
<result column="name" property="name"/>
resultMap>
resultMap 指定引用哪一个映射器
<select id="getUserWithPersonById" resultMap="UserWithPerson">
select u.username,p.name from tb_user u,tb_person p where u.id = p.id and u.id = #{id}
select>
@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserWithOrder {
private Integer id;
private String userName;
private String address;
private Long birthday;
private Order order;
}
//User中有Order
public UserWithOrder getUserWithOrder(Integer id);
<resultMap id="UserWithOrder" type="UserWithOrder">
<id column="userid" property="id"/>
<result column="username" property="userName"/>
<result column="birthday" property="address"/>
<result column="birthday" property="birthday"/>
//嵌套结果集
<association property="order" javaType="Order">
<id column="oid" property="id"/>
<result column="number" property="number"/>
<result column="uid" property="uid"/>
association>
resultMap>
<select id="getUserWithOrder" resultMap="UserWithOrder">
select *,u.id as userid,o.id oid from tb_user u,tb_orders o where o.id = u.id and u.id = #{id}
select>
/**
* 1对1结果映射
* @throws IOException
*/
@Test
public void test11() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = factory.openSession();
UserMapper1 mapper = sqlSession.getMapper(UserMapper1.class);
UserWithOrder userWithOrder = mapper.getUserWithOrder(1);
System.out.println(userWithOrder);
}
OrderMapper
namespace="com.zhw.mybatis2.mapper.OrderMapper"
<select id="getOrderById" resultType="Order" parameterType="int">
select * from tb_orders where id = #{id}
select>
<resultMap id="MyUserSetp" type="UserWithOrder">
<id column="id" property="id"/>
<result column="username" property="userName"/>
<result column="birthday" property="birthday"/>
<result column="address" property="address"/>
<association property="order"
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>
//14.分布查询
@Test
public void test14() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = factory.openSession();
UserMapper1 mapper = sqlSession.getMapper(UserMapper1.class);
UserWithOrder userWithOrderStep = mapper.getUserWithOrderStep(1);
//只用到了User的信息
System.out.println(userWithOrderStep.getId());
}
只发了一条查询语句
//14.延迟加载
@Test
public void test14() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = factory.openSession();
UserMapper1 mapper = sqlSession.getMapper(UserMapper1.class);
UserWithOrder userWithOrderStep = mapper.getUserWithOrderStep(1);
//用到了Order的对象的属性,所以加载了
System.out.println(userWithOrderStep.getOrder().getId());
}
发了两条sql语句
<resultMap id="User1WithOrders" type="User1">
<id column="uuuid" property="id"/>
<result column="birthday" property="birthday"/>
<result column="address" property="address"/>
<result column="username" property="userName"/>
//property:属性的名字,ofType:集合里面的泛型
<collection property="orders" ofType="com.zhw.mybatis2.entities.Order">
<id column="id" property="id"/>
<result column="number" property="number"/>
<result column="uid" property="uid"/>
collection>
resultMap>
<select id="getUser1WithById" resultMap="User1WithOrders">
SELECT* ,u.id AS uuuid FROM tb_user u LEFT JOIN tb_orders o ON u.`id` = o.`uid` WHERE u.`id` = #{id}
select>
<resultMap id="User1WithOrdersStep" type="com.zhw.mybatis2.entities.User1">
<id column="id" property="id"/>
<result column="address" property="address"/>
<result property="birthday" column="birthday"/>
<result property="userName" column="username"/>
collection>
resultMap>
<select id="getUser1WithByIdStep" resultMap="User1WithOrdersStep">
select * from tb_user where id = #{id}
select>
返回一个List
<select id="getOrderByIdList" resultType="Order" parameterType="int">
select * from tb_orders where uid = #{uid}
select>
//14.一对多 懒加载
@Test
public void test16() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = factory.openSession();
User1Mapper mapper = sqlSession.getMapper(User1Mapper.class);
User1 user1WithById = mapper.getUser1WithByIdStep(1);
System.out.println(user1WithById.getOrders().get(1));
}
测试成功
将多个值封装成一个map传递
column={key1=column1,key2=column2}
association和collection的FetchType属性,只当是否开启延迟加载,即使开启了全局的延迟加载,也按照指定的的属性
<collection property="orders"
ofType="com.zhw.mybatis2.entities.Order"
select="com.zhw.mybatis2.mapper.OrderMapper.getOrderByIdList"
column="{uid=id}"
fetchType="eager"
fetchType="lazy">
eager:立即
lazy:延迟加载
collection>
使用结果值来决定使用哪个 resultMap
看文档把不想写了
<select id="getUser1WithByIdStep" resultMap="User1WithOrdersStep">
select * from tb_user where id = #{id}
select>
//如果查出来的用户名为zhegnshihao则查询该用户的订单,否则什么也不做
<resultMap id="User1WithOrdersStep" type="com.zhw.mybatis2.entities.User1">
<id column="id" property="id"/>
<result column="address" property="address"/>
<result property="birthday" column="birthday"/>
<result property="userName" column="username"/>
column:为判断的属性,javaType:为该属性定义的类型
<discriminator javaType="string" column="userName">
valueL:为column指定的情况
<case value="zhengshihao">
<collection property="orders"
ofType="com.zhw.mybatis2.entities.Order"
select="com.zhw.mybatis2.mapper.OrderMapper.getOrderByIdList"
column="id"
fetchType="lazy">
collection>
case>
discriminator>
resultMap>
看官方文档
两级缓存
一级缓存:(本地缓存):sqlsession级别的缓存,一级缓存是一直开启的,没法关掉
@Test
public void test01() throws IOException {
SqlSession sqlSession = getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User userById = mapper.getUserById(1);
System.out.println(userById);
User userById1 = mapper.getUserById(1);
System.out.println(userById1);
System.out.println(userById == userById1);
}
只发出了一个sql语句,并且第二次查询的对象与第一次相同
//使用不同的sqlsession实现一级缓存失效
@Test
public void test02() throws IOException {
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
SqlSession sqlSession1 = sqlSessionFactory.openSession();
//sqlsession1
UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class);
User user1 = mapper1.getUserById(1);
System.out.println(user1);
//sqlsession2
SqlSession sqlSession2 = sqlSessionFactory.openSession();
UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class);
User user2 = mapper2.getUserById(1);
System.out.println(user2);
System.out.println(user1 == user2);
}
发了两条SQL语句
当前的sqlsession中还没有要查的数据
//相同的sqlsession,不同的条件
@Test
public void test03() throws IOException {
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
//
User userById = mapper.getUserById(1);
//因为2号员工在sqlsession中没有
User userById1 = mapper.getUserById(2);
}
执行了增删改操作就会清除sqlsession中的缓存
//相同的sqlsession,执行力增删改操作就会清除sqlsession的缓存
@Test
public void test04() throws IOException {
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User userById = mapper.getUserById(1);
mapper.addUser(new User(null,"fanyuning","xinxiang",19991212l));
sqlSession.commit();
User userById1 = mapper.getUserById(1);
System.out.println(userById1 == userById);
}
sqlSession.clearCache()
基于naespace级别的缓存,一个namespace对应一个二级缓存
工作机制
一个会话,查询一条数据,这个数据就会被放在当前会话的一级缓存中
如果当前会话关闭,一级缓存中的数据会被保存到二级缓存中;新的会话查询信息,就可以参照二级缓存中的内容
sqlsession === UserMapper ==> User
OrderMapper ==> Order
不同的namespace查出的数据会放在自己对应的缓存(map)中
开启全局二级缓存配置
在全局配置文件中开启二级缓存
<setting name="cacheEnabled" value="true"/>
去mappere.xml中配置使用二级缓存:
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zhw.cache.mapper.UserMapper">
//开启二级缓存
<cache eviction="" >cache>
<select id="getUserById" resultType="com.zhw.cache.entities.User">
select * from tb_user where id = #{id};
select>
<insert id="addUser" parameterType="user">
insert into tb_user(id,username,address,birthday) values (null ,#{userName},#{address},#{birthday});
insert>
mapper>
cache的配置
我们的pojo需要实现序列化接口
测试结果
/**
* 二级缓存
*/
@Test
public void testSecondLevelCache() throws IOException {
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
//获取不同的sqlsession
SqlSession sqlSession1 = sqlSessionFactory.openSession();
SqlSession sqlSession2 = sqlSessionFactory.openSession();
//获取mapper代理对象
UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class);
UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class);
//mapper1查询id为1的用户
User userById = mapper1.getUserById(1);
System.out.println(userById);
sqlSession1.close();
try {
//测试 flushInterval="10000"属性
Thread.sleep(12000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
//mapper2查询id为1的用户
//当不超时的情况下,会从二级缓存中获取数据,并没有发送sql语句
User userById1 = mapper2.getUserById(1);
System.out.println(userById1);
sqlSession2.close();
}
<setting name="cacheEnabled" value="false"/>
1.不会关闭二级缓存,只会关闭二级缓存
2.一级缓存值即可用
每个select标签都有useCache="true"
<select id="getUserById" resultType="User" useCache="false">
1.关闭二级缓存,一级缓存仍然可用
每个增删改标签都有flushCache="true"
<insert flushCache="true" id="addUser" parameterType="user">
insert into tb_user(id,username,address,birthday) values (null ,#{userName},#{address},#{birthday});
insert>
1.就会清除缓存
2.会清除一级和二级缓存的数据
3.查询标签的flushCache="false"
如果设置为true则每次也都会清除一级和二级缓存
/**
* sqlsession.clearCache()
* 是否清除二级缓存
* @throws IOException
*/
@Test
public void testSecondLevelCache3() throws IOException {
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
//获取不同的sqlsession
SqlSession sqlSession1 = sqlSessionFactory.openSession();
SqlSession sqlSession2 = sqlSessionFactory.openSession();
//获取mapper代理对象
UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class);
UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class);
//mapper1查询id为1的用户
User userById = mapper1.getUserById(1);
System.out.println(userById);
sqlSession1.close();
//只会清除对应的sqlsession中的一级缓存
//不会对二级缓存有影响
sqlSession2.clearCache();
//mapper2查询id为1的用户
User userById1 = mapper2.getUserById(1);
System.out.println(userById1);
sqlSession2.close();
}
localCacheScope = STATEMENT 时会禁用一级缓存(没人去设置它)
1.添加依赖
<dependency>
<groupId>log4jgroupId>
<artifactId>log4jartifactId>
<version>1.2.17version>
dependency>
2.日志配置文件
# Set root category priority to INFO and its only appender to CONSOLE.
#log4j.rootCategory=INFO, CONSOLE debug info warn error fatal
log4j.rootCategory=debug, CONSOLE, LOGFILE
# Set the enterprise logger category to FATAL and its only appender to CONSOLE.
log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE
# CONSOLE is set to be a ConsoleAppender using a PatternLayout.
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n
# LOGFILE is set to be a File appender using a PatternLayout.
log4j.appender.LOGFILE=org.apache.log4j.FileAppender
log4j.appender.LOGFILE.File=d:/axis.log
log4j.appender.LOGFILE.Append=true
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.LOGFILE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n
3.开启配置
<settings>
<setting name="logImpl" value="LOG4J"/>
settings>