mybatis 动态sql
接口中
public interface AdminMapper { public List<Admin> findByParams(Map<String,Object> param); }
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"> <mapper namespace="com.kaishengit.mapper.AdminMapper"> <select id="findByParams" parameterType="map" resultType="list" resultMap="adminMap"> select * from admin <where> <if test="name != null"> name = #{name} </if> <if test="password != null"> and password = #{password} </if> </where> </select> <!-- 在代码中就可以选择性的put name或者password,因为只要有if判断成立,会自动加上where 在第一个if不成立,第二个if成立的时候会自动把第二个条件前面的and去掉 原形: <select id="findByParams" parameterType="map" resultType="list" resultMap="adminMap"> select * from admin where (where后面要有一个空格,方便与后面的进行拼凑) <if test="name != null"> name = #{name} </if> <if test="password != null"> and password = #{password} </if> </select> 但是这样是有问题的,如果两个if都不成立就会多出一个where,或者第一个不成立就会多出一个and 所以我们可以用上面这样的where 标签 只要有if判断成立,会自动加上where 在第一个if不成立,第二个if成立的时候会自动把第二个条件前面的and去掉 除了用where还可以用trim <select id="findByParams" parameterType="map" resultType="list" resultMap="adminMap"> select * from admin 只要有一个if成立就添加where 并且告诉前缀是and或者or,只要在前面if不成立时 自动屏蔽and或or suffixOverrides(覆盖后缀),在后面一个if不成立的情况下,自动屏蔽上一个的and或者or <trim prefix="WHERE" prefixOverrides="AND |OR "> <if test="name != null"> name = #{name} </if> <if test="password != null"> and password = #{password} </if> </trim> </select> --> <resultMap type="Admin" id="adminMap"> <id property="id" column="id"/> <result property="name" column="name"/> <result property="password" column="password"/> </resultMap> </mapper>
代码中
public class Test { public static void main(String[] args) throws Exception { Reader reader = Resources.getResourceAsReader("mybatis.xml"); SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader); SqlSession session = factory.openSession(true); AdminMapper mapper = session.getMapper(AdminMapper.class); // 动态查询 Map<String, Object> map = new HashMap<String, Object>(); map.put("name", "admin"); map.put("password", "000000"); List<Admin> list = mapper.findByParams(map); for(Admin admin : list) { System.out.println(admin.getId()); } session.close(); } }
xml中还提供动态的其他sql
更新
当if成立的时候自动在前面加set
<update id="updateAuthorIfNecessary" parameterType="domain.blog.Author"> update Author <set> <if test="username != null">username=#{username},</if> <if test="password != null">password=#{password},</if> <if test="email != null">email=#{email},</if> <if test="bio != null">bio=#{bio}</if> </set> where id=#{id} </update> <!--或者用trim 最后一个不成立的时候自动屏蔽倒数第二个的逗号 <update id="updateAuthorIfNecessary" parameterType="domain.blog.Author"> update Author <trim prefix="SET" suffixOverrides=","> <if test="username != null">username=#{username},</if> <if test="password != null">password=#{password},</if> <if test="email != null">email=#{email},</if> <if test="bio != null">bio=#{bio}</if> </trim> where id=#{id} </update>
foreach
<select id="selectPostIn" resultType="domain.blog.Post"> SELECT * FROM POST P WHERE ID in <foreachitem="item" index="index" collection="list" open="(" separator="," close=")"> #{item} </foreach> </select>
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
缓存
<mapper namespace="com.kaishengit.mapper.NewsMapper"> <cache/> ... </mapper>
对象(pojo)必须是可序列化
功效如下:
映射语句文件中所有的select语句将被缓存
映射语句文件中的所有insert、update、delete语句会刷新缓存
缓存会使用least recentilyused(LRU,最近很少使用的)算法来收回
根据时间间隔来刷新缓存,默认不刷新
缓存会存储列表集合或对象的1024个引用
缓存被视为read/write的缓存
更改缓存
<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>
上面配置了一个FIFO缓存,每隔60秒刷新一次缓存,存储对象或集合512个引用,
而且缓存为只读缓存。
eviction回收策略
LRU:最近最少使用的,移除长时间不被使用的对象(默认)
FIFO:先进先出:按对象进入缓存的顺序来移除他们
SOFT:软引用:移除基于垃圾回收器状态和软引用规则的对象
WEAK:弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
flushInterval(刷新间隔):可以被设置为任意的正整数
size(引用数目)可以被设置为任意正整数,要记住你缓存的对象数目和你运行
环境的可用内存资源数目。默认值是1024。
readOnly(只读)属性可以被设置为true 或false。只读的缓存会给所有调用者返
回缓存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势。
可读写的缓存会返回缓存对象的拷贝(通过序列化)。这会慢一些,但是安全,因此
默认是false。
-----------------------------------------------------
-----------------------------------------------------
-----------------------------------------------------
MyBatisAnnotation
对于动态sql还是要自己写配置文件,不能用 annotation
主配置文件中
<mappers> <mapper class="com.kaishengit.mapper.DeptMapper"/> <mapper class="com.kaishengit.mapper.UserMapper"/> </mappers>
接口中
注解的缓存直接加@cachenamespace
@CacheNamespace public interface AdminMapper { @Insert("insert into admin(name,password) values(#{name},#{password})") @Options(flushCache=false) public void save(Admin admin); @Delete("delete from admin where id = #{id}") public void delete(int id); @Select("select * from admin where id = #{id}") public Admin findById(int id); @Update("update admin set name = #{name},password=#{password} where id = #{id}") public void update(Admin admin); @Select("select * from admin") public List<Admin> findAll(); @Select("select * from admin where name = #{name} and password = #{password}") /* 如果有多个参数,需要加注解,表明String name的这个name是给上面的大括号里面的name的 */ public Admin findByNameAndPwd(@Param("name") String name,@Param("password") String password); /--------------------------------/ /*多表查询 从adminMapper中链接查询到postMapper中 */ @Select("select * from admin where id = #{id}") @Results(value={ @Result(property="id",column="id"), @Result(property="name",column="name"), @Result(property="password",column="password"), /*property属性名 javaType该属性的类型 admin和post是一对多 many指定postMapper中链接查询的对应的方法 column="id"只传到postMapper中的findByAdminId方法中的参数*/ @Result(property="posts",javaType=List.class,column="id",many=@Many(select="com.kaishengit.mapper.PostMapper.findByAdminId")) }) public Admin find(int id); }
然后再postMapper中要写多表查询相关的查询,因为在adminMapper中的查询语句只有 select * from admin where id = #{id}
@CacheNamespace public interface PostMapper { //接受admin的id然后链接查询 @Select("SELECT * FROM post WHERE aid = #{adminId}") public List<Post> findByAdminId(int adminId); //从postMapper中链接查询到adminMapper中 @Select("select * from post where id = #{id}") @Results(value={ @Result(property="id",column="id"), @Result(property="title",column="title"), /* admin和post是一对多,one=@One(select="com.kaishengit.mapper.AdminMapper.findById")链接查询到 admin中的findById方法中,传过去的参数是aid*/ @Result(property="admin",javaType=Admin.class,column="aid",one=@One(select="com.kaishengit.mapper.AdminMapper.findById")) }) public Post findById(int id); }
public class Test { public static void main(String[] args) throws Exception { Reader reader = Resources.getResourceAsReader("mybatis.xml"); SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader); //没有了配置文件, 要加上这一段 factory.getConfiguration().addMapper(AdminMapper.class); factory.getConfiguration().addMapper(PostMapper.class); SqlSession session = factory.openSession(true); session.close(); } }