Java學(xué)習(xí)day-61:MyBatis框架(3)

一、resultMap標(biāo)簽的使用

1.解決列名和屬性名的不一致:

如果查詢時(shí)使用 resultType 屬性, 表示采用 MyBatis 的Auto-Mapping(自動(dòng)映射)機(jī)制, 即相同的列名和屬性名會(huì)自動(dòng)匹配. 因此, 當(dāng)數(shù)據(jù)庫表的列名和類的屬性名不一致時(shí), 會(huì)導(dǎo)致查不到數(shù)據(jù). 解決該問題可以有兩種方式:

  • 起列別名:

查詢時(shí), 可以通過列別名的方式將列名和屬性名保持一致, 繼續(xù)使用自動(dòng)映射, 從而解決該問題. 但是較為麻煩梁呈。

<select id="selAll" resultType="user"> 
 select id id1, username username1, password password2 from t_user
</select> 
  • 使用<resultMap>標(biāo)簽

<resultMap>用于自定義映射關(guān)系, 可以由程序員自主制定列名和屬性名的映射關(guān)系东羹。一旦使用 resultMap, 表示不再采用自動(dòng)映射機(jī)制鲁僚。

(1)代碼示例:

<mapper namespace="com.zlw.mapper.UserMapper">

    <resultMap type="user" id="umap">
        <id column="userId" property="userId1"/>
        <result column="userName" property="userName1"/>
        <result column="userPass" property="userpass1"/>
    </resultMap>
    
    <select id="selAll" resultMap="umap">
        select* from t_user
    </select>
</mapper>

(2)測(cè)試:

@Test
    public void Sel() throws IOException {
        InputStream is = Resources.getResourceAsStream("mybatis.xml");

        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
        SqlSession session = factory.openSession();
        List<User> list = session.selectList("com.zlw.mapper.UserMapper.selAll");
        for (User user : list) {
            System.out.println(user);
        }
        session.close();
    }

(3)結(jié)果:


結(jié)果

2.多表連接查詢(多對(duì)一):

?????mapper 層只做單表查詢操作, 在 service 層進(jìn)行手動(dòng)裝配, 實(shí)現(xiàn)關(guān)聯(lián)查詢的結(jié)果。
創(chuàng)建兩個(gè)表;
創(chuàng)建兩個(gè)實(shí)體類倦零;
Mapper層:
提供StudentMapper和ClazzMapper, StudentMapper查詢所有學(xué)生信息藐石,ClazzMapper 根據(jù)編號(hào)查詢班級(jí)信息即供。

(1)sql語句:

create table t_class(
    id int(3) PRIMARY key auto_increment,
    name VARCHAR(20) not null,
    room VARCHAR(20)
    
)
create table t_student(
    id int(5) PRIMARY KEY auto_increment,
    name VARCHAR(30) not null,
    age int(3),
    gender CHAR(3),
    cid int(3) references t_class (id)
)

(2)映射文件配置:

<select id="selAll" resultType="Student">
        select *from t_student
    </select>
<mapper namespace="com.zlw.mapper.ClazzMapper">
    <select id="findById" resultType="clazz" parameterType="int">
        select *from t_class where id = #{0}
    </select>
  </mapper>

(3)Service層:

public List<Student> selAll() {
        //學(xué)生mapper
        SqlSession session = MyBatisUtil.getSqlSession();
        StudentMapper stumapper= session.getMapper(StudentMapper.class);
        //班級(jí)mapper
        ClazzMapper clamapper = session.getMapper(ClazzMapper.class);
        
        List<Student> list = stumapper.selAll();
        
        for (Student student : list) {
            int id = student.getCid();
            Clazz clazz = clamapper.findById(id);
            student.setClazz(clazz);
        }
        session.close();
        return list;
    }

(4)測(cè)試:

@Test
    public void StudentTest() {
        StudentService ss = new StudentServiceImpl();
        List<Student> list = ss.selAll();
        for (Student student : list) {
            System.out.println(student);
        }
    }
結(jié)果

3.resultMap的N+1方式實(shí)現(xiàn)多表查詢(多對(duì) 一)

<association>標(biāo)簽的使用;用于關(guān)聯(lián)一個(gè)對(duì)象 于微。
屬性:
property: 指定要關(guān)聯(lián)的屬性名 逗嫡;
select: 設(shè)定要繼續(xù)引用的查詢, namespace+id ;
column: 查詢時(shí)需要傳遞的列 株依;

