Mybatis
原始方式
SqlMapConfig.xml+UserMapper.xml
查询
SqlMapConfig.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>
<typeAliases>
<package name="com.yan.model"/>
</typeAliases>
<environments default="development">
<!-- 配置环境-->
<environment id="development">
<!-- 配置JDBC事务管理器-->
<transactionManager type="JDBC">
</transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://172.16.0.5:3306/mybatis"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="Mapper/UserMapper.xml"/>
</mappers>
</configuration>
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=" ">
<select id="findUserById" parameterType="int" resultType="user">
select * from user where id=#{id};
</select>
</mapper>
使用:
//读取配置文件
InputStream inputStream= Resources.getResourceAsStream("SqlMapConfig.xml");
//通过SqlSessionFactoryBuilder获取 sessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//通过sessionFactory获取sqlSession
SqlSession sqlSession = sessionFactory.openSession();
//通过 sqlSession 操作数据库
User user = sqlSession.selectOne("findUserById", 10);
//关闭sqlSession
sqlSession.close();
System.out.println(user);
模糊查询:
${} 取值 用在Mapper.xml文件中表示值替换相当于字符串拼接sql
会造成sql注入,但在某些场景必须用它,比如 order by ${colname}
简单类型${}中变量必须为value
UserMapper.xml
<select id="findUserByName" parameterType="string" resultType="user">
select * from user where username like '%${value}%'
</select>
测试:
//读取配置文件
InputStream inputStream= Resources.getResourceAsStream("SqlMapConfig.xml");
//通过SqlSessionFactoryBuilder获取 sessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//通过sessionFactory获取sqlSession
SqlSession sqlSession = sessionFactory.openSession();
//通过 sqlSession 操作数据库
List<User> users = sqlSession.selectList("findUserByName", "张");
//关闭sqlSession
sqlSession.close();
System.out.println(users);
插入
UserMapper.xml
<!-- 添加 -->
<insert id="addUser" parameterType="user" >
<!-- 为user设置id -->
<selectKey keyProperty="id" resultType="int" order="AFTER">
SELECT LAST_INSERT_ID();
</selectKey>
insert into user (username,sex,birthday,address)
value (#{username},#{sex},#{birthday},#{address})
</insert>
测试:
//读取配置文件
InputStream inputStream= Resources.getResourceAsStream("SqlMapConfig.xml");
//通过SqlSessionFactoryBuilder获取 sessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//通过sessionFactory获取sqlSession
SqlSession sqlSession = sessionFactory.openSession();
User user=new User();
user.setUsername("yan");
user.setBirthday(new Date());
user.setAddress("长丰县");
user.setSex("2");
//通过 sqlSession 操作数据库
int affectRow = sqlSession.insert("addUser", user);
//提交数据
sqlSession.commit();
//关闭sqlSession
sqlSession.close();
System.out.println(affectRow);
System.out.println(user.getId());
删除
UserMapper.xml
<!-- 删除-->
<delete id="deleteUser" parameterType="int">
delete from user where id=#{id}
</delete>
测试
//读取配置文件
InputStream inputStream= Resources.getResourceAsStream("SqlMapConfig.xml");
//通过SqlSessionFactoryBuilder获取 sessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//通过sessionFactory获取sqlSession
SqlSession sqlSession = sessionFactory.openSession();
//通过 sqlSession 操作数据库
int affectRow = sqlSession.delete("deleteUser", 29);
//提交数据
sqlSession.commit();
//关闭sqlSession
sqlSession.close();
System.out.println(affectRow);
更新
UserMapper.xml
<!-- 更新用户-->
<update id="updateUser" parameterType="user">
update user set
username=#{username},sex=#{sex},birthday=#{birthday},address=#{address}
where id = #{id}
</update>
测试
//读取配置文件
InputStream inputStream= Resources.getResourceAsStream("SqlMapConfig.xml");
//通过SqlSessionFactoryBuilder获取 sessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//通过sessionFactory获取sqlSession
SqlSession sqlSession = sessionFactory.openSession();
User user=new User();
user.setUsername("闫绍帅");
user.setBirthday(new Date());
user.setAddress("长丰县");
user.setSex("2");
user.setId(26);
//通过 sqlSession 操作数据库
int affectRow = sqlSession.update("updateUser", user);
//提交数据
sqlSession.commit();
//关闭sqlSession
sqlSession.close();
System.out.println(affectRow);
#{}和${}区别
#{}相当于占位符?
当入参是对象时,#{}中填入有get方法的变量名就会取到对象中的值
当入参是简单类型时,#{}可填写任意值
类似于PreparedStatement,可以防止sql注入
${}只是简单的替换值不会做额外的处理,相当于拼接sql字符串
当入参是对象时${}中填入有get方法的变量名就会取到对象中的值
当入参是简单类型时,${}中只能填写value
${}会引起sql注入
mapper代理
默认使用jdk动态代理
Mapper和接口放在同一目录(todo:Mapper接口与xml分离)
SqlMapConfig.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>
<typeAliases>
<package name="com.yan.model"/>
</typeAliases>
<environments default="development">
<!-- 配置环境-->
<environment id="development">
<!-- 配置JDBC事务管理器-->
<transactionManager type="JDBC">
</transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://172.16.0.5:3306/mybatis"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<mappers>
<package name="com.yan.mapper"/>
</mappers>
</configuration>
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.yan.mapper.UserMapper">
<select id="findUserById" parameterType="int" resultType="user">
select * from user where id=#{id};
</select>
<!-- 添加 -->
<insert id="save" parameterType="user" >
<selectKey keyProperty="id" resultType="int" order="AFTER">
SELECT LAST_INSERT_ID();
</selectKey>
insert into user (username,sex,birthday,address)
value (#{username},#{sex},#{birthday},#{address})
</insert>
</mapper>
UserMapper.java
public interface UserMapper {
int save(User user);
User findUserById(int id);
}
测试:
//读取配置文件
InputStream inputStream= Resources.getResourceAsStream("SqlMapConfig.xml");
//通过SqlSessionFactoryBuilder获取 sessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//通过sessionFactory获取sqlSession
SqlSession sqlSession = sessionFactory.openSession();
//通过 sqlSession 操作数据库
// List<User> users = sqlSession.selectList("findUserByName", "张");
User user=new User();
user.setUsername("闫绍帅");
user.setBirthday(new Date());
user.setAddress("长丰县");
user.setSex("2");
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// mapper.save(user);
User user1 = mapper.findUserById(36);
sqlSession.commit();
System.out.println(user1);
配置log4j
依赖:
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
log4j.properties(类路径下)
# Global logging configuration
log4j.rootLogger=ERROR, stdout
# MyBatis logging configuration...
log4j.logger.com.yan.mapper=TRACE
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
SqlMapConfig.xml的configuration标签下:
<settings>
<setting name="logImpl" value="LOG4J"/>
</settings>
参数映射
parameterType
ONGL表达式支持嵌套类型,用 . 获取嵌套类型属性,参数是hashmap时候.后面写键名
内置别名 int-->int,String-->string,HashMap-->hashmap...
resultType
列名和返回对象属性名一致或者返回简单类型可以用resultType
列名与对象属性名不一致
1.起别名
2.用resultMap
例:
<resultMap id="userResultMap" type="user">
<id property="id" column="id"/>
<result property="username" column="username_"/>
<result property="sex" column="sex"/>
<result property="birthday" column="birthday"/>
</resultMap>
<select id="findUserById" parameterType="int" resultMap="userResultMap">
select id ,username username_,sex,birthday from user where id=#{id};
</select>
动态SQL
1.条件查询拼接
<!-- 如果user.id==0返回所有否则根据id查询-->
<select id="findUsers" parameterType="user" resultType="user">
select * from user
<where>
<if test="id !=null and id != 0 and id.toString()!=''">
id=#{id}
</if>
<if test="username !=null and username !=''">
AND username=#{username};
</if>
</where>
</select>
2.SQL片段
<sql id="if-test">
<if test="id !=null and id != 0 and id.toString()!=''">
id=#{id}
</if>
<if test="username !=null and username !=''">
AND username=#{username};
</if>
</sql>
<!-- 如果user.id==0返回所有否则根据id查询-->
<select id="findUsers" parameterType="user" resultType="user">
select * from user
<where>
<include refid="if-test"></include>
</where>
</select>
3.foreach
<!-- foreach遍历-->
<select id="findUsersByIds" parameterType="list" resultType="user">
select * from user
<where>
<if test="list!=null and list.size()>0">
id in
<foreach collection="collection" index="i" open="(" close=")" item="item" separator=",">
${item}
</foreach>
</if>
</where>
</select>
懒加载
Orders.java
public class Orders {
private Integer id;
private Integer userId;
private String number;
private Date createtime;
private String note;
//用户信息
private User user;
//订单明细
private List<Orderdetail> orderdetails;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number == null ? null : number.trim();
}
public Date getCreatetime() {
return createtime;
}
public void setCreatetime(Date createtime) {
this.createtime = createtime;
}
public String getNote() {
return note;
}
public void setNote(String note) {
this.note = note == null ? null : note.trim();
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public List<Orderdetail> getOrderdetails() {
return orderdetails;
}
public void setOrderdetails(List<Orderdetail> orderdetails) {
this.orderdetails = orderdetails;
}
@Override
public String toString() {
return "Orders [id=" + id + ", userId=" + userId + ", number=" + number
+ ", createtime=" + createtime + ", note=" + note + ", user="
+ user + ", orderdetails=" + orderdetails + "]";
}
}
SqlMapConfig.xml开启懒加载:
<settings>
<setting name="lazyLoadingEnabled" value="true"/>
</settings>
OrdersMapper.xml
<mapper namespace="com.yan.mapper.OrdersMapper">
<resultMap id="lazyLoadUser" type="orders">
<id property="id" column="id"/>
<result property="userId" column="user_id"/>
<association property="user" select="com.yan.mapper.UserMapper.findUserById" column="user_id"/>
</resultMap>
<select id="findOrdersById" parameterType="int" resultMap="lazyLoadUser">
select * from orders where id=#{id};
</select>
</mapper>
用到user属性时才会加载association中的查询语句,column="user_id"传入参数
mybatis缓存
一级缓存
session级别缓存(默认开启)
二级缓存
全局缓存,多session共用(session关闭才会写入缓存commit,close等)
SqlMapConfig.xml中允许使用二级缓存
<settings>
<settings>
<!--允许使用二级缓存-->
<setting name="cacheEnabled" value="true"/>
</settings>
UserMapper.xml使用二级缓存
<cache/>
model要继承序列化接口Serializable
任意session执行insert,delete,update等操作,二级缓存数据会清空
禁用某个方法使用二级缓存
<select id="findUserById" parameterType="int" resultMap="userResultMap" useCache="true">
select id ,username username_,sex,birthday from user where id=#{id};
</select>
Mybatis自带缓存不支持分布式缓存,可以整合其他缓存实现分布式缓存