多個學生,對應一個老師java
對於學生這邊而言,關聯多個學生,關聯一個老師 【多對一】git
對於老師而言,集合,一個老師又不少學生 【一對多】github
@Data @NoArgsConstructor @AllArgsConstructor public class teacher { private int id; private String name; }
@Data @NoArgsConstructor @AllArgsConstructor public class student { private int id; private String name; private teacher teacher; }
public interface StudentMapper { public List<student> getStudent(); }
思路:算法
複雜的對象就用association
和collection
sql
對象:association
集合:collection
數據庫
<mapper namespace="com.Dao.StudentMapper"> <resultMap id="stutea" type="pojo.student"> <result property="id" column="id"/> <result property="name" column="name"/> <association property="teacher" column="tid" javaType="pojo.teacher" select="getTeacher"/> </resultMap> <select id="getStudent" resultMap="stutea"> select * from mybatistest.stu </select> <select id="getTeacher" resultType="pojo.teacher"> select * from mybatistest.teacher where id = #{id} </select> </mapper>
<mapper namespace="com.Dao.StudentMapper"> <select id="getStudent" resultMap="studentTeacher2"> select s.id,s.name,t.name from mybatistest.stu s,mybatistest.teacher t where s.tid=t.id </select> <resultMap id="studentTeacher2" type="pojo.student"> <result property="id" column="id"/> <result property="name" column="name"/> <association property="teacher" javaType="pojo.teacher"> <result property="name" column="name"/> </association> </resultMap> </mapper>
@Test public void getStudent(){ SqlSession sqlSession = mybatis_util.getSqlSession1(); StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); List<student> student = mapper.getStudent(); for (pojo.student student1 : student) { System.out.println(student1); } sqlSession.close(); }
數據庫不變
緩存
@Data @NoArgsConstructor @AllArgsConstructor public class teacher { private int id; private String name; private List<student> students; }
@Data @NoArgsConstructor @AllArgsConstructor public class student { private int id; private String name; // private teacher teacher; private int tid; }
public interface TeacherMapper { public teacher getTeacher(@Param("tid") int id); }
<mapper namespace="com.Dao.TeacherMapper"> <select id="getTeacher" resultMap="geTeacher" > select * from mybatistest.teacher where id = #{tid} </select> <resultMap id="geTeacher" type="pojo.teacher"> <collection property="students" javaType="ArrayList" ofType="pojo.student" select="getStudent" column="id"></collection> </resultMap> <select id="getStudent" resultType="pojo.student"> select * from mybatistest.stu where tid = #{tid} </select> </mapper>
<mapper namespace="com.Dao.TeacherMapper"> <select id="getTeacher" resultMap="teacherStudent"> select t.id tid,t.name tname,s.id sid,s.name sname from mybatistest.stu s,mybatistest.teacher t where s.tid=t.id and t.id=#{tid} </select> <resultMap id="teacherStudent" type="pojo.teacher"> <result property="id" column="tid"/> <result property="name" column="tname"/> <collection property="students" ofType="pojo.student"> <result property="id" column="sid"/> <result property="name" column="sname"/> <result property="tid" column="tid"/> </collection> </resultMap> </mapper>
@Test public void getTeacher(){ SqlSession sqlSession = mybatis_util.getSqlSession1(); TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class); teacher teacher = mapper.getTeacher(1); System.out.println(teacher); sqlSession.close(); }
ofType & javaType安全
javaType
用來指定實體類中屬性ofTyoe
用來指定映射到List或者集合中pojo類型,泛型中的約束類型注意點:注意一對多和多對一中,屬性名和字段的問題mybatis
動態SQL就是指根據不一樣的條件生成不一樣的SQL語句app
CREATE TABLE `blog`( `id` INT(10) NOT NULL COMMENT '博客id', `title` VARCHAR(20) NOT NULL COMMENT '博客標題', `author` VARCHAR(10) NOT NULL COMMENT '做者', `create_time` DATETIME NOT NULL COMMENT '建立時間', `views` INT(20) NOT NULL COMMENT '瀏覽量' )ENGINE=INNODB CHARSET=utf8;
@Data @NoArgsConstructor @AllArgsConstructor public class Blog { private String id; private String title; private String author; private Date createTime; private int views; }
public interface BlogMapper { public int addBlog(Blog blog); }
<mapper namespace="com.Dao.BlogMapper"> <insert id="addBlog" parameterType="pojo.Blog"> insert into mybatistest.blog(id,title,author,create_time,views) values (#{id},#{title},#{author},#{createTime},#{views}) </insert> </mapper>
@Test public void Test(){ SqlSession sqlSession = mybatis_util.getSqlSession1(); BlogMapper mapper = sqlSession.getMapper(BlogMapper.class); Blog blog = new Blog(1, "title", "張", new Date(), 11); int i = mapper.addBlog(blog); System.out.println(i); }
接口
public interface BlogMapper { public List<Blog> queryBlogIF(Map map); }
映射文件
<mapper namespace="com.Dao.BlogMapper"> <select id="queryBlogIF" parameterType="map" resultType="pojo.Blog"> select * from mybatistest.blog where 1=1 <if test="views != null"> and views > #{views} </if> <if test="author != null"> and author=#{author} </if> <if test="title != null"> and title like #{title} </if> </select> </mapper>
測試
@Test public void queryBlogIF(){ SqlSession sqlSession = mybatis_util.getSqlSession1(); BlogMapper mapper = sqlSession.getMapper(BlogMapper.class); HashMap<String, Object> map = new HashMap<String, Object>(); map.put("views",10); List<Blog> blogs = mapper.queryBlogIF(map); for (Blog blog : blogs) { System.out.println(blog); } }
注意:
在配置文件中綁定:
<mappers> <mapper class="com.Dao.BlogMapper"/> </mappers>
這是由於在實體類中,數據庫中定義時間屬性爲:create_time,有_
。
能夠開啓駝峯命名法映射,在配置文件中加入:
<settings> <setting name="mapUnderscoreToCamelCase" value="true"/> </settings>
在數據庫字段命名規範中經常用下劃線 "_" 對單詞進行鏈接,如:"create_time"
,而開發中實體屬性一般會採用駝峯命名法命名爲 createTime
。
接口
public interface BlogMapper { public List<Blog> queryBlogChoose(Map map); }
映射文件
<select id="queryBlogChoose" parameterType="map" resultType="pojo.Blog"> select * from mybatistest.blog <where> <choose> <when test="title != null"> and title like #{title} </when> <when test="author != null"> and author = #{author} </when> <otherwise> and views > #{views} </otherwise> </choose> </where> </select>
測試
@Test public void queryBlogChoose(){ SqlSession sqlSession = mybatis_util.getSqlSession1(); BlogMapper mapper = sqlSession.getMapper(BlogMapper.class); HashMap<String, Object> map = new HashMap<String, Object>(); map.put("title","%啦%"); List<Blog> blogs = mapper.queryBlogChoose(map); for (Blog blog : blogs) { System.out.println(blog); } }
where
元素只會在子元素返回任何內容的狀況下才插入 「WHERE」 子句。並且,若子句的開頭爲 AND
或 OR
,where 元素也會將它們去除。
<where> <if test="views != null"> views > #{views} </if> <if test="author != null"> and author=#{author} </if> <if test="title != null"> and title like #{title} </if> </where>
set
元素能夠用於動態包含須要更新的列,忽略其它不更新的列。
接口
public int updateBlogSet(Map map);
映射文件
<update id="updateBlogSet" parameterType="map"> update mybatistest.blog <set> <if test="title != null">title=#{title},</if> <if test="author != null">author=#{author},</if> <if test="views != null">views=#{views},</if> </set> where id=#{id} </update>
測試
@Test public void updateBlogSet(){ SqlSession sqlSession = mybatis_util.getSqlSession1(); BlogMapper mapper = sqlSession.getMapper(BlogMapper.class); HashMap<String, Object> map = new HashMap<String, Object>(); map.put("id",1); map.put("title","t-test"); map.put("author","a-test"); map.put("views",100); int i = mapper.updateBlogSet(map); System.out.println(i); HashMap map1 = new HashMap(); List<Blog> blogs = mapper.queryBlogIF(map1); for (Blog blog : blogs) { System.out.println(blog); } }
接口
public List<Blog> queryBlogForeach(Map map);
映射文件
<select id="queryBlogForeach" parameterType="map"> select * from mybatistest.blog <where> /*此處的collection是一個list,因此map須要傳入一個list來進行遍歷*/ <foreach collection="ids" item="id" open="and (" close=")" separator="or"> id=#{id} </foreach> <if test="views != null"> and views > #{views} </if> <if test="author != null"> and author=#{author} </if> </where> </select>
測試
@Test public void queryBlogForeach(){ SqlSession sqlSession = mybatis_util.getSqlSession1(); BlogMapper mapper = sqlSession.getMapper(BlogMapper.class); HashMap<String, Object> map = new HashMap<String, Object>(); List<Integer> ids = new ArrayList<Integer>(); ids.add(2); ids.add(3); map.put("ids",ids); List<Blog> blogs = mapper.queryBlogForeach(map); for (Blog blog : blogs) { System.out.println(blog); } }
咱們能夠將一些公共的部分用<sql>
抽取出來,方便複用!
<sql id="id-test"> <choose> <when test="title != null"> and title like #{title} </when> <when test="author != null"> and author = #{author} </when> <otherwise> and views > #{views} </otherwise> </choose> </sql> <select id="queryBlogChoose" parameterType="map" resultType="pojo.Blog"> select * from mybatistest.blog <where> <include refid="id-test"></include> </where> </select>
動態SQL
就是在拼接SQL語句,咱們只要保證SQL的正確性,按照SQL的格式,去排列組合就能夠了
咱們能夠先在Mysql中寫出完整的SQL,在對應的去修改稱爲咱們的動態SQL
查詢:鏈接數據庫,耗資源!
一次查詢的結果,給他暫存在一個能夠直接取到的地方——內存:緩存
那麼咱們再次查詢的時候就能夠不用走數據庫了
Mybatis系統中默認頂一個兩級緩存:一級緩存和二級緩存
注意事項:
- 映射語句文件中的全部 select 語句的結果將會被緩存。
- 映射語句文件中的全部 insert、update 和 delete 語句會刷新緩存。
- 緩存會使用最近最少使用算法(LRU, Least Recently Used)算法來清除不須要的緩存。
- 緩存不會定時進行刷新(也就是說,沒有刷新間隔)。
- 緩存會保存列表或對象(不管查詢方法返回哪一種)的 1024 個引用。緩存會被視爲讀/寫緩存,這意味着獲取到的對象並非共享的,能夠安全地被調用者修改,而不干擾其餘調用者或線程所作的潛在修改。
一級緩存也叫本地緩存:
測試
@Test public void cache(){ SqlSession sqlSession = mybatis_util.getSqlSession1(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); user user = mapper.getUserById(1); System.out.println(user); System.out.println("==============================="); user user1 = mapper.getUserById(1); System.out.println(user1); System.out.println(user==user1); sqlSession.close(); }
從圖中能夠看出,數據在一級緩存,只查詢一次,這二者相同,爲true
手動清理緩存
@Test public void cache(){ SqlSession sqlSession = mybatis_util.getSqlSession1(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); user user = mapper.getUserById(1); System.out.println(user); sqlSession.clearCache(); //手動清理緩存 System.out.println("==============================="); user user1 = mapper.getUserById(1); System.out.println(user1); System.out.println(user==user1); sqlSession.close(); }
從圖中能夠看出,數據在一級緩存,手動清理緩存後,查詢了兩次,這二者不一樣,爲false
二級緩存是基於namespace的緩存,它的做用域比一級大
在配置文件開啓二級緩存
<setting name="cacheEnabled" value="true"/>
在對應的mapper.xml
中選擇開啓二級緩存
<cache/>
也能夠自定義cache
<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>
@Test public void SecondCache(){ SqlSession sqlSession = mybatis_util.getSqlSession(); UserDao mapper = sqlSession.getMapper(UserDao.class); user user = mapper.getUserByID(1); System.out.println(user); sqlSession.close(); System.out.println("==============================="); SqlSession sqlSession1 = mybatis_util.getSqlSession(); UserDao mapper1 = sqlSession1.getMapper(UserDao.class); user user1 = mapper1.getUserByID(1); System.out.println(user1); System.out.println(user==user1); sqlSession.close(); }
從圖中能夠看出,開啓二級緩存後,sqlSession關閉時,數據存入二級緩存,直接在二級緩存調出數據,只用查詢了一次 ,這二者不一樣,爲false
注意:可能會出現的錯誤:
Error serializing object. Cause:java.io.NotSerializableException: pojo.user
,這個錯誤只須要在實體類繼承Serializable
,即:class user implements Serializable
Ehcache是一種普遍使用的開源Java分佈式緩存。EhCache 是一個純Java的進程內緩存框架,具備快速、精幹等特色,是Hibernate中默認的CacheProvider。
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-ehcache --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-ehcache</artifactId> <version>1.0.0</version> </dependency>
建立ehcache.xml
<?xml version="1.0" encoding="UTF-8"?> <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd" updateCheck="false"> <diskStore path="./tmpdir/Tmp_EhCache"/> <defaultCache eternal="false" maxElementsInMemory="10000" overflowToDisk="false" diskPersistent="false" timeToIdleSeconds="1800" timeToLiveSeconds="259200" memoryStoreEvictionPolicy="LRU"/> <cache name="cloud_user" eternal="false" maxElementsInMemory="5000" overflowToDisk="false" diskPersistent="false" timeToIdleSeconds="1800" timeToLiveSeconds="1800" memoryStoreEvictionPolicy="LRU"/> </ehcache>
<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
其實沒什麼大的區別,想用能夠用