(1)mapper層:

提供StudentMapper和ClazzMapper, StudentMapper查詢所有學(xué)生信息驱证,ClazzMapper 根據(jù)編號(hào)查詢班級(jí)信息。再StudentMapper 中使用<association>設(shè)置裝配恋腕。

<mapper namespace="com.bjsxt.mapper.StudentMapper"> 
 <resultMap type="student" id="smap">   
<!-- N+1查詢時(shí), 同名映射可以省略, 但是只能使用一次 -->  
<result property="cid" column="cid" />  
 <!-- 用于關(guān)聯(lián)一個(gè)對(duì)象 -->   
<association property="clazz" select="com.zlw.mapper.ClazzMapper.selById" 
column="cid">
</association>  
</resultMap>  
<select id="selAll" resultMap="smap">   
select * from t_student 
 </select> 
</mapper> 
<mapper namespace="com.zlw.mapper.ClazzMapper">  
<select id="selById" resultType="clazz" parameterType="int">   
select * from t_class where id=#{0} 
 </select> 
</mapper> 

(2)service層:

@Override 
public List<Student> selAll() {   
SqlSession session = MyBatisUtil.getSession(); 
  // 學(xué)生mapper   
StudentMapper stuMapper = session.getMapper(StudentMapper.class); 

  List<Student> list = stuMapper.selAll(); 
 
  session.close();   return list;  
} 

(3)測(cè)試:

@Test
    public void StudentTest() {
        StudentService ss = new StudentServiceImpl();
        List<Student> list = ss.selAll();
        for (Student student : list) {
            System.out.println(student);
        }
    }
結(jié)果

4.解決N+1問題:

使用多表表連接查詢語句抹锄;
在 StudentMapper.xml 中定義多表連接查詢 SQL 語句, 一次性查到需要的所有數(shù)據(jù), 包括對(duì)應(yīng)班級(jí)的信息。
通過<resultMap>定義映射關(guān)系, 并通過<association>指定對(duì)象屬性的映射關(guān)系. 可以把<association>看成一個(gè)<resultMap>使用. javaType 屬性表示當(dāng)前對(duì)象, 可以寫全限定路徑或別名荠藤。

(1)MyBatis核心配置文件:

<?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>

    <properties resource="db.properties" />

    <settings>
        <setting name="logImpl" value="LOG4J" />
    </settings>

    <typeAliases>
        <package name="com.zlw.pojo"/>
    </typeAliases>

    <environments default="dev1">
        <environment id="dev1">
            <transactionManager type="JDBC"></transactionManager>
            <dataSource type="pooled">
                <property name="driver" value="${jdbc.driver}" />
                <property name="url" value="${jdbc.url}" />
                <property name="username" value="${jdbc.username}" />
                <property name="password" value="${jdbc.password}" />
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <package name="com.zlw.mapper"/>
    </mappers>
</configuration>

(2)封裝簡(jiǎn)單的工具類:

package com.zlw.util;

import java.io.IOException;
import java.io.InputStream;

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

