日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

mybatis实战教程(mybatis in action),mybatis入门到精通

發布時間:2024/9/27 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 mybatis实战教程(mybatis in action),mybatis入门到精通 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
 目錄(?) [-]
  • mybatis實戰教程mybatis in action之一開發環境搭建
  • mybatis實戰教程mybatis in action之二以接口的方式編程
  • mybatis實戰教程mybatis in action之三實現數據的增刪改查
  • mybatis實戰教程mybatis in action之四實現關聯數據的查詢
  • mybatis實戰教程mybatis in action之五與spring3集成附源碼
  • mybatis實戰教程mybatis in action之六與Spring MVC 的集成
  • mybatis實戰教程mybatis in action之七實現mybatis分頁源碼下載
  • mybatis實戰教程mybatis in action之八mybatis 動態sql語句
  • mybatis實戰教程mybatis in action之九mybatis 代碼生成工具的使用
  • mybatis SqlSessionDaoSupport的使用附代碼下載
  • 轉自:http://www.yihaomen.com/article/java/302.htm

    (讀者注:其實這個應該叫做很基礎的入門一下下,如果你看過Hibernate了那這個就非常的簡單)

    寫在這個系列前面的話:

    以前曾經用過ibatis,這是mybatis的前身,當時在做項目時,感覺很不錯,比hibernate靈活。性能也比hibernate好。而且也比較輕量級,因為當時在項目中,沒來的及做很很多筆記。后來項目結束了,我也沒寫總結文檔。已經過去好久了。但最近突然又對這個ORM 工具感興趣。因為接下來自己的項目中很有可能采用這個ORM工具。所以在此重新溫習了一下 mybatis, 因此就有了這個系列的 mybatis 教程.

    什么是mybatis
    MyBatis是支持普通SQL查詢,存儲過程和高級映射的優秀持久層框架。MyBatis消除了幾乎所有的JDBC代碼和參數的手工設置以及結果集的檢索。MyBatis使用簡單的XML或注解用于配置和原始映射,將接口和Java的POJOs(Plan Old Java Objects,普通的Java對象)映射成數據庫中的記錄.

    orm工具的基本思想
    無論是用過的hibernate,mybatis,你都可以法相他們有一個共同點:
    1. 從配置文件(通常是XML配置文件中)得到 sessionfactory.
    2. 由sessionfactory? 產生 session
    3. 在session 中完成對數據的增刪改查和事務提交等.
    4. 在用完之后關閉session 。

    5. 在java 對象和 數據庫之間有做mapping 的配置文件,也通常是xml 文件。

    mybatis實戰教程(mybatis in action)之一:開發環境搭建

    mybatis 的開發環境搭建,選擇: eclipse j2ee 版本,mysql 5.1 ,jdk 1.7,mybatis3.2.0.jar包。這些軟件工具均可以到各自的官方網站上下載。
    首先建立一個名字為 MyBaits 的 dynamic web project?
    1. 現階段,你可以直接建立java 工程,但一般都是開發web項目,這個系列教程最后也是web的,所以一開始就建立web工程。
    2. 將 mybatis-3.2.0-SNAPSHOT.jar,mysql-connector-java-5.1.22-bin.jar 拷貝到 web工程的lib目錄.
    3. 創建mysql 測試數據庫和用戶表,注意,這里采用的是 utf-8 編碼

    創建用戶表,并插入一條測試數據
    程序代碼
    Create TABLE `user` (
    ? `id` int(11) NOT NULL AUTO_INCREMENT,
    ? `userName` varchar(50) DEFAULT NULL,
    ? `userAge` int(11) DEFAULT NULL,
    ? `userAddress` varchar(200) DEFAULT NULL,
    ? PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;


    Insert INTO `user` VALUES ('1', 'summer', '100', 'shanghai,pudong');

    到此為止,前期準備工作就完成了。下面開始真正配置mybatis項目了。
    1. 在MyBatis 里面創建兩個源碼目錄,分別為 src_user,test_src, 用如下方式建立,鼠標右鍵點擊 JavaResource.


    2. 設置mybatis 配置文件:Configuration.xml, 在src_user目錄下建立此文件,內容如下:
    程序代碼
    < ?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>
    ??????? <typeAlias alias="User" type="com.yihaomen.mybatis.model.User"/>
    ??? </typeAliases>

    ??? <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://127.0.0.1:3306/mybatis" />
    ??????????? <property name="username" value="root"/>
    ??????????? <property name="password" value="password"/>
    ??????????? </dataSource>
    ??????? </environment>
    ??? </environments>
    ???
    ??? <mappers>
    ??????? <mapper resource="com/yihaomen/mybatis/model/User.xml"/>
    ??? </mappers>
    < /configuration>


    3. 建立與數據庫對應的 java class,以及映射文件.
    在src_user下建立package:com.yihaomen.mybatis.model ,并在這個 package 下建立 User 類:
    程序代碼
    package com.yihaomen.mybatis.model;

    public class User {
    ???
    ??? private int id;
    ??? private String userName;
    ??? private String userAge;
    ??? private String userAddress;
    ???
    ??? public int getId() {
    ??????? return id;
    ??? }
    ??? public void setId(int id) {
    ??????? this.id = id;
    ??? }
    ??? public String getUserName() {
    ??????? return userName;
    ??? }
    ??? public void setUserName(String userName) {
    ??????? this.userName = userName;
    ??? }
    ??? public String getUserAge() {
    ??????? return userAge;
    ??? }
    ??? public void setUserAge(String userAge) {
    ??????? this.userAge = userAge;
    ??? }
    ??? public String getUserAddress() {
    ??????? return userAddress;
    ??? }
    ??? public void setUserAddress(String userAddress) {
    ??????? this.userAddress = userAddress;
    ??? }

    }


    同時建立這個User 的映射文件 User.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.yihaomen.mybatis.models.UserMapper">
    ??? <select id="selectUserByID" parameterType="int" resultType="User">
    ??????? select * from `user` where id = #{id}
    ??? </select>
    < /mapper>


    下面對這幾個配置文件解釋下:
    1.Configuration.xml 是 mybatis 用來建立 sessionFactory 用的,里面主要包含了數據庫連接相關東西,還有 java 類所對應的別名,比如 <typeAlias alias="User" type="com.yihaomen.mybatis.model.User"/> 這個別名非常重要,你在 具體的類的映射中,比如User.xml 中 resultType 就是對應這里的。要保持一致,當然這里的 resultType 還有另外單獨的定義方式,后面再說。
    2.? Configuration.xml 里面 的<mapper resource="com/yihaomen/mybatis/model/User.xml"/>是包含要映射的類的xml配置文件。
    3. 在User.xml 文件里面 主要是定義各種SQL 語句,以及這些語句的參數,以及要返回的類型等.

    開始測試
    在test_src 源碼目錄下建立com.yihaomen.test這個package,并建立測試類Test:
    程序代碼
    package com.yihaomen.test;

    import java.io.Reader;

    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.apache.ibatis.session.SqlSessionFactoryBuilder;

    import com.yihaomen.mybatis.model.User;

    public class Test {
    ??? private static SqlSessionFactory sqlSessionFactory;
    ??? private static Reader reader;

    ??? static{
    ??????? try{
    ??????????? reader??? = Resources.getResourceAsReader("Configuration.xml");
    ??????????? sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
    ??????? }catch(Exception e){
    ??????????? e.printStackTrace();
    ??????? }
    ??? }

    ??? public static SqlSessionFactory getSession(){
    ??????? return sqlSessionFactory;
    ??? }
    ???
    ??? public static void main(String[] args) {
    ??????? SqlSession session = sqlSessionFactory.openSession();
    ??????? try {
    ??????? User user = (User) session.selectOne("com.yihaomen.mybatis.models.UserMapper.selectUserByID", 1);
    ??????? System.out.println(user.getUserAddress());
    ??????? System.out.println(user.getUserName());
    ??????? } finally {
    ??????? session.close();
    ??????? }
    ??? }
    }

    現在運行這個程序,是不是得到查詢結果了。恭喜你,環境搭建配置成功,接下來第二章,將講述基于接口的操作方式,增刪改查。
    整個工程目錄結構如下:




    除非申明,文章均為一號門原創,轉載請注明本文地址,謝謝!

    mybatis實戰教程(mybatis in action)之二:以接口的方式編程


    前面一章,已經搭建好了eclipse,mybatis,mysql的環境,并且實現了一個簡單的查詢。請注意,這種方式是用SqlSession實例來直接執行已映射的SQL語句:
    session.selectOne("com.yihaomen.mybatis.models.UserMapper.selectUserByID", 1)
    其實還有更簡單的方法,而且是更好的方法,使用合理描述參數和SQL語句返回值的接口(比如IUserOperation.class),這樣現在就可以至此那個更簡單,更安全的代碼,沒有容易發生的字符串文字和轉換的錯誤.下面是詳細過程:

    在src_user源碼目錄下建立 com.yihaomen.mybatis.inter 這個包,并建立接口類 IUserOperation , 內容如下:
    程序代碼
    package com.yihaomen.mybatis.inter;
    import com.yihaomen.mybatis.model.User;

    public interface IUserOperation {???
    ??? public User selectUserByID(int id);
    ???
    }

    請注意,這里面有一個方法名 selectUserByID 必須與 User.xml 里面配置的 select 的id 對應(<select id="selectUserByID")

    重寫測試代碼
    程序代碼
    public static void main(String[] args) {
    ??????? SqlSession session = sqlSessionFactory.openSession();
    ??????? try {
    ??????????? IUserOperation userOperation=session.getMapper(IUserOperation.class);
    ??????????? User user = userOperation.selectUserByID(1);
    ??????????? System.out.println(user.getUserAddress());
    ??????????? System.out.println(user.getUserName());
    ??????? } finally {
    ??????????? session.close();
    ??????? }
    ??? }

    整個工程結構圖現在如下:


    運行這個測試程序,就可以看到結果了。



    除非申明,文章均為一號門原創,轉載請注明本文地址,謝謝!

    mybatis實戰教程(mybatis in action)之三:實現數據的增刪改查


    前面已經講到用接口的方式編程。這種方式,要注意的一個地方就是。在User.xml? 的配置文件中,mapper namespace="com.yihaomen.mybatis.inter.IUserOperation" ,命名空間非常重要,不能有錯,必須與我們定義的package 和 接口一致。如果不一致就會出錯,這一章主要在上一講基于接口編程的基礎上完成如下事情:
    1. 用 mybatis 查詢數據,包括列表
    2. 用 mybatis 增加數據
    3. 用 mybatis 更新數據.
    4. 用 mybatis 刪除數據.

    查詢數據,前面已經講過簡單的,主要看查詢出列表的
    查詢出列表,也就是返回list, 在我們這個例子中也就是 List<User> , 這種方式返回數據,需要在User.xml 里面配置返回的類型 resultMap, 注意不是 resultType, 而這個resultMap 所對應的應該是我們自己配置的
    程序代碼
    < !-- 為了返回list 類型而定義的returnMap -->
    ??? <resultMap type="User" id="resultListUser">
    ??????? <id column="id" property="id" />
    ??????? <result column="userName" property="userName" />
    ??????? <result column="userAge" property="userAge" />
    ??????? <result column="userAddress" property="userAddress" />
    ??? </resultMap>

    查詢列表的語句在 User.xml 中
    程序代碼
    < !-- 返回list 的select 語句,注意 resultMap 的值是指向前面定義好的 -->
    ??? <select id="selectUsers" parameterType="string" resultMap="resultListUser">
    ??????? select * from user where userName like #{userName}
    ??? </select>


    在 IUserOperation 接口中增加方法:public List<User> selectUsers(String userName);???
    現在在 Test 類中做測試
    程序代碼
    public void getUserList(String userName){
    ??????? SqlSession session = sqlSessionFactory.openSession();
    ??????? try {
    ??????????? IUserOperation userOperation=session.getMapper(IUserOperation.class);??????????
    ??????????? List<User> users = userOperation.selectUsers(userName);
    ??????????? for(User user:users){
    ??????????????? System.out.println(user.getId()+":"+user.getUserName()+":"+user.getUserAddress());
    ??????????? }
    ???????????
    ??????? } finally {
    ??????????? session.close();
    ??????? }
    ??? }

    現在在main? 方法中可以測試:
    程序代碼
    public static void main(String[] args) {
    ??????? Test testUser=new Test();
    ??????? testUser.getUserList("%");
    ??? }

    可以看到,結果成功查詢出來。如果是查詢單個數據的話,用第二講用過的方法就可以了。

    用mybatis 增加數據
    在 IUserOperation 接口中增加方法:public void addUser(User user);
    在 User.xml 中配置
    程序代碼
    < !--執行增加操作的SQL語句。id和parameterType?
    ?????? 分別與IUserOperation接口中的addUser方法的名字和?
    ?????? 參數類型一致。以#{name}的形式引用Student參數?
    ?????? 的name屬性,MyBatis將使用反射讀取Student參數?
    ?????? 的此屬性。#{name}中name大小寫敏感。引用其他?
    ?????? 的gender等屬性與此一致。seGeneratedKeys設置?
    ?????? 為"true"表明要MyBatis獲取由數據庫自動生成的主?
    ?????? 鍵;keyProperty="id"指定把獲取到的主鍵值注入?
    ?????? 到Student的id屬性-->
    ??? <insert id="addUser" parameterType="User"
    ??????? useGeneratedKeys="true" keyProperty="id">
    ??????? insert into user(userName,userAge,userAddress)?
    ???????????? values(#{userName},#{userAge},#{userAddress})?
    ??? </insert>

    然后在 Test 中寫測試方法:
    程序代碼
    /**
    ???? * 測試增加,增加后,必須提交事務,否則不會寫入到數據庫.
    ???? */
    ??? public void addUser(){
    ??????? User user=new User();
    ??????? user.setUserAddress("人民廣場");
    ??????? user.setUserName("飛鳥");
    ??????? user.setUserAge(80);
    ??????? SqlSession session = sqlSessionFactory.openSession();
    ??????? try {
    ??????????? IUserOperation userOperation=session.getMapper(IUserOperation.class);
    ??????????? userOperation.addUser(user);
    ??????????? session.commit();
    ??????????? System.out.println("當前增加的用戶 id為:"+user.getId());
    ??????? } finally {
    ??????????? session.close();
    ??????? }
    ??? }


    用mybatis 更新數據
    方法類似,先在 IUserOperation 中增加方法:public void addUser(User user);
    然后配置 User.xml
    程序代碼
    <update id="updateUser" parameterType="User" >
    ??????? update user set userName=#{userName},userAge=#{userAge},userAddress=#{userAddress} where id=#{id}
    ??? </update>

    Test 類總的測試方法如下:
    程序代碼
    public void updateUser(){
    ??????? //先得到用戶,然后修改,提交。
    ??????? SqlSession session = sqlSessionFactory.openSession();
    ??????? try {
    ??????????? IUserOperation userOperation=session.getMapper(IUserOperation.class);
    ??????????? User user = userOperation.selectUserByID(4);???????????
    ??????????? user.setUserAddress("原來是魔都的浦東創新園區");
    ??????????? userOperation.updateUser(user);
    ??????????? session.commit();
    ???????????
    ??????? } finally {
    ??????????? session.close();
    ??????? }
    ??? }


    用mybatis 刪除數據
    同理,IUserOperation 增加方法:public void deleteUser(int id);
    配置User.xml
    程序代碼
    <delete id="deleteUser" parameterType="int">
    ??????? delete from user where id=#{id}
    ??? </delete>

    然后在Test類中寫測試方法:
    程序代碼

    ??? /**
    ???? * 刪除數據,刪除一定要 commit.
    ???? * @param id
    ???? */
    ??? public void deleteUser(int id){
    ??????? SqlSession session = sqlSessionFactory.openSession();
    ??????? try {
    ??????????? IUserOperation userOperation=session.getMapper(IUserOperation.class);??????????
    ??????????? userOperation.deleteUser(id);
    ??????????? session.commit();???????????
    ??????? } finally {
    ??????????? session.close();
    ??????? }
    ??? }


    這樣,所有增刪改查都完成了,注意在增加,更改,刪除的時候要調用session.commit(),這樣才會真正對數據庫進行操作,否則是沒有提交的。

    到此為止,簡單的單表操作,應該都會了,接下來的時間了,我會講多表聯合查詢,以及結果集的選取。


    除非申明,文章均為一號門原創,轉載請注明本文地址,謝謝!

    mybatis實戰教程(mybatis in action)之四:實現關聯數據的查詢


    有了前面幾章的基礎,對一些簡單的應用是可以處理的,但在實際項目中,經常是關聯表的查詢,比如最常見到的多對一,一對多等。這些查詢是如何處理的呢,這一講就講這個問題。我們首先創建一個Article 這個表,并初始化數據.
    程序代碼
    Drop TABLE IF EXISTS `article`;
    Create TABLE `article` (
    ? `id` int(11) NOT NULL auto_increment,
    ? `userid` int(11) NOT NULL,
    ? `title` varchar(100) NOT NULL,
    ? `content` text NOT NULL,
    ? PRIMARY KEY? (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

    -- ----------------------------
    -- 添加幾條測試數據
    -- ----------------------------
    Insert INTO `article` VALUES ('1', '1', 'test_title', 'test_content');
    Insert INTO `article` VALUES ('2', '1', 'test_title_2', 'test_content_2');
    Insert INTO `article` VALUES ('3', '1', 'test_title_3', 'test_content_3');
    Insert INTO `article` VALUES ('4', '1', 'test_title_4', 'test_content_4');

    你應該發現了,這幾個文章對應的userid都是1,所以需要用戶表user里面有id=1的數據。可以修改成滿足自己條件的數據.按照orm的規則,表已經創建了,那么肯定需要一個對象與之對應,所以我們增加一個 Article 的class
    程序代碼
    package com.yihaomen.mybatis.model;

    public class Article {
    ???
    ??? private int id;
    ??? private User user;
    ??? private String title;
    ??? private String content;
    ???
    ??? public int getId() {
    ??????? return id;
    ??? }
    ??? public void setId(int id) {
    ??????? this.id = id;
    ??? }
    ???
    ??? public User getUser() {
    ??????? return user;
    ??? }
    ??? public void setUser(User user) {
    ??????? this.user = user;
    ??? }
    ??? public String getTitle() {
    ??????? return title;
    ??? }
    ??? public void setTitle(String title) {
    ??????? this.title = title;
    ??? }
    ??? public String getContent() {
    ??????? return content;
    ??? }
    ??? public void setContent(String content) {
    ??????? this.content = content;
    ??? }

    }


    注意一下,文章的用戶是怎么定義的,是直接定義的一個User對象。而不是int類型。

    多對一的實現
    場景:在讀取某個用戶發表的所有文章。當然還是需要在User.xml 里面配置 select 語句, 但重點是這個 select 的resultMap 對應什么樣的數據呢。這是重點,這里要引入 association 看定義如下:
    程序代碼
    < !-- User 聯合文章進行查詢 方法之一的配置 (多對一的方式)? -->???
    ??? <resultMap id="resultUserArticleList" type="Article">
    ??????? <id property="id" column="aid" />
    ??????? <result property="title" column="title" />
    ??????? <result property="content" column="content" />
    ???????
    ??????? <association property="user" javaType="User">
    ??????????? <id property="id" column="id" />
    ??????????? <result property="userName" column="userName" />
    ??????????? <result property="userAddress" column="userAddress" />???????????
    ??????? </association>???????
    ??? </resultMap>

    < select id="getUserArticles" parameterType="int" resultMap="resultUserArticleList">
    ?????? select user.id,user.userName,user.userAddress,article.id aid,article.title,article.content from user,article
    ????????????? where user.id=article.userid and user.id=#{id}
    ??? </select>

    這樣配置之后,就可以了,將select 語句與resultMap 對應的映射結合起來看,就明白了。用association 來得到關聯的用戶,這是多對一的情況,因為所有的文章都是同一個用戶的。

    還有另外一種處理方式,可以復用我們前面已經定義好的 resultMap ,前面我們定義過一個 resultListUser ,看這第二種方法如何實現:
    程序代碼
    <resultMap type="User" id="resultListUser">
    ??????? <id column="id" property="id" />
    ??????? <result column="userName" property="userName" />
    ??????? <result column="userAge" property="userAge" />
    ??????? <result column="userAddress" property="userAddress" />
    ??? </resultMap>

    ??? <!-- User 聯合文章進行查詢 方法之二的配置 (多對一的方式) -->???
    ??? <resultMap id="resultUserArticleList-2" type="Article">
    ??????? <id property="id" column="aid" />
    ??????? <result property="title" column="title" />
    ??????? <result property="content" column="content" />???????
    ??????? <association property="user" javaType="User" resultMap="resultListUser" />????????????
    ??? </resultMap>
    ???
    ??? <select id="getUserArticles" parameterType="int" resultMap="resultUserArticleList">
    ?????? select user.id,user.userName,user.userAddress,article.id aid,article.title,article.content from user,article
    ????????????? where user.id=article.userid and user.id=#{id}
    ??? </select>

    將 association? 中對應的映射獨立抽取出來,可以達到復用的目的。

    好了,現在在Test 類中寫測試代碼:
    程序代碼
    public void getUserArticles(int userid){
    ??????? SqlSession session = sqlSessionFactory.openSession();
    ??????? try {
    ??????????? IUserOperation userOperation=session.getMapper(IUserOperation.class);??????????
    ??????????? List<Article> articles = userOperation.getUserArticles(userid);
    ??????????? for(Article article:articles){
    ??????????????? System.out.println(article.getTitle()+":"+article.getContent()+
    ??????????????????????? ":作者是:"+article.getUser().getUserName()+":地址:"+
    ???????????????????????? article.getUser().getUserAddress());
    ??????????? }
    ??????? } finally {
    ??????????? session.close();
    ??????? }
    ??? }


    漏掉了一點,我們一定要在 IUserOperation 接口中,加入 select 對應的id 名稱相同的方法:
    public List<Article> getUserArticles(int id);

    然后運行就可以測試。

    整個程序下載:
    點擊下載此文件



    除非申明,文章均為一號門原創,轉載請注明本文地址,謝謝!

    mybatis實戰教程(mybatis in action)之五:與spring3集成(附源碼)


    在這一系列文章中,前面講到純粹用mybatis 連接數據庫,然后 進行增刪改查,以及多表聯合查詢的的例子,但實際項目中,通常會用 spring 這個沾合劑來管理 datasource 等。充分利用spring 基于接口的編程,以及aop ,ioc 帶來的方便。用spring 來管理 mybatis 與管理hibernate 有很多類似的地方。今天的重點就是數據源管理以及 bean的配置。

    你可以下載源碼后,對比著看,源代碼沒有帶jar包,太大了,空間有限. 有截圖,你可以看到用到哪些jar包,源碼在本文最后.

    1. 首先對前面的工程結構做一點改變,在src_user源代碼目錄下建立文件夾config ,并將原來的 mybatis 配置文件 Configuration.xml 移動到這個文件夾中, 并在config 文家夾中建立 spring 配置文件:applicationContext.xml ,這個配置文件里最主要的配置:
    程序代碼
    < !--本示例采用DBCP連接池,應預先把DBCP的jar包復制到工程的lib目錄下。 -->

    ? <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
    ???? <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    ???? <property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis?characterEncoding=utf8"/>
    ???? <property name="username" value="root"/>
    ???? <property name="password" value="password"/>
    ? </bean>

    ? <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    ???? <!--dataSource屬性指定要用到的連接池-->
    ???? <property name="dataSource" ref="dataSource"/>
    ???? <!--configLocation屬性指定mybatis的核心配置文件-->
    ???? <property name="configLocation" value="config/Configuration.xml"/>
    ? </bean>

    ? <bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
    ???? <!--sqlSessionFactory屬性指定要用到的SqlSessionFactory實例-->
    ???? <property name="sqlSessionFactory" ref="sqlSessionFactory" />
    ???? <!--mapperInterface屬性指定映射器接口,用于實現此接口并生成映射器對象-->
    ???? <property name="mapperInterface" value="com.yihaomen.mybatis.inter.IUserOperation" />
    ? </bean>


    [b]這里面的重點就是 org.mybatis.spring.SqlSessionFactoryBean 與 org.mybatis.spring.mapper.MapperFactoryBean[b] 實現了 spring? 的接口,并產生對象。詳細可以查看 mybatis-spring 代碼。(http://code.google.com/p/mybatis/),如果僅僅使用,固定模式,這樣配置就好。

    然后寫測試程序
    程序代碼
    package com.yihaomen.test;

    import java.util.List;

    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;

    import com.yihaomen.mybatis.inter.IUserOperation;
    import com.yihaomen.mybatis.model.Article;
    import com.yihaomen.mybatis.model.User;


    public class MybatisSprintTest {
    ???
    ??? private static ApplicationContext ctx;?
    ???
    ??? static
    ??? {?
    ??????? ctx = new ClassPathXmlApplicationContext("config/applicationContext.xml");?
    ??? }???????
    ?????
    ??? public static void main(String[] args)?
    ??? {?
    ??????? IUserOperation mapper = (IUserOperation)ctx.getBean("userMapper");
    ??????? //測試id=1的用戶查詢,根據數據庫中的情況,可以改成你自己的.
    ??????? System.out.println("得到用戶id=1的用戶信息");
    ??????? User user = mapper.selectUserByID(1);
    ??????? System.out.println(user.getUserAddress());
    ???????
    ??????? //得到文章列表測試
    ??????? System.out.println("得到用戶id為1的所有文章列表");
    ??????? List<Article> articles = mapper.getUserArticles(1);
    ???????
    ??????? for(Article article:articles){
    ??????????? System.out.println(article.getContent()+"--"+article.getTitle());
    ??????? }
    ???????
    ??? }?

    ???
    }



    運行即可得到相應的結果.
    工程圖:

    用到的jar包,如下圖:


    源代碼下載,不帶 jar? 包,
    點擊下載此文件



    除非申明,文章均為一號門原創,轉載請注明本文地址,謝謝!

    mybatis實戰教程(mybatis in action)之六:與Spring MVC 的集成


    前面幾篇文章已經講到了mybatis與spring 的集成。但這個時候,所有的工程還不是web工程,雖然我一直是創建的web 工程。今天將直接用mybatis與Spring mvc 的方式集成起來,源碼在本文結尾處下載.主要有以下幾個方面的配置
    1. web.xml 配置 spring dispatchservlet ,比如為:mvc-dispatcher
    2. mvc-dispatcher-servlet.xml 文件配置
    3. spring applicationContext.XML文件配置(與數據庫相關,與mybatis sqlSessionFaction 整合,掃描所有mybatis mapper 文件等.)
    4. 編寫controller 類
    5. 編寫頁面代碼.
    先有個大概映像,整個工程圖如下:
    [/code]

    1. web.xml 配置 spring dispatchservlet ,比如為:mvc-dispatcher
    程序代碼
    <context-param>
    ??? <param-name>contextConfigLocation</param-name>
    ??? <param-value>classpath*:config/applicationContext.xml</param-value>
    ? </context-param>
    ? <listener>
    ??? <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    ? </listener>
    ? <listener>
    ??? <listener-class>
    ??????????? org.springframework.web.context.ContextCleanupListener</listener-class>
    ? </listener>
    ? <servlet>
    ??? <servlet-name>mvc-dispatcher</servlet-name>
    ??? <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    ??? <load-on-startup>1</load-on-startup>
    ? </servlet>
    ? <servlet-mapping>
    ??? <servlet-name>mvc-dispatcher</servlet-name>
    ??? <url-pattern>/</url-pattern>
    ? </servlet-mapping>

    2. 在web.xml 同目錄下配置 mvc-dispatcher-servlet.xml 文件,這個文件名前面部分必須與你在web.xml里面配置的DispatcherServlet 的servlet名字對應.其內容為:
    程序代碼
    <beans xmlns="http://www.springframework.org/schema/beans"
    ??? xmlns:context="http://www.springframework.org/schema/context"
    ??? xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    ??? xsi:schemaLocation="
    ??????? http://www.springframework.org/schema/beans????
    ??????? http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    ??????? http://www.springframework.org/schema/context
    ??????? http://www.springframework.org/schema/context/spring-context-3.0.xsd
    ??????? http://www.springframework.org/schema/mvc
    ??????? http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">

    ??? <context:component-scan base-package="com.yihaomen.controller" />
    ??? <mvc:annotation-driven />
    ???
    ??? <mvc:resources mapping="/static/**" location="/WEB-INF/static/"/>?
    ??? <mvc:default-servlet-handler/>?
    ????
    ??? <bean
    ??????? class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    ??????? <property name="prefix">
    ??????????? <value>/WEB-INF/pages/</value>
    ??????? </property>
    ??????? <property name="suffix">
    ??????????? <value>.jsp</value>
    ??????? </property>
    ??? </bean>

    < /beans>

    3. 在源碼目錄 config 目錄下配置 spring 配置文件 applicationContext.xml
    程序代碼
    < !--本示例采用DBCP連接池,應預先把DBCP的jar包復制到工程的lib目錄下。 -->??
    ??? <context:property-placeholder??? location="classpath:/config/database.properties" />
    ???????
    ??? <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
    ??????? destroy-method="close" p:driverClassName="com.mysql.jdbc.Driver"
    ??????? p:url="jdbc:mysql://127.0.0.1:3306/mybatis?characterEncoding=utf8"
    ??????? p:username="root" p:password="password"
    ??????? p:maxActive="10" p:maxIdle="10">
    ??? </bean>
    ???
    ??? <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    ????? <property name="dataSource" ref="dataSource" />
    ??? </bean>
    ???
    ????
    ? <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    ???? <!--dataSource屬性指定要用到的連接池-->
    ???? <property name="dataSource" ref="dataSource"/>
    ???? <!--configLocation屬性指定mybatis的核心配置文件-->
    ???? <property name="configLocation" value="classpath:config/Configuration.xml" />
    ???? <!-- 所有配置的mapper文件 -->
    ???? <property name="mapperLocations" value="classpath*:com/yihaomen/mapper/*.xml" />
    ? </bean>
    ?
    ? <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    ???? <property name="basePackage" value="com.yihaomen.inter" />????
    ? </bean>


    不知道為什么,一旦我用了 MapperScannerConfigurer 去掃描所有的mapper 接口時,數據庫配置datasource 就不能用讀取database.properties文件了。報錯: Cannot load JDBC driver class '${jdbc.driverClassName}',網上有人說在spring 3.1.1 下用 sqlSessionFactionBean 注入可以解決,但我用 spring 3.1.3 還是有問題,所以只好把數據庫連接信息直接配置在了XML 文件里面。

    4. 編寫 controller 層
    程序代碼
    package com.yihaomen.controller;
    import java.util.List;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.servlet.ModelAndView;
    import com.yihaomen.inter.IUserOperation;
    import com.yihaomen.model.Article;

    @Controller
    @RequestMapping("/article")
    public class UserController {
    ??? @Autowired
    ??? IUserOperation userMapper;

    ??? @RequestMapping("/list")
    ??? public ModelAndView listall(HttpServletRequest request,HttpServletResponse response){
    ??????? List<Article> articles=userMapper.getUserArticles(1);
    ??????? ModelAndView mav=new ModelAndView("list");
    ??????? mav.addObject("articles",articles);
    ??????? return mav;
    ??? }
    }

    5. 頁面文件:
    [code]
    < c:forEach items="${articles}" var="item">?
    ??????? ${item.id }--${item.title }--${item.content }<br />
    ??? </c:forEach>


    運行結果:


    當然還有 mybatis 的Configure.xml? 配置文件,與上一講的差不多,唯一不同的就是不用再配置類似如下的:?? <mapper resource="com/yihaomen/mapper/User.xml"/> ,所有這些都交給 在配置 sqlSessionFactory 的時候,由? <property name="mapperLocations" value="classpath*:com/yihaomen/mapper/*.xml" /> 去導入了。
    ???
    源碼下載:

    mybatis spring3 MVC 程序下載

    數據庫下載:

    spring mvc 數據庫測試文件



    除非申明,文章均為一號門原創,轉載請注明本文地址,謝謝!

    mybatis實戰教程(mybatis in action)之七:實現mybatis分頁(源碼下載)


    上一篇文章里已經講到了mybatis與spring MVC的集成,并且做了一個列表展示,顯示出所有article 列表,但沒有用到分頁,在實際的項目中,分頁是肯定需要的。而且是物理分頁,不是內存分頁。對于物理分頁方案,不同的數據庫,有不同的實現方法,對于mysql 來說 就是利用 limit offset,pagesize 方式來實現的。oracle 是通過rownum 來實現的,如果你熟悉相關數據庫的操作,是一樣的很好擴展,本文以mysql 為例子來講述.先看一下效果圖(源代碼在文章最后提供下載):

    實現mybatis 物理分頁,一個最簡單的方式是,是在你的mapper的SQL語句中直接寫類似如下方式 :
    程序代碼
    <select id="getUserArticles" parameterType="Your_params" resultMap="resultUserArticleList">
    ?????? select user.id,user.userName,user.userAddress,article.id aid,article.title,article.content from user,article
    ????????????? where user.id=article.userid and user.id=#{id} limit #{offset},#{pagesize}
    ??? </select>

    請注意這里的 parameterType 是你傳入的參數類,或者map ,里面包含了offset,pagesize ,和其他你需要的參數,用這種方式,肯定可以實現分頁。這是簡單的一種方式。但更通用的一種方式是用 mybatis 插件的方式. 參考了網上的很多資料 ,mybatis plugin 方面的資料。寫自己的插件.

    程序代碼
    package com.yihaomen.util;

    import java.lang.reflect.Field;
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.util.List;
    import java.util.Map;
    import java.util.Properties;

    import javax.xml.bind.PropertyException;

    import org.apache.ibatis.builder.xml.dynamic.ForEachSqlNode;
    import org.apache.ibatis.executor.ErrorContext;
    import org.apache.ibatis.executor.Executor;
    import org.apache.ibatis.executor.ExecutorException;
    import org.apache.ibatis.executor.statement.BaseStatementHandler;
    import org.apache.ibatis.executor.statement.RoutingStatementHandler;
    import org.apache.ibatis.executor.statement.StatementHandler;
    import org.apache.ibatis.mapping.BoundSql;
    import org.apache.ibatis.mapping.MappedStatement;
    import org.apache.ibatis.mapping.ParameterMapping;
    import org.apache.ibatis.mapping.ParameterMode;
    import org.apache.ibatis.plugin.Interceptor;
    import org.apache.ibatis.plugin.Intercepts;
    import org.apache.ibatis.plugin.Invocation;
    import org.apache.ibatis.plugin.Plugin;
    import org.apache.ibatis.plugin.Signature;
    import org.apache.ibatis.reflection.MetaObject;
    import org.apache.ibatis.reflection.property.PropertyTokenizer;
    import org.apache.ibatis.session.Configuration;
    import org.apache.ibatis.session.ResultHandler;
    import org.apache.ibatis.session.RowBounds;
    import org.apache.ibatis.type.TypeHandler;
    import org.apache.ibatis.type.TypeHandlerRegistry;

    @Intercepts({ @Signature(type = StatementHandler.class, method = "prepare", args = { Connection.class }) })
    public class PagePlugin implements Interceptor {

    ??? private static String dialect = "";
    ??? private static String pageSqlId = "";

    ??? @SuppressWarnings("unchecked")
    ??? public Object intercept(Invocation ivk) throws Throwable {

    ??????? if (ivk.getTarget() instanceof RoutingStatementHandler) {
    ??????????? RoutingStatementHandler statementHandler = (RoutingStatementHandler) ivk
    ??????????????????? .getTarget();
    ??????????? BaseStatementHandler delegate = (BaseStatementHandler) ReflectHelper
    ??????????????????? .getValueByFieldName(statementHandler, "delegate");
    ??????????? MappedStatement mappedStatement = (MappedStatement) ReflectHelper
    ??????????????????? .getValueByFieldName(delegate, "mappedStatement");

    ??????????? if (mappedStatement.getId().matches(pageSqlId)) {
    ??????????????? BoundSql boundSql = delegate.getBoundSql();
    ??????????????? Object parameterObject = boundSql.getParameterObject();
    ??????????????? if (parameterObject == null) {
    ??????????????????? throw new NullPointerException("parameterObject error");
    ??????????????? } else {
    ??????????????????? Connection connection = (Connection) ivk.getArgs()[0];
    ??????????????????? String sql = boundSql.getSql();
    ??????????????????? String countSql = "select count(0) from (" + sql + ") myCount";
    ??????????????????? System.out.println("總數sql 語句:"+countSql);
    ??????????????????? PreparedStatement countStmt = connection
    ??????????????????????????? .prepareStatement(countSql);
    ??????????????????? BoundSql countBS = new BoundSql(
    ??????????????????????????? mappedStatement.getConfiguration(), countSql,
    ??????????????????????????? boundSql.getParameterMappings(), parameterObject);
    ??????????????????? setParameters(countStmt, mappedStatement, countBS,
    ??????????????????????????? parameterObject);
    ??????????????????? ResultSet rs = countStmt.executeQuery();
    ??????????????????? int count = 0;
    ??????????????????? if (rs.next()) {
    ??????????????????????? count = rs.getInt(1);
    ??????????????????? }
    ??????????????????? rs.close();
    ??????????????????? countStmt.close();

    ??????????????????? PageInfo page = null;
    ??????????????????? if (parameterObject instanceof PageInfo) {
    ??????????????????????? page = (PageInfo) parameterObject;
    ??????????????????????? page.setTotalResult(count);
    ??????????????????? } else if(parameterObject instanceof Map){
    ??????????????????????? Map<String, Object> map = (Map<String, Object>)parameterObject;
    ??????????????????????? page = (PageInfo)map.get("page");
    ??????????????????????? if(page == null)
    ??????????????????????????? page = new PageInfo();
    ??????????????????????? page.setTotalResult(count);
    ??????????????????? }else {
    ??????????????????????? Field pageField = ReflectHelper.getFieldByFieldName(
    ??????????????????????????????? parameterObject, "page");
    ??????????????????????? if (pageField != null) {
    ??????????????????????????? page = (PageInfo) ReflectHelper.getValueByFieldName(
    ??????????????????????????????????? parameterObject, "page");
    ??????????????????????????? if (page == null)
    ??????????????????????????????? page = new PageInfo();
    ??????????????????????????? page.setTotalResult(count);
    ??????????????????????????? ReflectHelper.setValueByFieldName(parameterObject,
    ??????????????????????????????????? "page", page);
    ??????????????????????? } else {
    ??????????????????????????? throw new NoSuchFieldException(parameterObject
    ??????????????????????????????????? .getClass().getName());
    ??????????????????????? }
    ??????????????????? }
    ??????????????????? String pageSql = generatePageSql(sql, page);
    ??????????????????? System.out.println("page sql:"+pageSql);
    ??????????????????? ReflectHelper.setValueByFieldName(boundSql, "sql", pageSql);
    ??????????????? }
    ??????????? }
    ??????? }
    ??????? return ivk.proceed();
    ??? }

    ??? private void setParameters(PreparedStatement ps,
    ??????????? MappedStatement mappedStatement, BoundSql boundSql,
    ??????????? Object parameterObject) throws SQLException {
    ??????? ErrorContext.instance().activity("setting parameters")
    ??????????????? .object(mappedStatement.getParameterMap().getId());
    ??????? List<ParameterMapping> parameterMappings = boundSql
    ??????????????? .getParameterMappings();
    ??????? if (parameterMappings != null) {
    ??????????? Configuration configuration = mappedStatement.getConfiguration();
    ??????????? TypeHandlerRegistry typeHandlerRegistry = configuration
    ??????????????????? .getTypeHandlerRegistry();
    ??????????? MetaObject metaObject = parameterObject == null ? null
    ??????????????????? : configuration.newMetaObject(parameterObject);
    ??????????? for (int i = 0; i < parameterMappings.size(); i++) {
    ??????????????? ParameterMapping parameterMapping = parameterMappings.get(i);
    ??????????????? if (parameterMapping.getMode() != ParameterMode.OUT) {
    ??????????????????? Object value;
    ??????????????????? String propertyName = parameterMapping.getProperty();
    ??????????????????? PropertyTokenizer prop = new PropertyTokenizer(propertyName);
    ??????????????????? if (parameterObject == null) {
    ??????????????????????? value = null;
    ??????????????????? } else if (typeHandlerRegistry
    ??????????????????????????? .hasTypeHandler(parameterObject.getClass())) {
    ??????????????????????? value = parameterObject;
    ??????????????????? } else if (boundSql.hasAdditionalParameter(propertyName)) {
    ??????????????????????? value = boundSql.getAdditionalParameter(propertyName);
    ??????????????????? } else if (propertyName
    ??????????????????????????? .startsWith(ForEachSqlNode.ITEM_PREFIX)
    ??????????????????????????? && boundSql.hasAdditionalParameter(prop.getName())) {
    ??????????????????????? value = boundSql.getAdditionalParameter(prop.getName());
    ??????????????????????? if (value != null) {
    ??????????????????????????? value = configuration.newMetaObject(value)
    ??????????????????????????????????? .getValue(
    ??????????????????????????????????????????? propertyName.substring(prop
    ??????????????????????????????????????????????????? .getName().length()));
    ??????????????????????? }
    ??????????????????? } else {
    ??????????????????????? value = metaObject == null ? null : metaObject
    ??????????????????????????????? .getValue(propertyName);
    ??????????????????? }
    ??????????????????? TypeHandler typeHandler = parameterMapping.getTypeHandler();
    ??????????????????? if (typeHandler == null) {
    ??????????????????????? throw new ExecutorException(
    ??????????????????????????????? "There was no TypeHandler found for parameter "
    ??????????????????????????????????????? + propertyName + " of statement "
    ??????????????????????????????????????? + mappedStatement.getId());
    ??????????????????? }
    ??????????????????? typeHandler.setParameter(ps, i + 1, value,
    ??????????????????????????? parameterMapping.getJdbcType());
    ??????????????? }
    ??????????? }
    ??????? }
    ??? }


    ??? private String generatePageSql(String sql, PageInfo page) {
    ??????? if (page != null && (dialect !=null || !dialect.equals(""))) {
    ??????????? StringBuffer pageSql = new StringBuffer();
    ??????????? if ("mysql".equals(dialect)) {
    ??????????????? pageSql.append(sql);
    ??????????????? pageSql.append(" limit " + page.getCurrentResult() + ","
    ??????????????????????? + page.getShowCount());
    ??????????? } else if ("oracle".equals(dialect)) {
    ??????????????? pageSql.append("select * from (select tmp_tb.*,ROWNUM row_id from (");
    ??????????????? pageSql.append(sql);
    ??????????????? pageSql.append(")? tmp_tb where ROWNUM<=");
    ??????????????? pageSql.append(page.getCurrentResult() + page.getShowCount());
    ??????????????? pageSql.append(") where row_id>");
    ??????????????? pageSql.append(page.getCurrentResult());
    ??????????? }
    ??????????? return pageSql.toString();
    ??????? } else {
    ??????????? return sql;
    ??????? }
    ??? }

    ??? public Object plugin(Object arg0) {
    ??????? // TODO Auto-generated method stub
    ??????? return Plugin.wrap(arg0, this);
    ??? }

    ??? public void setProperties(Properties p) {
    ??????? dialect = p.getProperty("dialect");
    ??????? if (dialect ==null || dialect.equals("")) {
    ??????????? try {
    ??????????????? throw new PropertyException("dialect property is not found!");
    ??????????? } catch (PropertyException e) {
    ??????????????? // TODO Auto-generated catch block
    ??????????????? e.printStackTrace();
    ??????????? }
    ??????? }
    ??????? pageSqlId = p.getProperty("pageSqlId");
    ??????? if (dialect ==null || dialect.equals("")) {
    ??????????? try {
    ??????????????? throw new PropertyException("pageSqlId property is not found!");
    ??????????? } catch (PropertyException e) {
    ??????????????? // TODO Auto-generated catch block
    ??????????????? e.printStackTrace();
    ??????????? }
    ??????? }
    ??? }

    }

    此插件有兩個輔助類:PageInfo,ReflectHelper,你可以下載源代碼參考。
    寫了插件之后,當然需要在 mybatis 的配置文件Configuration.xml 里配置這個插件
    程序代碼
    ??? <plugins>
    ??????? <plugin interceptor="com.yihaomen.util.PagePlugin">
    ??????????? <property name="dialect" value="mysql" />
    ??????????? <property name="pageSqlId" value=".*ListPage.*" />
    ??????? </plugin>
    ??? </plugins>


    請注意,這個插件定義了一個規則,也就是在mapper中sql語句的id 必須包含ListPage才能被攔截。否則將不會分頁處理.

    插件寫好了,現在就可以在 spring mvc 中的controller 層中寫一個方法來測試這個分頁:
    程序代碼
    @RequestMapping("/pagelist")
    ??? public ModelAndView pageList(HttpServletRequest request,HttpServletResponse response){
    ??????? int currentPage = request.getParameter("page")==null?1:Integer.parseInt(request.getParameter("page"));
    ??????? int pageSize = 3;
    ??????? if (currentPage<=0){
    ??????????? currentPage =1;
    ??????? }
    ??????? int currentResult = (currentPage-1) * pageSize;
    ???????
    ??????? System.out.println(request.getRequestURI());
    ??????? System.out.println(request.getQueryString());
    ???????
    ??????? PageInfo page = new PageInfo();
    ??????? page.setShowCount(pageSize);
    ??????? page.setCurrentResult(currentResult);
    ??????? List<Article> articles=iUserOperation.selectArticleListPage(page,1);
    ???????
    ??????? System.out.println(page);
    ???????
    ??????? int totalCount = page.getTotalResult();
    ???????
    ??????? int lastPage=0;
    ??????? if (totalCount % pageSize==0){
    ??????????? lastPage = totalCount % pageSize;
    ??????? }
    ??????? else{
    ??????????? lastPage =1+ totalCount / pageSize;
    ??????? }
    ???????
    ??????? if (currentPage>=lastPage){
    ??????????? currentPage =lastPage;
    ??????? }
    ???????
    ??????? String pageStr = "";

    ??????? pageStr=String.format("<a href=\"%s\">上一頁</a>??? <a href=\"%s\">下一頁</a>",
    ??????????????????????? request.getRequestURI()+"?page="+(currentPage-1),request.getRequestURI()+"?page="+(currentPage+1) );


    ??????? //制定視圖,也就是list.jsp
    ??????? ModelAndView mav=new ModelAndView("list");
    ??????? mav.addObject("articles",articles);
    ??????? mav.addObject("pageStr",pageStr);
    ??????? return mav;
    ??? }


    然后運行程序,進入分頁頁面,你就可以看到結果了:


    源代碼下載:
    點擊下載此文件
    相關jar 包下載,請到下載這里例子中的jar
    http://www.yihaomen.com/article/java/318.htm (文章最后有源代碼下載,里面有jar 包,拷貝到上面源代碼里面所需要的lib 目錄下.)

    另外,你還得在前面提到的數據庫artilce表里面,多插入一些記錄,分頁效果就更好。


    除非申明,文章均為一號門原創,轉載請注明本文地址,謝謝!

    mybatis實戰教程(mybatis in action)之八:mybatis 動態sql語句


    mybatis 的動態sql語句是基于OGNL表達式的。可以方便的在 sql 語句中實現某些邏輯. 總體說來mybatis 動態SQL 語句主要有以下幾類:
    1. if 語句 (簡單的條件判斷)
    2. choose (when,otherwize) ,相當于java 語言中的 switch ,與 jstl 中的choose 很類似.
    3. trim (對包含的內容加上 prefix,或者 suffix 等,前綴,后綴)
    4. where (主要是用來簡化sql語句中where條件判斷的,能智能的處理 and or ,不必擔心多余導致語法錯誤)
    5. set (主要用于更新時)
    6. foreach (在實現 mybatis in 語句查詢時特別有用)
    下面分別介紹這幾種處理方式

    1. mybaits if 語句處理
    程序代碼
    ??? <select id="dynamicIfTest" parameterType="Blog" resultType="Blog">
    ??????? select * from t_blog where 1 = 1
    ??????? <if test="title != null">
    ??????????? and title = #{title}
    ??????? </if>
    ??????? <if test="content != null">
    ??????????? and content = #{content}
    ??????? </if>
    ??????? <if test="owner != null">
    ??????????? and owner = #{owner}
    ??????? </if>
    ??? </select>

    這條語句的意思非常簡單,如果你提供了title參數,那么就要滿足title=#{title},同樣如果你提供了Content和Owner的時候,它們也需要滿足相應的條件,之后就是返回滿足這些條件的所有Blog,這是非常有用的一個功能,以往我們使用其他類型框架或者直接使用JDBC的時候, 如果我們要達到同樣的選擇效果的時候,我們就需要拼SQL語句,這是極其麻煩的,比起來,上述的動態SQL就要簡單多了

    2.2. choose (when,otherwize) ,相當于java 語言中的 switch ,與 jstl 中的choose 很類似
    程序代碼
    ??? <select id="dynamicChooseTest" parameterType="Blog" resultType="Blog">
    ??????? select * from t_blog where 1 = 1
    ??????? <choose>
    ??????????? <when test="title != null">
    ??????????????? and title = #{title}
    ??????????? </when>
    ??????????? <when test="content != null">
    ??????????????? and content = #{content}
    ??????????? </when>
    ??????????? <otherwise>
    ??????????????? and owner = "owner1"
    ??????????? </otherwise>
    ??????? </choose>
    ??? </select>

    when元素表示當when中的條件滿足的時候就輸出其中的內容,跟JAVA中的switch效果差不多的是按照條件的順序,當when中有條件滿足的時候,就會跳出choose,即所有的when和otherwise條件中,只有一個會輸出,當所有的我很條件都不滿足的時候就輸出otherwise中的內容。所以上述語句的意思非常簡單, 當title!=null的時候就輸出and titlte = #{title},不再往下判斷條件,當title為空且content!=null的時候就輸出and content = #{content},當所有條件都不滿足的時候就輸出otherwise中的內容。

    3.trim (對包含的內容加上 prefix,或者 suffix 等,前綴,后綴)
    程序代碼
    ??? <select id="dynamicTrimTest" parameterType="Blog" resultType="Blog">
    ??????? select * from t_blog
    ??????? <trim prefix="where" prefixOverrides="and |or">
    ??????????? <if test="title != null">
    ??????????????? title = #{title}
    ??????????? </if>
    ??????????? <if test="content != null">
    ??????????????? and content = #{content}
    ??????????? </if>
    ??????????? <if test="owner != null">
    ??????????????? or owner = #{owner}
    ??????????? </if>
    ??????? </trim>
    ??? </select>

    trim元素的主要功能是可以在自己包含的內容前加上某些前綴,也可以在其后加上某些后綴,與之對應的屬性是prefix和suffix;可以把包含內容的首部某些內容覆蓋,即忽略,也可以把尾部的某些內容覆蓋,對應的屬性是prefixOverrides和suffixOverrides;正因為trim有這樣的功能,所以我們也可以非常簡單的利用trim來代替where元素的功能

    4. where (主要是用來簡化sql語句中where條件判斷的,能智能的處理 and or 條件
    程序代碼
    ??? <select id="dynamicWhereTest" parameterType="Blog" resultType="Blog">
    ??????? select * from t_blog
    ??????? <where>
    ??????????? <if test="title != null">
    ??????????????? title = #{title}
    ??????????? </if>
    ??????????? <if test="content != null">
    ??????????????? and content = #{content}
    ??????????? </if>
    ??????????? <if test="owner != null">
    ??????????????? and owner = #{owner}
    ??????????? </if>
    ??????? </where>
    ??? </select>


    where元素的作用是會在寫入where元素的地方輸出一個where,另外一個好處是你不需要考慮where元素里面的條件輸出是什么樣子的,MyBatis會智能的幫你處理,如果所有的條件都不滿足那么MyBatis就會查出所有的記錄,如果輸出后是and 開頭的,MyBatis會把第一個and忽略,當然如果是or開頭的,MyBatis也會把它忽略;此外,在where元素中你不需要考慮空格的問題,MyBatis會智能的幫你加上。像上述例子中,如果title=null, 而content != null,那么輸出的整個語句會是select * from t_blog where content = #{content},而不是select * from t_blog where and content = #{content},因為MyBatis會智能的把首個and 或 or 給忽略。

    5.set (主要用于更新時)
    程序代碼
    ??? <update id="dynamicSetTest" parameterType="Blog">
    ??????? update t_blog
    ??????? <set>
    ??????????? <if test="title != null">
    ??????????????? title = #{title},
    ??????????? </if>
    ??????????? <if test="content != null">
    ??????????????? content = #{content},
    ??????????? </if>
    ??????????? <if test="owner != null">
    ??????????????? owner = #{owner}
    ??????????? </if>
    ??????? </set>
    ??????? where id = #{id}
    ??? </update>

    set元素主要是用在更新操作的時候,它的主要功能和where元素其實是差不多的,主要是在包含的語句前輸出一個set,然后如果包含的語句是以逗號結束的話將會把該逗號忽略,如果set包含的內容為空的話則會出錯。有了set元素我們就可以動態的更新那些修改了的字段

    6. foreach (在實現 mybatis in 語句查詢時特別有用)
    foreach的主要用在構建in條件中,它可以在SQL語句中進行迭代一個集合。foreach元素的屬性主要有item,index,collection,open,separator,close。item表示集合中每一個元素進行迭代時的別名,index指定一個名字,用于表示在迭代過程中,每次迭代到的位置,open表示該語句以什么開始,separator表示在每次進行迭代之間以什么符號作為分隔符,close表示以什么結束,在使用foreach的時候最關鍵的也是最容易出錯的就是collection屬性,該屬性是必須指定的,但是在不同情況下,該屬性的值是不一樣的,主要有一下3種情況:
    如果傳入的是單參數且參數類型是一個List的時候,collection屬性值為list
    如果傳入的是單參數且參數類型是一個array數組的時候,collection的屬性值為array
    如果傳入的參數是多個的時候,我們就需要把它們封裝成一個Map了,當然單參數也可以封裝成map,實際上如果你在傳入參數的時候,在MyBatis里面也是會把它封裝成一個Map的,map的key就是參數名,所以這個時候collection屬性值就是傳入的List或array對象在自己封裝的map里面的key

    1.1.單參數List的類型
    程序代碼
    ??? <select id="dynamicForeachTest" resultType="Blog">
    ??????? select * from t_blog where id in
    ??????? <foreach collection="list" index="index" item="item" open="(" separator="," close=")">
    ??????????? #{item}
    ??????? </foreach>
    ??? </select>

    上述collection的值為list,對應的Mapper是這樣的
    程序代碼
    public List<Blog> dynamicForeachTest(List<Integer> ids);?


    測試代碼
    程序代碼
    ??? @Test
    ??? public void dynamicForeachTest() {
    ??????? SqlSession session = Util.getSqlSessionFactory().openSession();
    ??????? BlogMapper blogMapper = session.getMapper(BlogMapper.class);
    ??????? List<Integer> ids = new ArrayList<Integer>();
    ??????? ids.add(1);
    ??????? ids.add(3);
    ??????? ids.add(6);
    ??????? List<Blog> blogs = blogMapper.dynamicForeachTest(ids);
    ??????? for (Blog blog : blogs)
    ??????????? System.out.println(blog);
    ??????? session.close();
    ??? }


    2.數組類型的參數
    程序代碼
    ??? <select id="dynamicForeach2Test" resultType="Blog">
    ??????? select * from t_blog where id in
    ??????? <foreach collection="array" index="index" item="item" open="(" separator="," close=")">
    ??????????? #{item}
    ??????? </foreach>
    ??? </select>


    對應mapper
    程序代碼
    public List<Blog> dynamicForeach2Test(int[] ids);?


    3. Map 類型的參數
    程序代碼
    ??? <select id="dynamicForeach3Test" resultType="Blog">
    ??????? select * from t_blog where title like "%"#{title}"%" and id in
    ??????? <foreach collection="ids" index="index" item="item" open="(" separator="," close=")">
    ??????????? #{item}
    ??????? </foreach>
    ??? </select>


    mapper 應該是這樣的接口:
    程序代碼
    public List<Blog> dynamicForeach3Test(Map<String, Object> params);


    通過以上方法,就能完成一般的mybatis 的 動態SQL 語句.最常用的就是? if where foreach這幾個,一定要重點掌握.




    除非申明,文章均為一號門原創,轉載請注明本文地址,謝謝!

    mybatis實戰教程(mybatis in action)之九:mybatis 代碼生成工具的使用


    mybatis 應用程序,需要大量的配置文件,對于一個成百上千的數據庫表來說,完全手工配置,這是一個很恐怖的工作量. 所以mybatis 官方也推出了一個mybatis代碼生成工具的jar包. 今天花了一點時間,按照 mybatis generator 的doc 文檔參考,初步配置出了一個可以使用的版本,我把源代碼也提供下載,mybatis 代碼生成工具,主要有一下功能:
    1.生成pojo 與 數據庫結構對應
    2.如果有主鍵,能匹配主鍵
    3.如果沒有主鍵,可以用其他字段去匹配
    4.動態select,update,delete 方法
    5.自動生成接口(也就是以前的dao層)
    6.自動生成sql mapper,增刪改查各種語句配置,包括動態where語句配置
    7.生成Example 例子供參考

    下面介紹下詳細過程

    1. 創建測試工程,并配置mybatis代碼生成jar包
    下載地址:http://code.google.com/p/mybatis/downloads/list?can=3&q=Product%3DGenerator
    mysql 驅動下載:http://dev.mysql.com/downloads/connector/j/
    這些jar包,我也會包含在源代碼里面,可以在文章末尾處,下載源代碼,參考。

    用 eclipse 建立一個dynamic web project。
    解壓下載后的 mybatis-generator-core-1.3.2-bundle.zip 文件,其中有兩個目錄:一個目錄是文檔目錄docs,主要介紹這個代碼生成工具如何使用,另一個是lib目錄,里面的內容主要是jar 包,這里我們需要 mybatis-generator-core-1.3.2.jar,這個 jar 包. 將它拷貝到我們剛剛創建的 web工程的 WebContent/WEB-INF/lib? 目錄下.在這個目錄下也放入 mysql 驅動jar包.因為用 mysql? 做測試的.

    2.在數據庫中創建測試表
    在mybatis數據庫中創建 用來測試的category表(如果沒有mybatis這個數據庫,要創建,這是基于前面這個系列文章而寫的,已經有了mybatis 這個數據庫)
    程序代碼
    Drop TABLE IF EXISTS `category`;
    Create TABLE `category` (
    ? `id` int(11) NOT NULL AUTO_INCREMENT,
    ? `catname` varchar(50) NOT NULL,
    ? `catdescription` varchar(200) DEFAULT NULL,
    ? PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;


    3. 配置mybatis 代碼生成工具的配置文件?
    在創建的web工程中,創建相應的package 比如 :
    com.yihaomen.inter 用來存放mybatis 接口對象.
    com.yihaomen.mapper用來存放sql mapper對應的映射,sql語句等.
    com.yihaomen.model 用來存放與數據庫對應的model 。
    在用mybatis 代碼生成工具之前,這些目錄必須先創建好,作為一個好的應用程序,這些目錄的創建也是有規律的。

    根據mybatis代碼生成工具文檔,需要一個配置文件,這里命名為:mbgConfiguration.xml 放在src 目錄下. 配置文件內容如下:
    程序代碼
    < ?xml version="1.0" encoding="UTF-8"?>
    < !DOCTYPE generatorConfiguration
    ? PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
    ? "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">

    < generatorConfiguration>
    ?
    ? <!-- 配置mysql 驅動jar包路徑.用了絕對路徑 -->
    ? <classPathEntry location="D:\Work\Java\eclipse\workspace\myBatisGenerator\WebContent\WEB-INF\lib\mysql-connector-java-5.1.22-bin.jar" />

    ? <context id="yihaomen_mysql_tables" targetRuntime="MyBatis3">
    ?
    ??? <!-- 為了防止生成的代碼中有很多注釋,比較難看,加入下面的配置控制 -->
    ??? <commentGenerator>
    ????? <property name="suppressAllComments" value="true" />
    ????? <property name="suppressDate" value="true" />
    ??? </commentGenerator>
    ??? <!-- 注釋控制完畢 -->
    ?
    ??? <!-- 數據庫連接 -->
    ??? <jdbcConnection driverClass="com.mysql.jdbc.Driver"
    ??????? connectionURL="jdbc:mysql://127.0.0.1:3306/mybatis?characterEncoding=utf8"
    ??????? userId="root"
    ??????? password="password">
    ??? </jdbcConnection>

    ??? <javaTypeResolver >
    ????? <property name="forceBigDecimals" value="false" />
    ??? </javaTypeResolver>
    ???
    ??? <!-- 數據表對應的model 層? -->
    ??? <javaModelGenerator targetPackage="com.yihaomen.model" targetProject="src">
    ????? <property name="enableSubPackages" value="true" />
    ????? <property name="trimStrings" value="true" />
    ??? </javaModelGenerator>
    ???
    ??? <!-- sql mapper 隱射配置文件 -->
    ??? <sqlMapGenerator targetPackage="com.yihaomen.mapper"? targetProject="src">
    ????? <property name="enableSubPackages" value="true" />
    ??? </sqlMapGenerator>
    ???
    ??? <!-- 在ibatis2 中是dao層,但在mybatis3中,其實就是mapper接口 -->
    ??? <javaClientGenerator type="XMLMAPPER" targetPackage="com.yihaomen.inter"? targetProject="src">
    ????? <property name="enableSubPackages" value="true" />
    ??? </javaClientGenerator>
    ???
    ??? <!-- 要對那些數據表進行生成操作,必須要有一個. -->
    ??? <table schema="mybatis" tableName="category" domainObjectName="Category"
    ??????? enableCountByExample="false" enableUpdateByExample="false"
    ??????? enableDeleteByExample="false" enableSelectByExample="false"
    ??????? selectByExampleQueryId="false">????
    ??? </table>

    ? </context>
    < /generatorConfiguration>

    用一個main 方法來測試能否用mybatis 成生成剛剛創建的`category`表對應的model,sql mapper等內容.
    創建一個com.yihaomen.test 的package ,并在此package 下面建立一個測試的類GenMain:
    程序代碼
    package com.yihaomen.test;

    import java.io.File;
    import java.io.IOException;
    import java.sql.SQLException;
    import java.util.ArrayList;
    import java.util.List;

    import org.mybatis.generator.api.MyBatisGenerator;
    import org.mybatis.generator.config.Configuration;
    import org.mybatis.generator.config.xml.ConfigurationParser;
    import org.mybatis.generator.exception.InvalidConfigurationException;
    import org.mybatis.generator.exception.XMLParserException;
    import org.mybatis.generator.internal.DefaultShellCallback;

    public class GenMain {
    ??? public static void main(String[] args) {
    ??????? List<String> warnings = new ArrayList<String>();
    ??????? boolean overwrite = true;
    ??????? String genCfg = "/mbgConfiguration.xml";
    ??????? File configFile = new File(GenMain.class.getResource(genCfg).getFile());
    ??????? ConfigurationParser cp = new ConfigurationParser(warnings);
    ??????? Configuration config = null;
    ??????? try {
    ??????????? config = cp.parseConfiguration(configFile);
    ??????? } catch (IOException e) {
    ??????????? e.printStackTrace();
    ??????? } catch (XMLParserException e) {
    ??????????? e.printStackTrace();
    ??????? }
    ??????? DefaultShellCallback callback = new DefaultShellCallback(overwrite);
    ??????? MyBatisGenerator myBatisGenerator = null;
    ??????? try {
    ??????????? myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
    ??????? } catch (InvalidConfigurationException e) {
    ??????????? e.printStackTrace();
    ??????? }
    ??????? try {
    ??????????? myBatisGenerator.generate(null);
    ??????? } catch (SQLException e) {
    ??????????? e.printStackTrace();
    ??????? } catch (IOException e) {
    ??????????? e.printStackTrace();
    ??????? } catch (InterruptedException e) {
    ??????????? e.printStackTrace();
    ??????? }
    ??? }
    }


    到此為止,eclipse項目工程圖應該如下:


    4.運行測試的main 方法,生成mybatis 相關代碼
    運行GenMain類里的main方法,并刷新 工程,你會發現 各自package 目錄下已經響應生成了對應的文件,完全符合mybatis 規則,效果圖如下:


    5.注意事項
    如果你想生成example 之類的東西,需要在<table></table>里面去掉
    程序代碼
    enableCountByExample="false" enableUpdateByExample="false"
    enableDeleteByExample="false" enableSelectByExample="false"
    selectByExampleQueryId="false"

    這部分配置,這是生成Example而用的,一般來說對項目沒有用.

    另外生成的sql mapper 等,只是對單表的增刪改查,如果你有多表join操作,你就可以手動配置,如果調用存儲過程,你也需要手工配置. 這時工作量已經少很多了。

    如果你想用命令行方式處理,也是可以的.
    程序代碼
    比如:
    java -jar mybatis-generator-core-1.3.2.jar -mbgConfiguration.xm -overwrite

    這時,要用絕對路徑才行. 另外mbgConfiguration.xml? 配置文件中targetProject 的配置也必須是絕對路徑了。

    代碼下載:mybatis 代碼生成工具



    除非申明,文章均為一號門原創,轉載請注明本文地址,謝謝!

    mybatis SqlSessionDaoSupport的使用(附代碼下載)


    前面的系列mybatis 文章,已經基本講到了mybatis的操作,但都是基于mapper隱射操作的,在mybatis 3中這個mapper 接口貌似充當了以前在ibatis 2中的 DAO 層的作用。但事實上,如果有這個mapper接口不能完成的工作,或者需要更復雜的擴展的時候,你就需要自己的DAO 層. 事實上 mybatis 3 也是支持DAO 層設計的,類似于ibatis 2 .下面介紹下.

    在此之前,請下載 上一篇文章提供的代碼:http://www.yihaomen.com/article/java/326.htm

    首先創建一個com.yihaomen.dao的package.然后在里面分別創建接口UserDAO,以及實現該接口的UserDAOImpl
    程序代碼
    package com.yihaomen.dao;
    import java.util.List;
    import com.yihaomen.model.Article;
    public interface UserDAO {
    ??? public List<Article> getUserArticles(int userid);
    }


    程序代碼
    package com.yihaomen.dao;
    import java.util.List;
    import org.mybatis.spring.support.SqlSessionDaoSupport;
    import org.springframework.stereotype.Repository;
    import com.yihaomen.model.Article;

    @Repository
    public class UserDAOImpl extends SqlSessionDaoSupport implements UserDAO {
    ??? @Override
    ??? public List<Article> getUserArticles(int userid) {???????
    ??????? return this.getSqlSession().selectList("com.yihaomen.inter.IUserOperation.getUserArticles",userid);
    ??? }
    }


    執行的SQL 語句采用了命名空間+sql 語句id的方式,后面是參數.

    注意繼承了 "SqlSessionDaoSupport" ,利用方法 getSqlSession() 可以得到 SqlSessionTemplate ,從而可以執行各種sql語句,類似于hibernatetemplate一樣,至少思路一樣.

    如果與spring 3 mvc 集成要用? autowire的話,在daoimpl 類上 加上注解 “@Repository” ,另外還需要在spring 配置文件中加入<context:component-scan base-package="com.yihaomen.dao" /> 這樣在需要調用的地方,就可以使用autowire自動注入了。

    當然,你也可以按一般程序的思路,創建一個service 的package, 用service 去調用 dao層,我這里就沒有做了,因為比較簡單,用類似的方法,也機注意自動注入時,也要配置 <context:component-scan base-package="com.yihaomen.service" /> 等這樣的。

    在controller層中測試,直接調用dao層方法
    在controller中加入方法:
    程序代碼

    ??? @Autowired
    ??? UserDAO userDAO;

    ??????? .......

    ??? @RequestMapping("/daolist")
    ??? public ModelAndView listalldao(HttpServletRequest request,HttpServletResponse response){
    ??????? List<Article> articles=userDAO.getUserArticles(1);
    ??????? //制定視圖,也就是list.jsp
    ??????? ModelAndView mav=new ModelAndView("list");
    ??????? mav.addObject("articles",articles);
    ??????? return mav;
    ??? }

    這樣可以得到同樣的結果,而且滿足了一般程序的設計方法.代碼結構如下:


    完成后,程序代碼下載.
    點擊下載此文件

    提示

    推薦成功!

    查看鏈接地址:

    總結

    以上是生活随笔為你收集整理的mybatis实战教程(mybatis in action),mybatis入门到精通的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    免费在线电影网址大全 | 99久久99久久精品国产片果冰 | 中文字幕丰满人伦在线 | 日本护士三级少妇三级999 | 久草综合在线观看 | 国产精品午夜久久久久久99热 | 69视频永久免费观看 | 久久官网 | 在线观看日本高清mv视频 | 黄色特一级片 | 五月综合激情婷婷 | 日日爽夜夜操 | 免费一级黄色 | 精品久久久影院 | 狠狠色狠狠色综合日日小说 | 麻豆网站免费观看 | 国产精品手机在线观看 | 免费精品视频在线 | www.日韩免费 | 91看片在线看片 | 欧美电影黄色 | 一区二区三区精品在线视频 | 免费看黄色小说的网站 | 婷婷精品在线 | 亚洲精品黄色在线观看 | www.人人干| 97人人模人人爽人人少妇 | 久久久久免费看 | 国产精品18videosex性欧美 | 久久精品电影网 | 久久久久免费精品国产 | 国产精品麻 | 超级碰99 | 日韩激情网 | 91精品国产综合久久福利 | 91传媒在线 | 国产区 在线 | 色爱区综合激月婷婷 | 久久精品久久久久电影 | 久久久网站| 毛片美女网站 | 欧美日韩在线免费视频 | 精品国产区| 免费看的黄色录像 | 国产精品视频免费看 | 国产视频2区 | 91成年人在线观看 | 九九视频免费在线观看 | 日韩在线观看av | 欧美a级成人淫片免费看 | 日本公乱妇视频 | 日批在线看| 国产在线观看高清视频 | 国产精品成人一区二区三区吃奶 | 久久av伊人 | 91色在线观看视频 | 国产精品久久久久久久久岛 | 国产精品成人一区二区三区吃奶 | 天天色天天草天天射 | 狠狠插狠狠干 | 日韩电影中文字幕 | 国产精品久久久久婷婷二区次 | 欧美午夜寂寞影院 | 欧美激情在线看 | 久久这里只有精品1 | 国产日韩中文字幕在线 | 四虎影视国产精品免费久久 | 美女网站色在线观看 | 久久一区国产 | 国产色 在线 | 黄色美女免费网站 | 日韩免费不卡av | 日本丶国产丶欧美色综合 | 婷婷六月丁 | 日韩精品一区二区免费 | 日韩精品在线观看av | 97国产精品一区二区 | 五月天综合网站 | 中文视频一区二区 | 久久爱992xxoo| 日韩欧美在线观看一区 | 亚洲综合激情小说 | av在线之家电影网站 | 国产精品一区欧美 | 免费h精品视频在线播放 | 免费网站观看www在线观看 | 黄色三级在线观看 | 精品久久久久亚洲 | 91亚洲精品国偷拍自产在线观看 | 欧美aa级 | 日韩在线观看三区 | 国产精品高清一区二区三区 | 国产精品久久久影视 | 在线观看久久 | 99久久精品国产一区二区三区 | 日本 在线 视频 中文 有码 | 91女子私密保健养生少妇 | 香蕉在线观看 | 大胆欧美gogo免费视频一二区 | 日韩久久久久久久 | 黄色一级大片在线免费看产 | 二区三区在线观看 | 激情五月婷婷综合 | 中文字幕欧美激情 | 国产色在线,com| 天堂在线一区二区三区 | 日韩欧美一区二区三区免费观看 | 狠狠干天天射 | 亚洲永久精品在线观看 | 欧美视频xxx | 久久99免费观看 | 在线观看理论 | 日韩毛片一区 | 视频一区二区视频 | 免费视频黄色 | 天堂av网在线 | 国产亚洲精品女人久久久久久 | av大全在线 | 欧美日韩免费在线观看视频 | 激情黄色av | 婷婷在线看 | 免费久久99精品国产婷婷六月 | 久久精品视 | 中文字幕亚洲精品日韩 | 日本丶国产丶欧美色综合 | 成年人在线观看免费视频 | 亚洲成av片人久久久 | 伊人久久精品久久亚洲一区 | 99久久精品免费一区 | 久久久久久99精品 | 在线天堂8√ | 日日夜夜网站 | 欧美另类美少妇69xxxx | 成年人国产在线观看 | 黄色成人在线 | 狠狠干夜夜爱 | 久草在线视频中文 | 人人讲| 欧美黄在线 | 欧美精品网站 | 一二区精品 | 欧美一区二区三区免费观看 | 色偷偷888欧美精品久久久 | 天干啦夜天干天干在线线 | 在线黄色观看 | 在线观看国产一区 | 国产精品高潮呻吟久久av无 | www.夜夜骑.com | 在线观看涩涩 | 国产白浆在线观看 | 国产三级av在线 | 欧美亚洲一区二区在线 | 久久免费片 | 久久伦理影院 | 蜜臀久久99精品久久久无需会员 | 91精品啪| 国产精品 9999| 日本性高潮视频 | 日韩精品电影在线播放 | 亚洲午夜精 | 美女很黄免费网站 | 欧美国产日韩一区二区 | 国产亚洲精品久久久久久无几年桃 | 香蕉视频久久久 | 777xxx欧美 | 亚洲国产色一区 | 欧美午夜精品久久久久 | 99精品免费观看 | 欧美伦理一区二区三区 | 热久久国产 | 国产高清福利在线 | 天天曰天天爽 | 日日操天天爽 | av看片网址| zzijzzij日本成熟少妇 | 安徽妇搡bbbb搡bbbb | 1024在线看片 | 人人舔人人射 | 美女久久久久久久久久 | 天天操夜夜操 | 91视视频在线直接观看在线看网页在线看 | 久久免费视频7 | 国产高清视频在线 | 99精品国产aⅴ | 国产精品地址 | 亚洲精品欧美专区 | 国产超碰97 | 少妇激情久久 | 97视频在线免费观看 | 国产精品自产拍在线观看桃花 | 97超碰人人澡 | 亚洲国产精品成人综合 | 国产网红在线观看 | 亚洲综合成人专区片 | 天天干夜夜想 | 一区二区三区在线免费 | 国产不卡一 | 96国产精品视频 | 涩涩网站在线 | 国产在线观看99 | 九九99视频 | 激情网站免费观看 | 亚洲精品ww | 成人av电影免费观看 | 国产一区二区久久久久 | 久久久91精品国产一区二区精品 | 日韩精品视频第一页 | 亚洲精品国产区 | 日韩黄色软件 | 高潮毛片无遮挡高清免费 | 黄网站色| 黄网站app在线观看免费视频 | 国产亚洲精品v | 久久久久久久久久电影 | 免费三级网 | 欧美日韩在线免费观看 | 香蕉视频国产在线观看 | 波多野结衣在线观看视频 | 亚洲成人二区 | 天天操天天插 | 久久精品亚洲国产 | 狠狠狠色丁香婷婷综合激情 | 亚洲精品综合欧美二区变态 | 丁香婷婷深情五月亚洲 | 国内精品久久久精品电影院 | 国产一级黄大片 | 精品一区二区三区四区在线 | 91亚洲精品在线观看 | 免费av观看网站 | 天天爱综合 | 亚洲激情久久 | 99精品国产在热久久 | 视频三区 | 精品一区二区三区久久久 | 在线观看视频h | av久久久| 国产精品成人国产乱一区 | 亚洲精品国产第一综合99久久 | 欧美一级淫片videoshd | 欧美国产日韩在线观看 | 玖玖视频在线 | 婷婷色资源 | 黄色av一区二区三区 | 中文字幕高清免费日韩视频在线 | 久久精品成人 | 国产黄色精品网站 | 日韩在线第一区 | 欧美精品中文 | 国产高清福利在线 | 成人午夜剧场在线观看 | 91桃色免费视频 | 91免费观看视频网站 | 天天射天天射天天 | 手机在线免费av | 一区二区三区日韩在线 | 日韩一区精品 | 亚洲久草网 | 99久久激情视频 | 国产精品激情偷乱一区二区∴ | 久久久亚洲电影 | 日韩精品一区二区三区在线播放 | 欧美日韩综合在线观看 | 国内少妇自拍视频一区 | 中文字幕在线播放一区二区 | 成人一区二区三区在线 | 久久久久久久久久久久影院 | 亚洲日本在线视频观看 | 成人久久久久久久久久 | 色婷婷综合激情 | 久久最新视频 | 国产资源网站 | 久久久久久久久久福利 | 在线观看日本韩国电影 | 91高清视频在线 | 午夜精品成人一区二区三区 | www.干| 99久久精品国产一区二区三区 | 97日日碰人人模人人澡分享吧 | 久久在线看| 成人av资源网| 成人黄色av免费在线观看 | 国产精品不卡av | 亚洲国产成人精品在线 | 91九色视频在线 | 精品国产美女 | 欧美做受xxx | 狠狠狠色 | 久久草在线精品 | 久久久www | 西西人体www444 | 亚洲天堂激情 | av电影免费在线播放 | 97成人在线免费视频 | 激情五月六月婷婷 | 玖玖在线免费视频 | 这里只有精彩视频 | 高清av网站 | 激情视频二区 | japanesefreesex中国少妇 | 99热播精品 | 麻豆视频免费看 | 国产精品尤物 | 欧美精品乱码久久久久久按摩 | 伊人看片 | 超级碰碰视频 | av网址在线播放 | 国产a视频免费观看 | 99久久精品免费看国产一区二区三区 | 久久久久久久国产精品 | 在线免费中文字幕 | 黄色小说在线观看视频 | 久热免费 | 成人av片免费观看app下载 | 天天干天天操av | 国产精品成人免费 | 最近中文字幕mv免费高清在线 | 99免费国产 | 天天se天天cao天天干 | 国产四虎在线 | 国产小视频免费在线观看 | 人人草在线视频 | 在线视频在线观看 | 久久精品久久国产 | 国产精品午夜在线观看 | 婷婷久久五月天 | 精品国产人成亚洲区 | 欧美嫩草影院 | 日日夜夜人人精品 | av在线一| 欧美日韩二三区 | 毛片一二区 | 国产精品免费久久久久久 | 久久99影院 | 玖草影院| 亚洲精品乱码久久久久久蜜桃91 | 日韩色区 | 美女视频黄免费网站 | 一区在线免费观看 | 丁香六月在线 | 日韩va亚洲va欧美va久久 | 久久亚洲欧美 | 日韩欧在线 | av免费观看高清 | 成年人app网址 | www.人人干| 射射射av | 亚洲国产精品va在线 | 激情网五月天 | 婷婷成人亚洲综合国产xv88 | 国产在线观看中文字幕 | 在线免费观看羞羞视频 | 99久久99久国产黄毛片 | 成人理论在线观看 | 欧美午夜视频在线 | 精品福利网站 | 97碰在线 | 国产精品女同一区二区三区久久夜 | 久久人网| 日本中文字幕在线一区 | 91丨九色丨高潮丰满 | 国产日韩欧美中文 | 欧产日产国产69 | 日韩av在线不卡 | 久久久精品 一区二区三区 国产99视频在线观看 | 国产精品第一视频 | 免费视频一区二区 | 最近中文字幕国语免费av | 午夜精品久久久99热福利 | 伊人六月| 久久精品一区二区三 | 国产精品久久精品国产 | 国产精品女教师 | 狠狠色丁香婷婷综合基地 | 亚洲作爱视频 | av成人亚洲 | 免费亚洲黄色 | 伊人久久国产精品 | 久久99精品热在线观看 | 久久久久免费精品视频 | 天天干天天操天天射 | 国产亚洲精品美女 | 九九热只有这里有精品 | 激情五月婷婷综合网 | 97人人模人人爽人人喊中文字 | 九九爱免费视频 | www.夜夜爽| 亚洲精品国产精品国产 | 天天干天天草天天爽 | 亚洲精品国产区 | 久久6精品 | 国产中文字幕网 | 天天天干 | 国产精品成人一区二区三区吃奶 | 免费污片 | 欧亚日韩精品一区二区在线 | 欧美最新另类人妖 | 中文字幕国产一区 | 在线观看日韩一区 | 521色香蕉网站在线观看 | 亚洲黄色免费在线看 | 亚洲人人精品 | 亚洲成人av在线电影 | 国产啊v在线| 亚洲精品网站在线 | 综合天天色 | 亚洲视频 视频在线 | 成人免费一区二区三区在线观看 | 成人福利在线 | 国产最新视频在线 | 国产精品综合久久久久 | 2019免费中文字幕 | 欧美亚洲另类在线视频 | 精品国产成人在线 | wwwwww国产| 日本丰满少妇免费一区 | 成人国产精品久久久久久亚洲 | 人人澡人人草 | 中文字幕亚洲欧美日韩 | 国产91亚洲精品 | 欧美 亚洲 另类 激情 另类 | 91精品国产麻豆 | 中文字幕在线观看完整 | 精品美女在线观看 | 午夜影院在线观看18 | 婷婷资源站 | 国产在线播放一区二区 | 国产精品原创av片国产免费 | 国产午夜一级毛片 | 91香蕉国产 | 日韩在线一级 | 黄色1级大片 | 日韩免费在线观看 | 91精品久久久久久久久 | 九九热免费视频在线观看 | 日本最新中文字幕 | 久久网站av | 午夜影视av | 日韩综合精品 | 日批在线观看 | 欧美亚洲国产日韩 | 久久久久久久免费观看 | 欧美日韩首页 | 黄色www免费 | 在线视频1卡二卡三卡 | 久操视频在线播放 | 草久久影院 | 国产又粗又猛又黄又爽视频 | 天天综合网天天 | 国产色爽 | 国产午夜精品一区 | 久久精品国产一区 | 色在线亚洲| 又黄又爽又色无遮挡免费 | 99热精品国产 | www.国产精品| 免费中文字幕在线观看 | 亚洲精品在线国产 | 精品国产亚洲日本 | www.精选视频.com | 久草在线高清视频 | 久草免费在线视频观看 | 新av在线 | 在线免费视频一区 | 尤物97国产精品久久精品国产 | 中文亚洲欧美日韩 | 午夜精品福利在线 | 亚洲精品玖玖玖av在线看 | 国产精品激情偷乱一区二区∴ | 人人射 | 国产一区二区在线免费 | 成人免费观看在线视频 | 中文字幕 国产 一区 | 国产精品一区在线播放 | 国产日韩精品一区二区 | 狠狠搞,com| 亚洲无吗av| 青青河边草观看完整版高清 | 黄色小说免费在线观看 | www.狠狠 | 国产黑丝一区二区 | 成人黄色毛片视频 | 日韩激情一二三区 | 成人在线视频免费看 | 最新国产一区二区三区 | 婷婷丁香五 | 久久亚洲人 | 亚洲视频免费 | 国产麻豆剧果冻传媒视频播放量 | 婷婷色视频 | 国产99久久九九精品免费 | 99久久久久 | 97av视频在线| 久久视频这里有久久精品视频11 | 奇米影音四色 | 黄色网址国产 | 欧美日韩国产精品一区二区 | 亚洲综合导航 | 99精品99| 怡红院av久久久久久久 | 日韩激情av在线 | 91女神的呻吟细腰翘臀美女 | 日韩精品在线看 | 欧美色婷婷 | 日日夜夜免费精品视频 | 国产在线久久久 | 国内精品视频免费 | 国产区精品| www.久久婷婷| 91桃花视频| 五月开心六月婷婷 | 欧美一级性生活片 | 欧美一区二视频在线免费观看 | av成人在线观看 | 日本3级在线观看 | 日韩av影视在线 | 成人在线观看你懂的 | 激情欧美xxxx| 亚洲精品国产精品乱码在线观看 | 最新超碰 | av一区二区三区在线观看 | 国产98色在线 | 日韩 | 在线影视 一区 二区 三区 | 九九久久精品 | 久日视频 | 女人18毛片a级毛片一区二区 | 日韩网站在线免费观看 | 日韩av资源在线观看 | 国产不卡毛片 | 欧美韩国日本在线观看 | 免费久久99精品国产 | 六月色丁香 | 国产97视频在线 | 欧美成人黄色片 | 久久精品免费观看 | 国产在线综合视频 | 亚洲精品国产电影 | 久久综合久久久久88 | 91精品视频在线看 | 国产日韩欧美在线影视 | 99精品视频99| 精品国产免费久久 | 欧美日韩大片在线观看 | 欧美大jb | 国产精品久久综合 | 国产一区久久久 | 久久伊人五月天 | 亚洲日本黄色 | 97色婷婷成人综合在线观看 | 精品国产精品国产偷麻豆 | 国产精品视频永久免费播放 | 香蕉影视在线观看 | 国产高清不卡一区二区三区 | 日韩中文在线视频 | 色婷婷五 | 色综合天天 | 成年人免费在线观看 | 91大神精品视频在线观看 | 亚洲精品视频网址 | 久久综合给合久久狠狠色 | 亚洲欧美婷婷六月色综合 | 91九色精品女同系列 | 色综合夜色一区 | 国产黄色在线网站 | 麻豆国产精品永久免费视频 | 少妇av网 | 中文字幕av播放 | 成人av一区二区三区 | 国产福利一区二区三区视频 | 亚洲高清国产视频 | 婷婷丁香激情网 | 91精品婷婷国产综合久久蝌蚪 | www.xxx.性狂虐 | 亚洲精品综合久久 | 久久久伊人网 | 欧美三级高清 | 久久免费国产电影 | 日韩亚洲精品电影 | 免费看片成年人 | 国产最新网站 | 成人av免费在线 | 91av原创 | av一区二区三区在线观看 | 西西www4444大胆视频 | 中文字幕免费在线看 | 91完整版观看 | 99人成在线观看视频 | 特黄特色特刺激视频免费播放 | 爱干视频 | 久久er99热精品一区二区 | 中文字幕在线观看的网站 | 国产精品美女毛片真酒店 | 成人一区二区三区在线观看 | 久色 网 | 天堂在线v | 国产精品久久久久久吹潮天美传媒 | 欧美福利视频一区 | 亚洲涩涩网站 | 午夜久久福利 | 欧美成人一二区 | 婷婷 中文字幕 | avv天堂| 午夜视频免费播放 | 亚洲四虎影院 | 激情久久五月 | 久久综合久久鬼 | 伊人天堂网 | 九九欧美视频 | 91在线看黄 | 日韩在线观看视频网站 | 91亚洲精品久久久蜜桃网站 | 婷婷丁香av | 欧美俄罗斯性视频 | 射射色| 一区二区视频在线免费观看 | 天天看天天干天天操 | 97视频播放 | 久久久穴 | 天天天天天天干 | 91av视频 | 日韩中文字幕免费视频 | 成人免费视频网 | 99热精品久久 | 毛片www | 激情图片区 | 色综合久久66 | 色偷偷88欧美精品久久久 | 国产91影视| 日本xxxx.com| 一级a毛片高清视频 | 日本中文字幕一二区观 | 国产资源网 | 久久久久亚洲a | 久久韩国免费视频 | 美女久久久 | 99久久精品国 | 99精品国产一区二区三区不卡 | 久久大片网站 | av黄免费看 | 亚洲欧美成人综合 | 91欧美精品| 日韩欧美网址 | 久久免费精品一区二区三区 | 手机看片国产日韩 | 亚洲午夜精品一区二区三区电影院 | 成片视频免费观看 | 99视频在线 | 日韩免费网址 | 亚洲国产精品激情在线观看 | 日韩色视频在线观看 | 国产成人三级在线观看 | 99在线免费视频 | 极品久久久久 | 天天摸天天舔 | 欧美午夜理伦三级在线观看 | 日本午夜在线观看 | 特级大胆西西4444www | 激情五月六月婷婷 | 天堂va在线观看 | 久久欧美精品 | 亚洲一级黄色大片 | 99色99| 在线观看一级 | 网站免费黄色 | 日韩欧美高清不卡 | 亚洲精品国精品久久99热 | 就操操久久 | 亚洲欧美成人综合 | 国产亚洲在线观看 | 国产精品你懂的在线观看 | 丁香六月婷婷综合 | 天天综合色| 香蕉久久久久久av成人 | 99久久电影 | 日韩电影在线一区二区 | 天天搞夜夜骑 | 超碰在线人 | 在线观看中文字幕dvd播放 | 亚洲开心色| 狠狠色丁香久久婷婷综合丁香 | 久久经典国产 | 一区二区三区在线电影 | 国产精品久久久久久久久久免费看 | 天天干天天怕 | 欧美成人黄 | 日韩免费一级a毛片在线播放一级 | 丁香婷婷综合激情五月色 | 国产精品九色 | 97**国产露脸精品国产 | 欧美少妇xxxxxx | 激情五月***国产精品 | 人成在线免费视频 | 国产在线国偷精品产拍 | 国产亚洲精品久久久久久久久久久久 | 日韩一区二区三区高清在线观看 | 大胆欧美gogo免费视频一二区 | 91看片看淫黄大片 | 欧美一区二区精美视频 | 日日夜夜精品视频天天综合网 | 在线视频日韩欧美 | 手机版av在线 | 久久久久久久久久影视 | 久久免费影院 | 999久久久久久久久久久 | 黄色网在线播放 | 日韩在线观看一区 | 激情网站网址 | 欧美少妇影院 | 日韩www在线| 国产 亚洲 欧美 在线 | av千婊在线免费观看 | 精品福利在线视频 | 国内99视频 | 色网址99 | 最近中文字幕免费 | www.狠狠| av免费在线看网站 | 右手影院亚洲欧美 | 婷婷色吧| 中文字幕在线观看第一区 | 中文字幕一区二区三区四区久久 | 日韩一级黄色av | 99理论片| 国产一二三区av | 欧美日韩久久不卡 | 久久久午夜视频 | 欧美 日韩 国产 成人 在线 | 99免在线观看免费视频高清 | 久久免费视频网站 | 国产96在线 | www.国产视频 | 国产在线国偷精品产拍免费yy | 久久久www成人免费毛片麻豆 | 特级毛片在线 | 欧美 激情在线 | 亚洲一区视频免费观看 | 免费色视频网站 | 99麻豆视频| av福利在线导航 | 国产玖玖精品视频 | 精品国偷自产国产一区 | 人人干免费 | 天天干,夜夜爽 | 国产精品久久 | 成人精品国产 | 这里只有精品视频在线观看 | 中文字幕色网站 | 久久久影院一区二区三区 | 亚洲精品人人 | 亚洲一区日韩精品 | 中文字幕在线视频国产 | 成人久久18免费网站 | 在线观看日韩av | 8090yy亚洲精品久久 | 中文字幕一区二区三区在线播放 | 久操中文字幕在线观看 | 狠狠久久 | 精品国产亚洲一区二区麻豆 | 国内丰满少妇猛烈精品播 | 国产精品美女久久久久久久久 | 日韩a欧美 | 最新超碰| 天天插视频 | 天天天干天天射天天天操 | 国产精品va| 成人av电影免费观看 | 天天干一干 | 亚洲天堂网在线播放 | 中文视频一区二区 | 99精品在线免费观看 | 国产一区二区精品91 | 欧美成人精品在线 | 国产精品久久久久一区二区三区共 | 日韩二区三区 | 日本99久久 | 国产综合激情 | 91激情视频在线观看 | 激情开心 | 天天碰天天操视频 | 国产精品a成v人在线播放 | 午夜精品久久久久久久99婷婷 | 91九色网站 | 欧美午夜剧场 | 视频三区在线 | 人人草网站 | 国产精品一区二区免费 | 欧美日韩在线电影 | 99超碰在线播放 | 欧洲视频一区 | 人人舔人人干 | 九九色网 | 综合色伊人 | 欧美a在线看 | 午夜视频99 | 亚洲一区二区观看 | av色综合| 成人黄色电影视频 | 色丁香色婷婷 | 亚洲精品一区二区在线观看 | 伊人婷婷网 | 精品一区二区综合 | 国产精品第10页 | 日韩精品视频久久 | 日韩av一区二区在线影视 | 日韩av一区二区三区在线观看 | 国产精品2019| 亚洲dvd| 日韩精品欧美专区 | 黄色片网站av | 色多多视频在线 | 婷婷六月天天 | 久久久久激情视频 | 中文字幕无吗 | 国产人在线成免费视频 | 久久99热精品 | 婷婷日日 | 天天透天天插 | 91精品爽啪蜜夜国产在线播放 | 国产亚洲精品成人 | 亚洲另类人人澡 | 免费日韩一区二区三区 | 国产视频资源 | 国产精品久久久久久久免费观看 | 国产精品第54页 | 尤物97国产精品久久精品国产 | 91香蕉国产在线观看软件 | 日韩黄色av网站 | 人人射人人插 | 国产精品美女久久久久久久 | 欧美一级特黄aaaaaa大片在线观看 | 日韩av免费在线电影 | 天天av资源 | 国产日本在线观看 | 中文字幕在线观看1 | av在线免费观看网站 | 国内揄拍国产精品 | 99精品久久久久 | 17videosex性欧美 | 中文字幕在线视频国产 | 91成人免费看片 | 亚洲国产精品人久久电影 | 色婷婷五 | 天天插狠狠干 | 国产福利午夜 | 97综合网| 五月综合色婷婷 | 91理论片午午伦夜理片久久 | 日韩最新av | 91成人久久| 久久久精品视频成人 | 国产成人一区二区三区 | 六月丁香激情网 | 国产成人无码AⅤ片在线观 日韩av不卡在线 | 婷婷激情影院 | 丝袜精品视频 | 婷婷色狠狠 | 亚洲精品播放 | 精品视频| 亚洲丝袜一区二区 | 国产黄色片网站 | 国产淫片免费看 | 一区二区三区免费在线观看视频 | 国产精品观看在线亚洲人成网 | 在线视频中文字幕一区 | 天天操天天摸天天爽 | 91新人在线观看 | 精品国产电影一区 | 国产免费观看av | 91爱爱视频 | 色九九影院 | 国产不卡av在线 | 麻豆国产在线视频 | 在线视频18在线视频4k | 欧美伊人网| 97视频免费在线看 | 亚洲最大在线视频 | av中文天堂在线 | 成人污视频在线观看 | 亚洲综合爱| 激情欧美国产 | 国产小视频在线免费观看视频 | 欧美性性网 | 国产日韩视频在线 | 日本激情中文字幕 | 成人中文字幕av | 欧美激情第28页 | 天天摸天天弄 | 毛片在线播放网址 | 国产午夜精品免费一区二区三区视频 | 免费成人av在线看 | 黄网站免费大全入口 | 国产精品青草综合久久久久99 | 欧美精品国产综合久久 | 国产在线视频导航 | 亚洲欧美经典 | 人人网人人爽 | 久久久久久久久久久福利 | 亚洲欧美国产日韩在线观看 | 91在线免费观看网站 | 玖玖精品在线 | 91精品爽啪蜜夜国产在线播放 | av午夜电影| 日韩二区三区在线观看 | 国产露脸91国语对白 | 91最新视频在线观看 | 国产福利免费看 | 欧美a影视 | 中文字幕在线观看国产 | 亚洲第一区在线播放 | av片在线观看 | 亚洲精品乱码久久久久久蜜桃91 | 草久久久久久久 | 日韩精品短视频 | 亚洲久在线 | 91精品中文字幕 | 欧美日韩国产一区二区三区 | 久久成人毛片 | 亚洲理论在线观看 | 国产精品18久久久久久久网站 | 久久综合久久综合九色 | 国产亚洲成人网 | 日韩在线播放av | 激情电影在线观看 | 黄色网址在线播放 | 黄色小说视频网站 | 久久爱综合 | 久久久伊人网 | 精品理论片 | 欧美精品在线视频 | 亚洲精品国精品久久99热 | 亚州国产精品 | 草久中文字幕 | 777视频在线观看 | 日av免费| 涩涩在线 | 日韩成人免费在线观看 | 国产精品一区二区三区视频免费 | 黄色一级大片在线免费看国产一 | www.av小说| 天天干天天操天天射 | 香蕉视频久久久 | 亚洲 中文 欧美 日韩vr 在线 | 日韩二区三区在线 | 日韩精品一区二区免费 | 欧亚日韩精品一区二区在线 | 国产69久久 | 亚洲精品国产精品国自产在线 | 色综合久久综合网 | 国产亚洲精品久久久久久网站 | 麻豆精品91 | 欧美激情亚洲综合 | 西西www4444大胆在线 | 色在线国产 | 国产精品av免费 | 免费看v片网站 | 9999免费视频| 国产精品嫩草影院123 | 日日夜夜网站 | 久久社区视频 | 日韩久久久 | 中文在线最新版天堂 | 婷婷综合激情 | 天天色天天射天天综合网 | 一级片视频免费观看 | 91精品视频在线 | 色视频网站在线 | 啪嗒啪嗒免费观看完整版 | 日韩中文在线视频 | 碰超在线97人人 | 五月香视频在线观看 | a视频在线播放 | 伊人丁香| 婷婷激情五月综合 | www.日韩免费 | 激情av资源| 日韩欧美视频一区二区 | 久久 地址 | 亚洲最新av网址 | 亚洲精品mv在线观看 | 免费精品国产va自在自线 | 91中文字幕网 | 开心激情婷婷 | 亚洲第一伊人 | 色www精品视频在线观看 | 91欧美视频网站 | 天天操天天舔天天干 | 久久精品视频在线播放 | 午夜久久福利视频 | 国产 欧美 在线 | 亚洲综合导航 | 人人澡人人爽欧一区 | 日本中文字幕高清 | 欧美激情精品久久 | 亚洲精品66 | 婷婷国产精品 | 91av电影| 久热香蕉视频 | 国产v亚洲v | 久久成人精品 |