有的時候須要根據要查詢的參數動態的拼接SQL語句java
經常使用標籤:sql
- if:字符判斷數據庫
- choose【when...otherwise】:分支選擇緩存
- trim【where,set】:字符串截取,其中where標籤封裝查詢條件,set標籤封裝修改條件安全
- foreach:session
if案例mybatis
1)在EmployeeMapper接口文件添加一個方法app
public Student getStudent(Student student);
2)若是要寫下列的SQL語句,只要是不爲空,就做爲查詢條件,以下所示,這樣寫其實是有問題的,因此咱們要寫成動態SQL語句:ide
<select id="getEmployeeByConditionIf" resultType="com.neuedu.entity.Employee"> select *from tbl_employee where id = #{id} and user_name = #{userName} and email = #{email} and gender = #{gender} </select>
3)用if標籤改寫爲動態SQL,以下所示:測試
<select id="getStudent" resultType="com.neuedu.mybatis.entity.Student"> SELECT * FROM student where <if test="id != null"> id=#{id} </if> <if test="name !=null and name!=''"> and name=#{name} </if> <if test="password !=null and password !=''"> and password=#{password} </if> <if test="email !=null and email !=''"> and email=#{email} </if> </select>
4)測試代碼
@Test public void TestgetStudent(){ StudentMapper bean = ioc.getBean(StudentMapper.class); Student student = new Student(4,"jack", "111", "jack@qq.com"); System.out.println(student); Student student2 = bean.getStudent(student); System.out.println(student2); }
#測試結果沒問題,
可是仔細來講,上面的sql語句是有問題的,當咱們不給動態sql語句傳遞id值的時候,sql語句的拼裝就會有問題!【name前有一個and】
- where 標籤
<select id="getStudent" resultType="com.neuedu.mybatis.entity.Student"> SELECT * FROM student <where> <if test="id != null"> id=#{id} </if> <if test="name !=null and name!=''"> and name=#{name} </if> <if test="password !=null and password !=''"> and password=#{password} </if> <if test="email !=null and email !=''"> and email=#{email} </if> </where> </select>
3.須要注意:where標籤只會去掉第一個多出來的and或者or
也就是說使用where標籤有時候仍是不能解決問題的,那怎麼辦呢?咱們這裏可使用trim標籤!
- trim標籤:能夠自定義字符串的截取規則
<select id="getStudent" resultType="com.neuedu.mybatis.entity.Student"> SELECT * FROM student <trim prefix="where" prefixOverrides="and"> <if test="id != null"> id=#{id} </if> <if test="name !=null and name!=''"> and name=#{name} </if> <if test="password !=null and password !=''"> and password=#{password} </if> <if test="email !=null and email !=''"> and email=#{email} </if> </trim> </select>
- choose標籤:分支選擇,相似於Java中的帶了break的switch...case
至關於確保了第一個case 符合以後,就跳出
案例演示:
1.在EmployeeMapper接口中添加一個方法
public List<Student> getStus(Student student);
2.sql映射文件
<select id="getStus" resultType="com.neuedu.mybatis.entity.Student"> select * from student <where> <choose> <when test="id !=null"> id = #{id} </when> <when test="name !=null and name!=''"> name = #{name} </when> <when test="password !=null and password!=''"> password = #{password} </when> <when test="email !=null and email!=''"> email = #{email} </when> <otherwise> 1 = 1 </otherwise> </choose> </where> </select>
- set標籤:字符串截取,能夠寫在trim裏面
set元素會動態前置set關鍵字,同時也會消除無關的逗號
1)在EmployeeMapper中添加一個更新的方法
public void updateStu(Student student);
2)在sql映射文件中,填寫相應的sql語句,以下所示【set標籤能夠將字段後面的逗號去掉】
<update id="updateStu"> update student <set> <if test="name !=null and name!=''"> name=#{name}, </if> <if test="password !=null and password !=''"> password=#{password}, </if> <if test="email !=null and email !=''"> email=#{email} </if> </set> where id = #{id} </update>
3)測試類代碼爲
@Test public void TestUpdateStu(){ StudentMapper bean = ioc.getBean(StudentMapper.class); bean.updateStu(new Student(4, "jackk", null, null)); }
將set標籤用trim標籤代替
<update id="updateStu"> update student <trim prefix="set" suffixOverrides=","> <if test="name !=null and name!=''"> name=#{name}, </if> <if test="password !=null and password !=''"> password=#{password}, </if> <if test="email !=null and email !=''"> email=#{email} </if> </trim> where id = #{id} </update>
- foreach:遍歷元素
public List<Student> getStuByIdForEach(@Param("ids")List<Integer> ids);
2.在MyBatis的sql映射文件中寫相應的代碼
<select id="getStuByIdForEach" resultType="com.neuedu.mybatis.entity.Student"> select * from student where id in <foreach collection="ids" item="id" open="(" close=")" separator=","> #{id} </foreach> </select>
3.測試類代碼
@Test public void getStuByIdForEach(){ StudentMapper bean = ioc.getBean(StudentMapper.class); List<Integer> list = Arrays.asList(16,17,18,19); List<Student> stuByIdForEachlist = bean.getStuByIdForEach(list); for (Student student : stuByIdForEachlist) { System.out.println(student); } }
foreach標籤還能夠用於批量保存數據,
1.在EmployeeMapper接口類中添加批量插入的方法
public void insertStus(@Param("stus")List<Student> student);
2.在EmployeeMapper.xml的sql映射文件中添加響應的語句
foreach 中用 collection,collection中是從Mapper接口傳來的參數,separator是去掉中間符號
<insert id="insertStus"> insert into student (name,password,email) values <foreach collection="stus" item="stu" separator=","> (#{stu.name},#{stu.password},#{stu.email}) </foreach> </insert>
3.測試代碼
@Test public void TestInsertStus(){ StudentMapper bean = ioc.getBean(StudentMapper.class); List<Student> list = new ArrayList<Student>(); list.add(new Student("123","123", "123")); list.add(new Student("123","123", "123")); list.add(new Student("123","123", "123")); bean.insertStus(list); }
MyBatis-緩存機制
一級緩存:
案例:測試一級緩存【默認是開啓的】
@Test public void TestFirstCache(){ SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); session = sqlSessionFactory.openSession(); mapper = session.getMapper(EmployeeMapper.class); Employee emp = mapper.getEmpInfoById(4); System.out.println(emp); Employee emp2 = mapper.getEmpInfoById(4); System.out.println(emp2); System.out.println(emp == emp2); session.commit(); session.close(); }
一級緩存失效的狀況【4種】(沒有使用到當前一級緩存的狀況,效果就是,還須要再向數據庫發出查詢)
1.sqlSession不一樣,從新定義SqlSession
將返回兩條select語句
將返回false,說明emp2不是emp的緩存
@Test public void TestFirstCache(){ SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); session = sqlSessionFactory.openSession(); mapper = session.getMapper(EmployeeMapper.class); Employee emp = mapper.getEmpInfoById(4); System.out.println(emp); SqlSession session2 = sqlSessionFactory.openSession(); EmployeeMapper mapper2 = session2.getMapper(EmployeeMapper.class); Employee emp2 = mapper2.getEmpInfoById(4); System.out.println(emp2); System.out.println(emp == emp2); session.commit(); session.close(); }
2.SqlSession相同,可是查詢條件不同[當前緩存中尚未這個數據]
就是至關於根據不一樣條件再次查找
@Test public void TestFirstCache(){ SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); session = sqlSessionFactory.openSession(); mapper = session.getMapper(EmployeeMapper.class); Employee emp = mapper.getEmpInfoById(4); System.out.println(emp); Employee emp2 = mapper.getEmpInfoById(16); System.out.println(emp2); System.out.println(emp == emp2); session.commit(); session.close(); }
3.SqlSession相同,可是兩次查詢之間執行了增刪改操做【此次增刪改可能對當前數據有影響】
由於默認自動刷新了緩存
@Test public void TestFirstCache(){ SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); session = sqlSessionFactory.openSession(); mapper = session.getMapper(EmployeeMapper.class); Employee emp = mapper.getEmpInfoById(4); System.out.println(emp); mapper.deleteEmp(16); Employee emp2 = mapper.getEmpInfoById(4); System.out.println(emp2); System.out.println(emp == emp2); session.commit(); session.close(); }
4.SqlSession相同,手動清除了一級緩存[緩存清空]
手動清除了緩存,因此得從新查找
@Test public void TestFirstCache(){ SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); session = sqlSessionFactory.openSession(); mapper = session.getMapper(EmployeeMapper.class); Employee emp = mapper.getEmpInfoById(4); System.out.println(emp); session.clearCache(); Employee emp2 = mapper.getEmpInfoById(4); System.out.println(emp2); System.out.println(emp == emp2); session.commit(); session.close(); }
二級緩存:
案例:
1)開啓全局二級緩存配置:
<setting name="cacheEnabled" value="true"/>
2)去mapper.xml中配置使用二級緩存
<cache eviction="FIFO" size="100" readOnly="false"/>
3)咱們的POJO須要實現序列化接口[implements Serializable]
4)必須先關閉以前的sqlsession對象
測試:
能夠看到只發送了一次SQL語句,第二次查詢時從二級緩存中拿到的數據,並無發送新的sql語句。
@Test public void TestFirstCache(){ SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); session = sqlSessionFactory.openSession(); mapper = session.getMapper(EmployeeMapper.class); Employee emp = mapper.getEmpInfoById(4); System.out.println(emp); session.close(); SqlSession session2 = sqlSessionFactory.openSession(); EmployeeMapper mapper2 = session2.getMapper(EmployeeMapper.class); Employee emp2 = mapper2.getEmpInfoById(4); System.out.println(emp2); session2.close(); }
須要注意的是:只有一級緩存中關閉的狀況下,二級緩存纔會被使用。
須要注意的是:在哪一個Mapper.xml文件中開啓了<cache>緩存標籤,哪一個Mapper中就開啓了二級緩存。