public class MyBatisUtil {
    private static SqlSessionFactory factory = null;
    static {
        try {
            InputStream is = Resources.getResourceAsStream("mybatis.xml");
            factory = new SqlSessionFactoryBuilder().build(is);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static SqlSession getSqlSession() {
        SqlSession session = null;
        if (factory != null) {
            session = factory.openSession();
        }
        return session;
    }
}

(3)mapper層:

    <resultMap type="student" id="umap">

        <id property="id" column="id" />
        <result property="name" column="name" />
        <result property="age" column="age" />
        <result property="gender" column="gender" />
        <result property="cid" column="cid" />

        <association property="clazz" javaType="clazz">
            <id property="id" column="cid" />
            <result property="name" column="cname" />
            <result property="room" column="room" />
        </association>

    </resultMap>
    <select id="selAll2" resultMap="umap">
        select s.*,c.name cname ,c.room from t_student s
        LEFT JOIN t_class c on s.cid= c.id
    </select>
<mapper namespace="com.zlw.mapper.ClazzMapper">
    <select id="findById" resultType="clazz" parameterType="int">
        select *from t_class where id = #{0}
    </select>
    
  </mapper>

(4)service層:

public List<Student> selAll2() {
            //學(xué)生mapper
            SqlSession session = MyBatisUtil.getSqlSession();
            StudentMapper stumapper= session.getMapper(StudentMapper.class);
            
            List<Student> list = stumapper.selAll2();
            
            session.close();
            return list;
        }

(5)測(cè)試:

@Test
    public void StudentTest2() {
        StudentService ss = new StudentServiceImpl();
        List<Student> list = ss.selAll2();
        for (Student student : list) {
            System.out.println(student);
        }
    }
結(jié)果

5.resultMap的關(guān)聯(lián)方式實(shí)現(xiàn)多表查詢(一對(duì)多) :

在 ClazzMapper.xml 中定義多表連接查詢 SQL 語句, 一次性查到需要的所有數(shù)據(jù), 包括對(duì)應(yīng)學(xué)生的信息伙单。
通過<resultMap>定義映射關(guān)系, 并通過<collection>指定集合屬性泛型的映射關(guān)系. 可以把<collection>看成一個(gè)<resultMap>使用。ofType 屬性表示集合的泛型, 可以寫全限定路徑或別名哈肖。

  • mapper層:
<resultMap type="clazz" id="cmap2">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <result property="room" column="room"/>
        
        <collection property="stus" javaType="list" ofType="student">
            <id property="id" column="sid"/>
            <result property="name" column="sname"/>
            <result property="age" column="age"/>
            <result property="gender" column="gender"/>
            <result property="cid" column="cid"/>
        </collection>
    </resultMap>
    <select id="selAll2" resultMap="cmap2">
    select c.*,s.id sid,s.name sname ,s.age,s.gender,s.cid from t_student s
        right JOIN t_class c on s.cid= c.id
    </select>
<mapper namespace="com.zlw.mapper.StudentMapper">

    <select id="findById" resultType="student">
        select *from t_student where cid = #{0}
    </select>
</mapper>
  • service層:
public List<Clazz> selAll2() {
        SqlSession session = MyBatisUtil.getSqlSession();
        ClazzMapper mapper = session.getMapper(ClazzMapper.class);
        List<Clazz> list = mapper.selAll2();
        return list;
    }

(3)測(cè)試:

    @Test
    public void ClazzTest2() {
        ClassService cs = new ClazzServiceImpl();
        List<Clazz> list = cs.selAll2();
        for (Clazz clazz : list) {
            System.out.println(clazz);
        }
    }
結(jié)果

6.通過Auto-Mapping實(shí)現(xiàn)多表查詢 :

) 通過 MyBatis 的 Auto-Mapping 機(jī)制及數(shù)據(jù)庫查詢時(shí)的別
名結(jié)合, 可以方便的實(shí)現(xiàn)多表查詢吻育。
SQL 語句中, 別名出現(xiàn)特殊符號(hào)時(shí), 必須進(jìn)行處理. MySQL可以使用(``)符號(hào), Oracle 可以使用("")符號(hào)。
(1)mapper:

<!-- auto -->
    <select id="selAll3" resultType="student">
        select s.*,c.id `clazz.id`,c.name `clazz.name` ,c.room `clazz.room` 
        from t_student s
        LEFT JOIN t_class c 
        on s.cid= c.id
    </select>

(2)service:

    public List<Student> selAll3() {
        SqlSession session = MyBatisUtil.getSqlSession();
        StudentMapper mapper = session.getMapper(StudentMapper.class);
        
        List<Student> list = mapper.selAll3();
        session.close();
        return list;
    }

(3)測(cè)試:

@Test
    public void StudentTest3() {
        StudentService ss = new StudentServiceImpl();
        List<Student> list = ss.selAll3();
        for (Student student : list) {
            System.out.println(student);
        }
    }
結(jié)果

二淤井、MyBatis的注解開發(fā)

1.注解開發(fā):

注解是用于描述代碼的代碼. 例如: @Test(用于描述方法進(jìn)行 junit 測(cè)試),@Override(用于描述方法的重寫), @Param(用于描述屬性的名稱)布疼。
使用前必須先導(dǎo)包 摊趾;
使用注解一般用于簡(jiǎn)化配置文件. 但是, 注解有時(shí)候也不是很友好(有時(shí)候反而更麻煩), 例如動(dòng)態(tài) SQL。
注解和配置文件可以配合使用游两。

