= 建立數據庫,表,表數據html
CREATE TABLE `user` ( `id` int(20) NOT NULL AUTO_INCREMENT,#id不爲0,自增 `name` varchar(30) DEFAULT NULL,#name默認null `pwd` varchar(30) DEFAULT NULL,#pwd默認null PRIMARY KEY (`id`)#主鍵索引=id )ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8; INSERT INTO `user` VALUES(1,'狂神','123456'); INSERT INTO `user` VALUES(2,'張三','123456'); INSERT INTO `user` VALUES(3,'李四','123456');
<dependency> <!--mysql驅動--> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.48</version> </dependency> <dependency> <!--mybatis官網--> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.2</version> </dependency> <dependency> <!-- junit測試--> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency>
防止後綴爲properties和xml配置文件沒法加載java
<!--資源過濾器,防止導入資源失敗問題,最好在父子pom.xml裏都加入一下代碼--> <build> <resources> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>true</filtering> </resource> <resource> <directory>src/main/java</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>true</filtering> </resource> </resources> </build>
<?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> <!--數據源--> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <!--鏈接數據庫,所有都要被下來--> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=false&useUnicode=true&characterEncoding=utf-8"/> <property name="username" value="root"/> <property name="password" value="admin"/> </dataSource> </environment> </environments> <!--mapper注入mybatis--> <mappers> <mapper resource="com/ssl/dao/UserMapper.xml"/> </mappers> </configuration>
public class MyBatisUtil { /** * 提高sqlSessionFactory做用域,便於全局使用 */ private static SqlSessionFactory sqlSessionFactory; static { try { /* 使用Mybatis第一步,獲取sqlSessionFactory對象 */ String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } catch (IOException e) { e.printStackTrace(); } } /** * sqlSessionFactory對象獲取SQLSession實例 */ public static SqlSession getSqlSession() { return sqlSessionFactory.openSession(); } }
public interface UserDao { List<User> getUserList(); }
<?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"> <!--namespace命名空間=要實現的dao接口--> <mapper namespace="com.ssl.dao.UserDao"> <select id="getUserList" resultType="com.ssl.pojo.User"> select * from mybatis.user </select> </mapper>
<mappers> <mapper resource="com/ssl/dao/UserMapper.xml"/> </mappers>
public class UserMapperTest { @Test public void getUserList() { //1 獲取是sqlSession對象 SqlSession sqlSession = MyBatisUtil.getSqlSession(); //2 獲取的是接口的.class,由於多態 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); List<User> userList = userMapper.getUserList(); for (User user : userList) { System.out.println(user); } //3 建議:最後關閉sqlSession sqlSession.close(); } }
<mapper namespace="com.ssl.dao.UserMapper"> <select id="getUserList" resultType="com.ssl.pojo.User"> select * from mybatis.user </select> </mapper>
<mapper namespace="com.ssl.dao.UserMapper"> <!--增刪改須要提交事務,沒有指定的返回值,都是int,因此不用添加resultType--> <!--添加一個用戶,對象中的屬性能夠直接取出來--> <insert id="addUser" parameterType="com.ssl.pojo.User"> INSERT INTO mybatis.user(id,NAME,pwd) VALUES (#{id},#{name},#{pwd}); </insert> <update id="updateUser" parameterType="com.ssl.pojo.User"> update mybatis.user set name = #{name},pwd=#{pwd} where id=#{id}; </update> <delete id="deleteUserById" parameterType="int"> delete from mybatis.user where id=#{id} </delete> </mapper>
# 增長鬚要values insert into mybatis.user(id,NAME,pwd) VALUES (#{id},#{name},#{pwd}); # 修改須要set update mybatis.user set name = #{name},pwd=#{pwd} where id=#{id}; # 刪除須要from delete from mybatis.user where id=#{id}
<!--模糊查詢1 不推薦--> <select id="getLikeUser1" parameterType="string" resultType="com.ssl.pojo.User"> select * from mybatis.user where name like #{value}; </select> <!--模糊查詢2 建議寫死--> <select id="getLikeUser2" parameterType="string" resultType="com.ssl.pojo.User"> select * from mybatis.user where name like "%"#{value}"%"; </select>
<environments default="development"> <environment id="development"> <!--事務管理器:默認JDBC--> <transactionManager type="JDBC"/> <!--鏈接數據源:默認POOLED--> <dataSource type="POOLED"> <property name="driver" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </dataSource> </environment> </environments>
driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/mybatis?useSSL=false&useUnicode=true&characterEncoding=utf-8 username=root password=123456
settings配置 | 解釋說明 | 默認狀態 |
---|---|---|
cacheEnabled(重要) | 全局性地開啓或關閉全部映射器配置文件中已配置的任何緩存。 | 默認開啓 |
lazyLoadingEnabled | 延遲加載的全局開關。當開啓時,全部關聯對象都會延遲加載。 特定關聯關係中可經過設置 fetchType 屬性來覆蓋該項的開關狀態。 | 默認關閉 |
mapUnderscoreToCamelCase(重要) | 是否開啓駝峯命名自動映射,即從經典數據庫列名 A_COLUMN 映射到經典 Java 屬性名 aColumn。 | 默認關閉 |
logImpl(最重要) | 指定 MyBatis 所用日誌的具體實現,未指定時將自動查找。 | SLF4J、LOG4J、STDOUT_LOGGING等,默認關閉 |
<!--給各類類取別名,簡化使用配置--> <typeAliases> <!--方式一:指定類 <typeAlias alias="User" type="com.ssl.pojo.User"/> --> <!--方式二;指定包,包中的小寫做爲別名 也能夠更改小寫名,在類上使用@value(「別名」) --> <package name="com.ssl.pojo"/> </typeAliases>
後期須要加深學習的兩大插件,使Mybatis配置更加簡單mysql
<!-- 使用resource相對於類路徑的資源引用 --> <mappers> <mapper resource="org/mybatis/builder/AuthorMapper.xml"/> <mapper resource="org/mybatis/builder/BlogMapper.xml"/> <mapper resource="org/mybatis/builder/PostMapper.xml"/> </mappers>
<!-- 使用class映射器接口實現類的徹底限定類名 --> <mappers> <mapper class="org.mybatis.builder.AuthorMapper"/> <mapper class="org.mybatis.builder.BlogMapper"/> <mapper class="org.mybatis.builder.PostMapper"/> </mappers> <!-- 使用package+name將包內的映射器接口實現所有註冊爲映射器 --> <mappers> <package name="org.mybatis.builder"/> </mappers>
名稱 | 解釋說明 |
---|---|
SqlSessionFactoryBuilder | 一旦建立就再也不須要它了,做用域是局部變量=靜態代碼塊先加載 |
SqlSessionFactory | 運行期間一直存在,做用域是應用做用域,使用單例模式或者靜態單例模式。 |
SqlSession | 鏈接到數據庫的請求,線程不安全,用完後立刻關閉;做用域是方法或者請求中,用完就關閉,關閉操做十分重要 |
public class MyBatisUtil { //0 提高第三步中sqlSessionFactory做用域 private static SqlSessionFactory sqlSessionFactory; static { try { //1 獲取mybatis配置文件 String resource = "mybatis-config.xml"; //2 獲取配置文件的輸入流 InputStream inputStream = Resources.getResourceAsStream(resource); //3 使用SqlSessionFactoryBuilder().build()建立sqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } catch (IOException e) { e.printStackTrace(); } } //4 經過getSqlSession獲取session public static SqlSession getSqlSession() { return sqlSessionFactory.openSession(true); } }
//查詢結果:不一致的字段查詢結果爲null User{id=1, name='狂神', password='null'}
<?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"> <!--namespace命名空間=要實現的dao接口=原來的dao實現類--> <mapper namespace="com.ssl.dao.UserMapper"> <!--更改結果集映射,解決屬性名和數據庫列名不一致--> <resultMap id="UserMap" type="com.ssl.pojo.User"> <result column="pwd" property="password"/> </resultMap> <!--經過id查詢一個用戶--> <select id="getUserById" parameterType="int" resultMap="UserMap"> select * from mybatis.user where id = #{id}; </select> </mapper>
LOG4J:必須掌握,步驟:setting配置,導包,配置pro,測試時加載面試
setting配置,+導依賴包算法
<settings> <setting name="logImpl" value="log4j"/> </settings>
<!--log4j日誌--> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency>
log4j.properties:須要時去網上找一份spring
# log4j日誌系統:通用配置 # Define the root logger with appender file # log=D:\logs log4j.rootLogger = DEBUG, FILE, console # 輸出到當前目錄文件下的log包中 log4j.appender.FILE=org.apache.log4j.FileAppender log4j.appender.FILE.File=./logs/log4j.log # Set the immediate flush to true (default) log4j.appender.FILE.ImmediateFlush=true # Set the threshold to debug mode log4j.appender.FILE.Threshold=debug # Set the threshold to debug mode # 設置日誌信息追加 log4j.appender.FILE.Append=true # Set the maximum file size before rollover # 30MB log4j.appender.FILE.MaxFileSize=5KB # Set the backup index log4j.appender.FILE.MaxBackupIndex=2 # Define the layout for file appender log4j.appender.FILE.layout=org.apache.log4j.PatternLayout log4j.appender.FILE.layout.conversionPattern=%m%n # 將日誌輸出到控制檯 log4j.appender.console=org.apache.log4j.ConsoleAppender log4j.appender.console.layout=org.apache.log4j.PatternLayout log4j.appender.console.layout.ConversionPattern=[%d{yyyy-MM-dd HH:mm:ss}]-[%t]-[%F:%L]-[%p]-[%c]-%m%n #log4j.appender.console.layout.ConversionPattern=[%d{yyyy-MM-dd}]-[%t]-[%x]-[%-5p]-[%-10c:%m%n] log4j.appender.console.encoding=UTF-8
test中:static Logger logger = Logger.getLogger(UserMapperTest.class);
sql
public class UserMapperTest { //使用log4j static Logger logger = Logger.getLogger(UserMapperTest.class); @Test public void getUserById() { //1 獲取是sqlSession對象 SqlSession sqlSession = MyBatisUtil.getSqlSession(); //2 獲取方式一:getMapper UserMapper userMapper = sqlSession.getMapper(UserMapper.class); User user = userMapper.getUserById(1); System.out.println(user); //3 建議:最後關閉sqlSession sqlSession.close(); } }
<settings> <!-- <setting name="logImpl" value="log4j"/>--> <setting name="logImpl" value="STDOUT_LOGGING"/> </settings>
select * from user limit startIndex,pageSize;# startIndex=(第幾頁-1)*pageSize select * from user limit index;# 默認從第一個元素到第index個用戶
public interface UserMapper { /** * 根據id獲取一個用戶 * @param id 指定 * @return User */ User getUserById(int id); /** * 經過map分頁數據,推薦使用 * @param map 經常使用 * @return ListUser */ List<User> getLimitUser(Map<String,Object> map); /** * 瞭解,不推薦使用,經過RowBounds分頁數據 * @return ListUser */ List<User> getLimitUserByRowBounds(); }
<?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.ssl.dao.UserMapper"> <!--更改結果集映射,解決屬性名和數據庫列名不一致--> <resultMap id="UserMap" type="com.ssl.pojo.User"> <result column="pwd" property="password"/> </resultMap> <!--map分頁--> <select id="getLimitUser" parameterType="map" resultMap="UserMap"> select * from mybatis.user limit #{startIndex},#{pageSize}; </select> <!--RowBounds分頁--> <select id="getLimitUserByRowBounds" resultMap="UserMap"> select * from mybatis.user ; </select> </mapper>
public class UserMapperTest { @Test public void getLimitUser() { UserMapper userMapper = MyBatisUtil.getSqlSession().getMapper(UserMapper.class); Map<String, Object> map = new HashMap<>(); //mapper.xml會自動尋找map中的key=#{key} map.put("startIndex",0); map.put("pageSize",2); List<User> limitUser = userMapper.getLimitUser(map); for (User user : limitUser) { System.out.println(user); } } @Test public void getLimitUserBrRowBounds() { SqlSession sqlSession = MyBatisUtil.getSqlSession(); //老式的查詢分頁:使用RowBounds RowBounds rowBounds = new RowBounds(0, 2); //語法麻煩 List<User> usersList = sqlSession.selectList("com.ssl.dao.UserMapper.getLimitUserByRowBounds",0,rowBounds); for (User user : usersList) { System.out.println(user); } } }
<!--綁定註解開發的接口 class--> <mappers> <mapper class="com.ssl.dao.UserMapper"/> </mappers>
學習@param(很是重要)數據庫
public interface UserMapper { /** * 使用註解開發,有侷限性就是column 必須與 dao接口成員屬性名一致,否知輸出就是null,查不出來 * 因此註解語句開發,便於使用簡單場景 */ @Select("select * from user") List<User> getUsers(); /** * @param id=uid * @return User */ @Select("select * from user where id = #{uid}") User getUserById(@Param("uid") int id); }
public static SqlSession getSqlSession() { //不推薦使用,建議手動提交commit return sqlSessionFactory.openSession(true); }
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.12</version> </dependency>
新建實體類Student、Teacher和數據庫表apache
CREATE TABLE `student` ( `id` int(10) NOT NULL, `name` varchar(20) DEFAULT NULL, `tid` int(10) DEFAULT NULL, PRIMARY KEY (`id`), KEY `fktid` (`tid`), CONSTRAINT `fktid` FOREIGN KEY (`tid`) REFERENCES `teacher` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 CREATE TABLE `teacher` ( `id` int(10) NOT NULL, `name` varchar(20) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8
@Data @AllArgsConstructor @NoArgsConstructor public class Student { private Integer id; private String name; //須要關聯一個老師類 private Teacher teacher; } @Data @AllArgsConstructor @NoArgsConstructor public class Teacher { private int id; private String name; }
public interface StudentMapper { //子查詢 List<Student> getStudents(); //聯表查詢 List<Student> getStudents1(); }
mapper.xml編程
<!--方式一:按照查詢嵌套處理 = 子查詢--> <select id="getStudents" resultMap="resultStudents"> select * from mybatis.student; </select> <resultMap id="resultStudents" type="student"> <!--association:屬性是對象時使用--> <!--collection:屬性是集合時候用--> <association property="teacher" column="tid" javaType="teacher" select="getTeachers"/> </resultMap> <select id="getTeachers" resultType="teacher"> select * from mybatis.teacher where id = #{tid} </select>
@Test public void getStudents() { StudentMapper studentMapper = MyBatisUtil.getSqlSession().getMapper(StudentMapper.class); List<Student> students = studentMapper.getStudents(); for (Student student : students) { System.out.println(student); } /* Student(id=1, name=小紅, teacher=Teacher(id=1, name=秦老師)) */ }
<!--方式二:按照結果嵌套處理 = 聯表查詢--> <select id="getStudents1" resultMap="resultStudents1"> select s.id sid,s.name sname,t.name tname from student s,teacher t where s.tid = t.id; </select> <resultMap id="resultStudents1" type="student"> <result property="id" column="sid"/> <result property="name" column="sname"/> <association property="teacher" javaType="teacher"> <result property="name" column="tname"/> </association> </resultMap>
@Test public void getStudents1() { StudentMapper studentMapper = MyBatisUtil.getSqlSession().getMapper(StudentMapper.class); List<Student> students = studentMapper.getStudents1(); for (Student student : students) { System.out.println(student); } /* Student(id=1, name=小紅, teacher=Teacher(id=0, name=秦老師)) */ }
@Data @AllArgsConstructor @NoArgsConstructor public class Student { private Integer id; private String name; private int tid; } @Data @AllArgsConstructor @NoArgsConstructor public class Teacher { private int id; private String name; //一對多的集合 private List<Student> students; }
public interface StudentMapper { } public interface TeacherMapper { /** * 子查詢:按查詢嵌套查詢 * @param tid * @return */ Teacher getTeacher(@Param("id") int tid); /** * 聯表查詢:按結果嵌套查詢 * @param tid * @return */ Teacher getTeacher1(@Param("id") int tid); }
<!--子查詢:按查詢嵌套查詢--> <select id="getTeacher" resultMap="teacherToStudent"> select id, name from mybatis.teacher where id = #{id} </select> <resultMap id="teacherToStudent" type="teacher"> <result property="id" column="id"/> <result property="name" column="name"/> <!-- column="id"是teacher表中的id--> <collection property="students" javaType="List" ofType="student" column="id" select="getStudentsByTeacherId" /> </resultMap> <select id="getStudentsByTeacherId" resultType="student"> select * from mybatis.student where tid = #{id} </select>
測試:
@Test public void getTeacher() { TeacherMapper teacherMapper = MyBatisUtil.getSqlSession().getMapper(TeacherMapper.class); Teacher teacher = teacherMapper.getTeacher(1); System.out.println(teacher); /* 若是id=0怎麼解決?就是collection中配置result property="id" column="id" Teacher(id=1, name=秦老師, students=[Student(id=1, name=小紅, tid=1),Student(id=2, name=小明, tid=1)... */ }
<!--聯表查詢:按結果嵌套查詢--> <select id="getTeacher1" resultMap="teacherAndStudent"> select s.id sid,s.name sname,t.name tname,t.id tid from mybatis.teacher t,mybatis.student s where s.tid=t.id and t.id =#{id} </select> <resultMap id="teacherAndStudent" type="teacher"> <result property="id" column="tid"/> <result property="name" column="tname"/> <!--集合對象用collection綁定,javaType是返回單個屬性,不能返回集合, 返回屬性是集合用ofType綁定--> <collection property="students" ofType="student"> <result property="id" column="sid"/> <result property="name" column="sname"/> <result property="tid" column="tid"/> </collection> </resultMap>
測試:
@Test public void getTeacher1() { TeacherMapper teacherMapper = MyBatisUtil.getSqlSession().getMapper(TeacherMapper.class); Teacher teacher = teacherMapper.getTeacher1(1); System.out.println(teacher); /* Teacher(id=1, name=秦老師, students=[Student(id=1, name=小紅, tid=1), Student(id=2, name=小明, tid=1)... */ }
javaType & ofType
注意點:
四個判斷條件:
CREATE TABLE blog( id VARCHAR(50) NOT NULL COMMENT '博客id', title VARCHAR(100) NOT NULL COMMENT '博客標題', author VARBINARY(30) NOT NULL COMMENT'博客做者', # 數據庫時間DateTime類型=pojo中的Date類型 # 下劃線命名調到pojo中的駝峯式命令,須要mybatis開啓駝峯式命令 create_time DATETIME NOT NULL COMMENT'建立時間', views INT(30) NOT NULL COMMENT'瀏覽量' )ENGINE=INNODB DEFAULT CHARSET = utf8;
@Data @AllArgsConstructor @NoArgsConstructor public class Blog { private String id; private String title; private String author; /** * 下劃線命名調到pojo中的駝峯式命令,須要mybatis開啓駝峯式命令 */ private Date createTime; private int views; }
<!--解決駝峯命令,使用setting配置,只能用戶數據庫中的xx_xx編程bean中的駝峯式--> <settings> <setting name="logImpl" value="STDOUT_LOGGING"/> <setting name="mapUnderscoreToCamelCase" value="true"/> </settings>
public class MyBatisUtil { /** * 提高sqlSessionFactory做用域,便於全局使用 */ private static SqlSessionFactory sqlSessionFactory; static { try { /* 使用Mybatis第一步,獲取sqlSessionFactory對象 */ String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } catch (IOException e) { e.printStackTrace(); } } /** * sqlSessionFactory對象獲取SQLSession實例 */ public static SqlSession getSqlSession() { return sqlSessionFactory.openSession(true); } } //隨機產生數據庫表中的views public class UUIDUtils { public static String getId() { return UUID.randomUUID().toString().replaceAll("-", ""); } @Test public void getUUId() { System.out.println(UUIDUtils.getId()); } }
public interface BlogMapper { int addBlog(Blog blog); List<Blog> queryBlogByIf(Map map); List<Blog> queryBlogByWhere(Map map); List<Blog> queryBlogByForeach(Map map); }
方式一:經過< if >直接使用,或者< include>跳轉sql使用時候,須要保證where成立,因此須要在sql語句中加上相似where 1= 1
或者 where state = 'active'
等語句
<!--if:經過include跳轉到使用,缺點是必須寫上判斷條件成立 where 1=1--> <select id="queryBlogByIf" parameterType="map" resultType="Blog"> select * from mybatis.blog where 1=1 <include refid="if_title_author_like" /> </select> <sql id="if_title_author_like"> <if test="title !=null"> and title like #{title} </if> <if test="author !=null"> and author like #{author} </if> </sql>
where 1= 1
<!--if:經過where直接使用/直接使用if判斷,可是不推薦。原理:若是test存在,就自動加上where --> <select id="queryBlogByWhere" parameterType="map" resultType="Blog"> select * from mybatis.blog <where> <if test="id !=null"> id like #{id} </if> <if test="views !=null"> and views like #{views} </if> </where> </select>
@Test public void queryBlogByIf() { SqlSession sqlSession = MyBatisUtil.getSqlSession(); BlogMapper blogMapper = sqlSession.getMapper(BlogMapper.class); Map<String, String> map = new HashMap<>(); //模糊查詢,使用map的好處 map.put("title", "%my%"); List<Blog> blogs = blogMapper.queryBlogByIf(map); System.out.println(blogs); sqlSession.close(); } @Test public void queryBlogByWhere() { SqlSession sqlSession = MyBatisUtil.getSqlSession(); BlogMapper blogMapper = sqlSession.getMapper(BlogMapper.class); Map<String, Object> map = new HashMap<>(); //map.put("id","%4%"); map.put("views", "%2%"); List<Blog> blogs = blogMapper.queryBlogByWhere(map); System.out.println(blogs); sqlSession.close(); }
WHERE state = ‘ACTIVE’
等保證where成立<!--官網案例--> <select id="findActiveBlogLike" resultType="Blog"> SELECT * FROM BLOG WHERE state = ‘ACTIVE’ <choose> <when test="title != null"> AND title like #{title} </when> <when test="author != null and author.name != null"> AND author_name like #{author.name} </when> <otherwise> AND featured = 1 </otherwise> </choose> </select>
<select id="findActiveBlogLike" resultType="Blog"> SELECT * FROM BLOG WHERE <if test="state != null"> state = #{state} </if> <if test="title != null"> AND title like #{title} </if> <if test="author != null and author.name != null"> AND author_name like #{author.name} </if> </select>
# 沒有條件成立 SELECT * FROM BLOG WHERE # 第一個條件沒有成立 SELECT * FROM BLOG WHERE AND title like ‘someTitle’
使用< where >
<select id="findActiveBlogLike" resultType="Blog"> SELECT * FROM BLOG <where> <if test="state != null"> state = #{state} </if> <if test="title != null"> AND title like #{title} </if> <if test="author != null and author.name != null"> AND author_name like #{author.name} </if> </where> </select>
使用自定義 trim 元素來定製 where 元素的功能
與< where>等價的< trim>
<trim prefix="WHERE" prefixOverrides="AND |OR "> ... </trim>
概念:用於動態update語句的叫作 set。set 元素能夠用於動態包含須要更新的列,忽略其它不更新的列
<trim prefix="SET" suffixOverrides=","> ... </trim>
<update id="updateAuthorIfNecessary"> 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>
SELECT * FROM blog WHERE 1=1 AND (id=1 OR id=2);
<select id="queryBlogByForeach" parameterType="map" resultType="Blog"> select * from mybatis.blog <where> <foreach collection="ids" item="id" open="(" separator="or" close=")"> id=#{id} </foreach> </where> </select> <!--官網案例:使用in時--> <select id="selectPostIn" resultType="domain.blog.Post"> SELECT * FROM POST P WHERE ID in <foreach item="item" index="index" collection="list" open="(" separator="," close=")"> #{item} </foreach> </select>
細節:
<sql id="if_title_author_like"> <if test="title !=null"> and title like #{title} </if> <if test="author !=null"> and author like #{author} </if> </sql> <select id="queryBlogByIf" parameterType="map" resultType="Blog"> select * from mybatis.blog where 1=1 <include refid="if_title_author_like" /> </select>
<select id="selectBlogsLike" resultType="Blog"> <bind name="pattern" value="'%' + _parameter.getTitle() + '%'" /> SELECT * FROM BLOG WHERE title LIKE #{pattern} </select>
什麼樣的數據須要用到緩存?
二級緩存工做原理:
默認狀況下,只啓用了本地的會話(一級)緩存,它僅僅對一個會話中的數據進行緩存。
緩存失效
sqlSession.clearCache();
<settings> <setting name="logImpl" value="STDOUT_LOGGING"/> <!--開啓全局緩存 默認是開啓的,顯示寫便於可讀--> <setting name="cacheEnabled" value="true"/> </settings>
mappper.xml開啓二級緩存:
<!--開啓二級緩存--> <cache/>
緩存會被視爲讀/寫緩存,這意味着獲取到的對象並非共享的,能夠安全地被調用者修改,而不干擾其餘調用者或線程所作的潛在修改。
@Data @AllArgsConstructor @NoArgsConstructor public class User implements Serializable { private int id; private String name; private String pwd; public static void main(String[] args) { new ArrayList<>(); new HashMap<>(); new LinkedList<>(); } }
開啓二級緩存時,能夠指定參數
<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>
eviction:清楚算法,默認LRU
LRU
– 最近最少使用:移除最長時間不被使用的對象。FIFO
– 先進先出:按對象進入緩存的順序來移除它們。SOFT
– 軟引用:基於垃圾回收器狀態和軟引用規則移除對象。WEAK
– 弱引用:更積極地基於垃圾收集器狀態和弱引用規則移除對象。使用二級緩存
public class MyTest { @Test public void queryUserById() { SqlSession sqlSession = MyBatisUtil.getSqlSession(); SqlSession sqlSession1 = MyBatisUtil.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); User user = mapper.queryUserById(1); //關閉上次sqlSession,若是開啓二級緩存,就會把此次的一級緩存保存到二級緩存中 sqlSession.close(); System.out.println("================="); UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class); //若是開啓二級緩存,下次相同mapper的查詢操做會先重二級緩存中查找 User user1 = mapper1.queryUserById(1); sqlSession1.close(); } }
<!-- https://mvnrepository.com/artifact/org.mybatis.caches/mybatis-ehcache --> <dependency> <groupId>org.mybatis.caches</groupId> <artifactId>mybatis-ehcache</artifactId> <version>1.2.0</version> </dependency>
<cache type="org.mybatis.caches.encache.EhcacheCache"/>
<?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"> <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"/> <!-- diskStore:爲緩存路徑,ehcache分爲內存和磁盤兩級,此屬性定義磁盤的緩存位置。參數解釋以下: user.home – 用戶主目錄 user.dir – 用戶當前工做目錄 java.io.tmpdir – 默認臨時文件路徑 --> <diskStore path="java.io.tmpdir/Tmp_EhCache"/> <!-- defaultCache:默認緩存策略,當ehcache找不到定義的緩存時,則使用這個緩存策略。只能定義一個。 --> <!-- name:緩存名稱。 maxElementsInMemory:緩存最大數目 maxElementsOnDisk:硬盤最大緩存個數。 eternal:對象是否永久有效,一但設置了,timeout將不起做用。 overflowToDisk:是否保存到磁盤,當系統當機時 timeToIdleSeconds:設置對象在失效前的容許閒置時間(單位:秒)。僅當eternal=false對象不是永久有效時使用,可選屬性,默認值是0,也就是可閒置時間無窮大。 timeToLiveSeconds:設置對象在失效前容許存活時間(單位:秒)。最大時間介於建立時間和失效時間之間。僅當eternal=false對象不是永久有效時使用,默認是0.,也就是對象存活時間無窮大。 diskPersistent:是否緩存虛擬機重啓期數據 Whether the disk store persists between restarts of the Virtual Machine. The default value is false. diskSpoolBufferSizeMB:這個參數設置DiskStore(磁盤緩存)的緩存區大小。默認是30MB。每一個Cache都應該有本身的一個緩衝區。 diskExpiryThreadIntervalSeconds:磁盤失效線程運行時間間隔,默認是120秒。 memoryStoreEvictionPolicy:當達到maxElementsInMemory限制時,Ehcache將會根據指定的策略去清理內存。默認策略是LRU(最近最少使用)。你能夠設置爲FIFO(先進先出)或是LFU(較少使用)。 clearOnFlush:內存數量最大時是否清除。 memoryStoreEvictionPolicy:可選策略有:LRU(最近最少使用,默認策略)、FIFO(先進先出)、LFU(最少訪問次數)。 FIFO,first in first out,這個是你們最熟的,先進先出。 LFU, Less Frequently Used,就是上面例子中使用的策略,直白一點就是講一直以來最少被使用的。如上面所講,緩存的元素有一個hit屬性,hit值最小的將會被清出緩存。 LRU,Least Recently Used,最近最少使用的,緩存的元素有一個時間戳,當緩存容量滿了,而又須要騰出地方來緩存新的元素的時候,那麼現有緩存元素中時間戳離當前時間最遠的元素將被清出緩存。 --> </ehcache>