  • 注解的屬性:
    屬性的設(shè)定方式是: 屬性名=屬性值 ;
    基本類型和 String, 可以直接使用雙引號(hào)的形式
    數(shù)組類型, name={值 1, 值 2, ...}; 如果數(shù)組元素只有一個(gè), 可以省略大括號(hào)严就;
    對(duì)象類型, name=@對(duì)象名(屬性) 。
    如果屬性是該注解的默認(rèn)屬性, 而且該注解只配置這一個(gè)屬性, 可以將屬性名省略器罐。

2.使用注解完成單表增刪改查:

@Select: 類似于<select>
@Insert: 類似于<insert>
@Update: 類似于<update>
@Delete: 類似于<delete>

(1)mapper:

package com.zlw.mapper;

import java.util.List;

import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;

import com.zlw.pojo.Student;

public interface StudentMapper {
    
    @Select("select * from t_student")
    List<Student> sleAll();
    
    @Insert("insert into t_student values(default,#{name},#{age},#{gender},#{cid})")
    int add(Student stu);
    
    @Update("update t_student set age=#{1} where id=#{0}")
    int update(int id, int age);
    
    @Delete("delete from t_student where id = #{0}")
    int delete(int id);
}

(2)測(cè)試:

package com.zlw.test;

import java.util.List;

import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import com.zlw.mapper.StudentMapper;
import com.zlw.pojo.Student;
import com.zlw.util.MyBatisUtil;

public class Test01 {
    
    @Test
    public void selAll() {
        SqlSession session = MyBatisUtil.getSqlSession();
        StudentMapper mapper = session.getMapper(StudentMapper.class);
        
        List<Student> list = mapper.sleAll();
        for (Student student : list) {
            System.out.println(student);
        }
        session.close();
    }
    @Test
    public void add() {
        SqlSession session = MyBatisUtil.getSqlSession();
        StudentMapper mapper = session.getMapper(StudentMapper.class);
        
        Student stu = new Student();
        stu.setName("Dave");
        stu.setAge(18);
        stu.setGender("男");
        stu.setCid(2);
        int num = mapper.add(stu);
        if(num>0) {
            System.out.println("添加成功梢为!");
            session.commit();
        }else {
            System.out.println("添加失敗轰坊!");
            session.rollback();
        }
        session.close();
    }
    @Test
    public void update() {
        SqlSession session = MyBatisUtil.getSqlSession();
        StudentMapper mapper = session.getMapper(StudentMapper.class);
        
        int num = mapper.update(6,20);
        if(num>0) {
            System.out.println("修改成功铸董!");
            session.commit();
        }else {
            System.out.println("修改失敗肴沫!");
            session.rollback();
        }
        session.close();
    }

    @Test
    public void delete() {
        SqlSession session = MyBatisUtil.getSqlSession();
        StudentMapper mapper = session.getMapper(StudentMapper.class);
        
        int num = mapper.delete(6);
        if(num>0) {
            System.out.println("刪除成功粟害!");
            session.commit();
        }else {
            System.out.println("刪除失敗颤芬!");
            session.rollback();
        }
        session.close();
    }

}

3.其他注釋:

@Results: 類似于<resultMap>
@Result: 類似于<resultMap>的子標(biāo)簽
@One: 類似于<association>
@Many: 類似于<collection>

  • 實(shí)現(xiàn)多表查詢操作:
    (1)mapper:
public interface StudentMapper {
    @Select("select *from t_student")
    @Results(value= {
            @Result(column="id",property = "id", id=true),
            @Result(column = "name",property = "name"),
            @Result(column = "age",property = "age"),
            @Result(column = "gender",property = "gender"),
            @Result(column = "cid",property = "cid"),
            @Result(column = "cid",property = "clazz",one =@One(select= "com.zlw.mapper.ClazzMapper.selAll"))
    })
    List<Student> selAll();
}
public interface ClazzMapper {
    
    @Select("select *from t_class where id = #{0}")
    Clazz selAll(int id);   
}

(2)測(cè)試:

@Test
    public void selAll() {
        SqlSession session = MyBatisUtil.getSqlSession();
        StudentMapper mapper= session.getMapper(StudentMapper.class);
        
        List<Student> list = mapper.selAll();
        for (Student student : list) {
            System.out.println(student);
        }
    }
結(jié)果

三悲幅、MyBatis的運(yùn)行原理

1.MyBatis中涉及的接口和類:

  • 類:

(1)Resources:用于加載MyBatis核心配置文件;
(2)XMLConfigBuilder:用于解析xml文件站蝠;
(3)Configuration:用于存放xml文件解析后的結(jié)果汰具;
(4)DefaultSqlSessionFactory:是 SqlSessionFactory接口的實(shí)現(xiàn)類,創(chuàng)建時(shí)需要使用Configuration 對(duì)象菱魔;
(5)DefaultSqlSession:是 SqlSession 接口的實(shí)現(xiàn)類留荔;

  • 接口:

(1)SqlSession:是MyBatis操作的核心;
(2)TransactionFactory:用于生產(chǎn)Transaction對(duì)象澜倦;
(3)Transaction:用于表示操作數(shù)據(jù)庫的事務(wù)對(duì)象聚蝶;
(4)Executor:是MyBatis的核心執(zhí)行器,類似于jdbc中的Statement藻治,常用的實(shí)現(xiàn)類是SimpleExecutor碘勉。

2.MyBatis的運(yùn)行原理:

??????當(dāng)MyBatis運(yùn)行開始時(shí),先通過Resource加載核心配置文件桩卵,再使用XMLConfigBuilder對(duì)配置文件進(jìn)行解析验靡,將解析結(jié)果封裝為Configuration對(duì)象, 然后, 使用Configuration對(duì)象構(gòu)建一個(gè)DefaultSqlSessionFactory對(duì)象, 至此, SqlSession工廠構(gòu)建完成。
??????接下來, 通過工廠對(duì)象調(diào)用 openSession 方法創(chuàng)建SqlSession 對(duì) 象 吸占;在 這 個(gè) 過 程 中 , 需 要 通 過TransactionFactory生成 Transaction 對(duì)象, 并且, 還需要?jiǎng)?chuàng)建核心執(zhí)行器 Executor 對(duì)象, 之后, 通過這些對(duì)象來創(chuàng)建DefaultSqlSession對(duì)象, 至此, SqlSession對(duì)象創(chuàng)建成功晴叨。
??????之后, 通過 SqlSession 對(duì)象執(zhí)行相應(yīng)的操作, 如果執(zhí)行成功, 調(diào)用 commit 方法提交事務(wù); 如果失敗, 調(diào)用rollback 方法事務(wù)回滾。最后, 調(diào)用 close 方法關(guān)閉session 資源矾屯。以上, 就是 MyBatis 的運(yùn)行原理兼蕊。

3.

4.

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市件蚕,隨后出現(xiàn)的幾起案子孙技,更是在濱河造成了極大的恐慌产禾,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,080評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件牵啦,死亡現(xiàn)場(chǎng)離奇詭異亚情,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)哈雏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,422評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門楞件,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人裳瘪,你說我怎么就攤上這事土浸。” “怎么了彭羹?”我有些...
    開封第一講書人閱讀 157,630評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵黄伊,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我派殷,道長(zhǎng)还最,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,554評(píng)論 1 284
  • 正文 為了忘掉前任毡惜,我火速辦了婚禮拓轻,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘虱黄。我一直安慰自己悦即,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,662評(píng)論 6 386
  • 文/花漫 我一把揭開白布橱乱。 她就那樣靜靜地躺著,像睡著了一般粱甫。 火紅的嫁衣襯著肌膚如雪泳叠。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,856評(píng)論 1 290
  • 那天茶宵,我揣著相機(jī)與錄音危纫,去河邊找鬼。 笑死乌庶,一個(gè)胖子當(dāng)著我的面吹牛种蝶,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播瞒大,決...
    沈念sama閱讀 39,014評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼螃征,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了透敌?” 一聲冷哼從身側(cè)響起盯滚,我...
    開封第一講書人閱讀 37,752評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤踢械,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后魄藕,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體内列,經(jīng)...
    沈念sama閱讀 44,212評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,541評(píng)論 2 327
  • 正文 我和宋清朗相戀三年背率,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了话瞧。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,687評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡寝姿,死狀恐怖交排,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情会油,我是刑警寧澤个粱,帶...
    沈念sama閱讀 34,347評(píng)論 4 331
  • 正文 年R本政府宣布,位于F島的核電站翻翩,受9級(jí)特大地震影響都许,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜嫂冻,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,973評(píng)論 3 315
  • 文/蒙蒙 一胶征、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧桨仿,春花似錦睛低、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,777評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至吹零,卻和暖如春罩抗,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背灿椅。 一陣腳步聲響...
    開封第一講書人閱讀 32,006評(píng)論 1 266
  • 我被黑心中介騙來泰國打工套蒂, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留贮尉,地道東北人坪它。 一個(gè)月前我還...
    沈念sama閱讀 46,406評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像吩翻,于是被迫代替她去往敵國和親婴洼。 傳聞我的和親對(duì)象是個(gè)殘疾皇子骨坑,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,576評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容