MyBatis 由浅入深(实践篇)-3

MyBatis 高级知识

  1. 开发环境

[Java环境] :jdk1.8.0_91
[开发工具] : IDEA 2016.2.5
[数据库] : MySQL 5.7.13
[项目管理工具]:Maven 3.1.1

  1. 数据库
--Table structure for tb_items
DROP TABLE IF EXISTS `tb_items`;
CREATE TABLE `tb_items` (
  `id` int(11) NOT NULL,
  `name` varchar(255) DEFAULT NULL COMMENT '商品名',
  `price` float(10,1) DEFAULT NULL COMMENT '价格',
  `detail` varchar(255) DEFAULT NULL COMMENT '商品介绍',
  `stock` int(255) DEFAULT NULL COMMENT '库存',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


-- Table structure for tb_orderdetail
DROP TABLE IF EXISTS `tb_orderdetail`;
CREATE TABLE `tb_orderdetail` (
  `id` int(11) NOT NULL,
  `order_id` int(11) NOT NULL COMMENT '订单id',
  `item_id` int(11) NOT NULL COMMENT '商品id',
  `count` int(11) DEFAULT NULL COMMENT '订单量',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- Table structure for tb_orders
DROP TABLE IF EXISTS `tb_orders`;
CREATE TABLE `tb_orders` (
  `id` int(11) NOT NULL,
  `userId` int(11) NOT NULL,
  `number` varchar(255) DEFAULT NULL COMMENT '订单号',
  `createtime` date DEFAULT NULL,
  `note` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- Table structure for tb_user
DROP TABLE IF EXISTS `tb_user`;
CREATE TABLE `tb_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(255) DEFAULT NULL,
  `sex` varchar(10) DEFAULT NULL,
  `birthday` date DEFAULT NULL,
  `address` varchar(500) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

用户表 tb_user:记录用户信息
订单表 tb_orders:记录用户所创建的订单(购买商品的订单)
订单明细表 tb_orderdetail:记录了订单的详细信息即购买商品的信息
商品表 tb_items:记录了商品信息

表之间的关联关系

实际业务中,实体与实体之间存在一定的业务关系(一对一,一对多,多对多),而关系性数据库通常是根据业务实体建表,所以上述几个关系也可以用来形容表之间的关联关系。

那么根据上述所建的 订单类业务表分析:

  1. 用户(tb_user) 和 订单 (tb_orders)
    一个用户可以有多个订单(一对多)
    一个订单只能由一个用户创建(一对一)
  2. 订单(tb_orders) 和 订单详情(tb_orderdetail)
    一个订单可以有多个订单明细(一对多)
    一个订单明细只能属于一个订单(一对一)
  3. 订单详情(tb_orderdetail) 和 商品(tb_items)
    一个订单明细只能对应一个商品(一对一)
    一个商品可以包含在多个订单明细中(一对多)
  4. 订单(tb_orders) 和 商品(tb_items)
    一个订单可以包含多个商品,同理一个商品可以被多个订单包含(多对多)

订单(tb_orders) 和 商品(tb_items)之间的这种多对多关系在很多实际业务中不利于DTO数据建模及开发维护,此时,使用订单详情(tb_orderdetail) 可以将 一个多对多关系拆分成两个一对多关系。
多对多关系拆分成一对多关系,是简化数据库实体建模常用的一种方式

复杂数据模型

在实际开发过程中,经常从多个有关联关系的表中提取出符合业务需求的数据,此时需要将返回的数据封装成一个对象,此时这个对象就需要针对表关联关系(一对一,一对多,多对多)进行设计。
如何使用 MyBatis 将这个包含关联关系的复杂对象与 sql 返回数据进行绑定,使程序运行时自动映射成该对象实例呢?

一对一查询

业务需求:查询订单列表用户及下订单的用户信息

sql 实现业务:

SELECT orders.*, USER.username, USER.sex, USER.address FROM tb_orders orders, tb_user user WHERE orders.userId = user.id

使用 resultType

1.创建实体对象(pojo)

Order.java

import cn.guan.mybatis.example2.User;

import java.util.Date;
import java.util.List;

/**
 *  订单实体类
 **/
public class Order {
    private Integer id;
    private Integer userId;
    private String number;
    private Date createtime;
    private String note;
    //用户信息
    private User user;
    //订单明细
    private List<Orderdetail> orderdetails;

    //setter and getter and toString
    ···
}

Orderdetail.java

**
 * 订单详情实体类
 **/
public class Orderdetail {
    private Integer id;
    private Integer order_id;
    private Integer itemsId;
    private Integer count;
    //明细对应的商品信息
    private Item items;

    //setter and getter and toString
    ···
}

Item.java

/**
 * 商品实体类
 **/
public class Item {
    private Integer id;
    private String name;
    private Float price;
    private String detail;
    private Integer stock;
    
    //setter and getter and toString
    ···
}

OrderCustom.java

/**
 * @Description : 通过此类映射订单和用户查询的结果,让此类继承包括 字段较多的pojo类
 */
public class OrderCustom extends Order{

    //用户属性
    private String username;
    private String sex;
    private String address;

    //setter and getter and toString
    ···
}

2.创建 Mapper 接口
OrderCustomMapper.java

/**
 *@Description : mapper 接口
 */
public interface OrderCustomMapper {
    OrderCustom findOrdersUserByResultType() throws Exception;
}

3.创建 Mapper 接口对应 *-mapper.xml 并配置 路径
ordercustom-mapper.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">

<!--namespace :命名空间,对 sql 进行分类化管理,用于隔离 sql 语句-->
<!--命名空间设置为 mapper 接口地址  -->
<mapper namespace="cn.guan.mybatis.example4.OrderCustomMapper">
    <select id="findOrdersUserByResultType" resultType="cn.guan.mybatis.example4.OrderCustom">
        SELECT orders.*, USER.username, USER.sex, USER.address FROM tb_orders orders, tb_user user WHERE orders.userId = user.id
    </select>

</mapper>

mybatis-config.xml 中配置加载路径

  <!--加载 mapper 文件 路径-->
    <mappers>
        <mapper resource="mapperDir2/ordercustom-mapper.xml" />
    </mappers>

4.测试

MyBatisMappingTest.java

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 org.junit.Before;
import org.junit.Test;

import java.io.InputStream;

/**
 * @Description : MyBatis 多种映射关系测试
 */
public class MyBatisMappingTest {

    private SqlSessionFactory sqlSessionFactory;

    @Before
    public void init() throws Exception
    {
        //创建sqlSessionFactory
        //Mybatis 配置文件
        String resource = "mybatis-config.xml";
        //得到配置文件流
        InputStream inputStream = Resources.getResourceAsStream(resource);
        //创建会话工厂,传入Mybatis的配置文件信息
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    }

    @Test
    public void testOne2One(){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //创建usermapper对象,mybatis自动生成代理对象
        OrderCustomMapper orderCustomMapper = sqlSession.getMapper(OrderCustomMapper.class);
        //调用UserMapper的方法
        OrderCustom orderCustom = null;
        try {
            orderCustom = orderCustomMapper.findOrdersUserByResultType();
            System.out.println(orderCustom);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

使用 resultMap

使用 resultMap 将查询结果中的订单信息映射到 Orders 对象中,在 orders 类中添加 User 属性,将关联查询出来的用户信息映射到 orders 对象中的 user 属性中。

1.修改 ordercustom-mapper.xml
定义 resultMap

<?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 :命名空间,对 sql 进行分类化管理,用于隔离 sql 语句-->
<!--命名空间设置为 mapper 接口地址  -->
<mapper namespace="cn.guan.mybatis.example4.OrderCustomMapper">

    <!--定义查询订单关联查询用户信息的resultMap
          将整个查询结果映射到cn.guan.mybatis.example4.Order
      -->
    <resultMap id="OrderUserResultMap" type="cn.guan.mybatis.example4.Order">
        <!--配置映射的订单信息-->
        <!--id表示查询结果中的唯一标识  在这里是订单的唯一标识  如果是由多列组成的唯一标识,那么就需要配置多个id
        column:id 是订单信息中的唯一标识列
        property:id 是订单信息唯一标识列所映射到orders中的id属性
        最终resultMap对column和property做一个映射关系(对应关系)
        -->
        <id column="id" property="id"/>
        <result column="userId" property="userId"/>
        <result column="number" property="number"/>
        <result column="createtime" property="createtime"/>
        <result column="note" property="note"/>
        <!--配置映射的关联用户信息
                  association 用于映射关联查询单个对象的信息
                  property  将要关联查询的用户信息映射到 orders中的属性中去
              -->
        <association property="user" javaType="cn.guan.mybatis.example2.User">
            <!--id 关联用户信息的唯一标识
                column: 指定唯一标识用户的信息
                property:映射到user的那个属性
            -->
            <id column="id" property="id"/>
            <result column="username" property="username"/>
            <result column="sex" property="sex"/>
            <result column="address" property="address"/>
            <result column="birthday" property="birthday"/>
        </association>
    </resultMap>
    
    <select id="findOrdersUserByResultMap" parameterType="int" resultMap="OrderUserResultMap">
        SELECT orders.*, USER.username, USER.sex, USER.address FROM tb_orders orders, tb_user user WHERE orders.userId = user.id
    </select>
</mapper>

2.新增一个接口
OrderCustomMapper.java

/**
 *@Description : mapper 接口
 */
public interface OrderCustomMapper {
    OrderCustom findOrdersUserByResultType() throws Exception;
    List<Order> findOrdersUserByResultMap() throws Exception;
}

3.测试

    
    ···

    @Test
    public void testOne2OneByResultMap(){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //创建usermapper对象,mybatis自动生成代理对象
        OrderCustomMapper orderCustomMapper = sqlSession.getMapper(OrderCustomMapper.class);
        //调用UserMapper的方法
        List<Order> orderList = null;
        try {
            orderList = orderCustomMapper.findOrdersUserByResultMap();
            System.out.println(orderList);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

一对多查询

需求:查询订单及订单明细

使用sql 实现业务:

SELECT c.username,c.sex,c.address,a.*,b.id as orderdetailId,b.item_id as itemId,b.count 
FROM tb_orders a 
LEFT JOIN tb_orderdetail b on a.id = b.order_id
LEFT JOIN tb_user c on a.userId = c.id;

使用 resultType

分析:
如果使用 resultType 将查询结果映射到 pojo 中,订单信息就会重复。

使用 resultMap

预期:
对 order 的映射不能出现重复记录。
在 Order 中添加 一个 Orderdetail 的 List 属性,将查询结果中的订单信息映射到 Order 中,订单明细信息映射到 List<Orderdetail> 中,这样订单信息就不会重复。

1.修改 ordercustom-mapper.xml
定义 resultMap

<?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 :命名空间,对 sql 进行分类化管理,用于隔离 sql 语句-->
<!--命名空间设置为 mapper 接口地址  -->
<mapper namespace="cn.guan.mybatis.example4.OrderCustomMapper">

    <!--定义查询订单关联查询用户信息的resultMap
          将整个查询结果映射到cn.guan.mybatis.example4.Order
      -->
    <resultMap id="OrderUserResultMap" type="cn.guan.mybatis.example4.Order">
        <!--配置映射的订单信息-->
        <!--id表示查询结果中的唯一标识  在这里是订单的唯一标识  如果是由多列组成的唯一标识,那么就需要配置多个id
        column:id 是订单信息中的唯一标识列
        property:id 是订单信息唯一标识列所映射到orders中的id属性
        最终resultMap对column和property做一个映射关系(对应关系)
        -->
        <id column="id" property="id"/>
        <result column="userId" property="userId"/>
        <result column="number" property="number"/>
        <result column="createtime" property="createtime"/>
        <result column="note" property="note"/>
        <!--配置映射的关联用户信息
                  association 用于映射关联查询单个对象的信息
                  property  将要关联查询的用户信息映射到 orders中的属性中去
              -->
        <association property="user" javaType="cn.guan.mybatis.example2.User">
            <!--id 关联用户信息的唯一标识
                column: 指定唯一标识用户的信息
                property:映射到user的那个属性
            -->
            <id column="id" property="id"/>
            <result column="username" property="username"/>
            <result column="sex" property="sex"/>
            <result column="address" property="address"/>
            <result column="birthday" property="birthday"/>
        </association>
    </resultMap>

    <!--定义查询订单关联查询用户信息的resultMap
          将整个查询结果映射到cn.guan.mybatis.example4.Order
      -->
    <resultMap id="OrderAndOrderdetailsResultMap" type="cn.guan.mybatis.example4.Order" extends="OrderUserResultMap">
        <!-- 订单信息 -->
        <!-- 用户信息 -->
        <!-- 使用extends继承,不用在中配置订单信息和用户信息的映射 -->
        <!-- 订单明细信息
        一个订单关联查询出了多条明细,要使用collection进行映射
        collection:对关联查询到多条记录映射到集合对象中
        property:将关联查询到多条记录映射到cn.zhisheng.mybatis.po.Orders哪个属性
        ofType:指定映射到list集合属性中pojo的类型
         -->
        <collection property="orderdetails" ofType="cn.guan.mybatis.example4.Orderdetail">
            <!-- id:订单明细唯 一标识
       property:要将订单明细的唯 一标识 映射到cn.zhisheng.mybatis.po.Orderdetail的哪个属性-->
            <id column="orderdetailId" property="id"/>
            <result column="itemId" property="itemsId"/>
            <result column="count" property="count"/>
            <result column="orderId" property="order_id"/>
        </collection>
    </resultMap>
    
    <select id="findAllOrdersAndOrderdetails" parameterType="int" resultMap="OrderAndOrderdetailsResultMap">
       SELECT c.username,c.sex,c.address,a.*,b.id as orderdetailId,b.order_id as orderId ,b.item_id as itemId,b.count as count
        FROM tb_orders a
        LEFT JOIN tb_orderdetail b on a.id = b.order_id
        LEFT JOIN tb_user c on a.userId = c.id;
    </select>

</mapper>

2.新增一个接口

OrderCustomMapper.java

/**
 *@Description : mapper 接口
 */
public interface OrderCustomMapper {
    OrderCustom findOrdersUserByResultType() throws Exception;
    List<Order> findOrdersUserByResultMap() throws Exception;
    List<Order> findAllOrdersAndOrderdetails() throws Exception;
}

3.测试

    
    ···

    @Test
    public void testOne2MoreByResultMap(){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //创建usermapper对象,mybatis自动生成代理对象
        OrderCustomMapper orderCustomMapper = sqlSession.getMapper(OrderCustomMapper.class);
        //调用UserMapper的方法
        List<Order> orderList = null;
        try {
            orderList = orderCustomMapper.findOrdersUserByResultMap();
            System.out.println(orderList);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

多对多查询

需求:查询用户及用户购买的商品信息

sql 实现业务:

SELECT c.username,c.sex,c.address,a.*,b.id as orderdetailId,b.order_id as orderId ,b.item_id as itemId,b.count as count,d.`name` as itemName,d.price as itemPrice,d.detail as itemDetail
FROM tb_orders a 
LEFT JOIN tb_orderdetail b on a.id = b.order_id
LEFT JOIN tb_user c on a.userId = c.id
LEFT JOIN tb_items d on b.item_id = d.id;

映射思路:
用户信息映射到 User 中,
在 User 中添加 List<Order> 属性,用于映射用户下的订单
Order 中的 List<Orderdetail> 用于映射 Order 对应的订单明细
Orderdetail 中添加 Item 属性用于映射明细对应商品的信息

1.pojo 类

User.java


public class User {
    //user 基本属性
    ···
    private List<Order> orders;
    
    //setter and getter and toString
    ···
}

Order.java

public class Order {
    //Order 基本属性
    ···
    //订单明细
        private List<Orderdetail> orderdetails;
    
        //setter and getter and toString
        ···
}

Orderdetail.java

public class Orderdetail {
    //Orderdetail 基本属性
    ···
    //明细对应的商品信息
        private Item items;
    
        //setter and getter and toString
        ···
}

2.映射文件

userorders-mapper.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">

<!--namespace :命名空间,对 sql 进行分类化管理,用于隔离 sql 语句-->
<!--命名空间设置为 mapper 接口地址  -->
<mapper namespace="cn.guan.mybatis.example4.UserOrdersMapper">
    <!--定义查询用户及用户购买商品信息的 resultMap-->
    <resultMap id="UserAndOrdersResultMap" type="cn.guan.mybatis.example4.User">
        <!--用户信息-->
        <id column="id" property="id"/>
        <result column="username" property="username"/>
        <result column="sex" property="sex"/>
        <result column="address" property="address"/>
        <result column="birthday" property="birthday"/>

        <!--订单信息
            一个用户对应多个订单,使用collection映射
        -->
        <collection property="orders" ofType="cn.guan.mybatis.example4.Order">
            <id column="id" property="id"/>
            <result column="userId" property="userId"/>
            <result column="number" property="number"/>
            <result column="createtime" property="createtime"/>
            <result column="note" property="note"/>
            <!-- 订单明细
               一个订单包括 多个明细
           -->
            <collection property="orderdetails" ofType="cn.guan.mybatis.example4.Orderdetail">
                <id column="orderdetailId" property="id"/>
                <result column="itemId" property="itemsId"/>
                <result column="count" property="count"/>
                <result column="orderId" property="order_id"/>

                <!-- 商品信息
                     一个订单明细对应一个商品
                -->
                <association property="items" javaType="cn.guan.mybatis.example4.Item">
                    <id column="itemId" property="id"/>
                    <result column="itemName" property="name"/>
                    <result column="itemPrice" property="price"/>
                    <result column="itemDetail" property="detail"/>
                </association>
            </collection>

        </collection>


    </resultMap>
    
    <select id="findUserAndOrdersByUserId" parameterType="int" resultMap="UserAndOrdersResultMap">
       SELECT c.id,c.username,c.sex,c.address,a.*,b.id as orderdetailId,b.order_id as orderId ,b.item_id as itemId,b.count as count,d.`name` as itemName,d.price as itemPrice,d.detail as itemDetail
        FROM tb_orders a
        LEFT JOIN tb_orderdetail b on a.id = b.order_id
        LEFT JOIN tb_user c on a.userId = c.id
        LEFT JOIN tb_items d on b.item_id = d.id
        where c.id = #{value};
    </select>

</mapper>

加载映射文件:
mybatis-config.xml

<?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">
            <!-- 使用jdbc事务管理,事务由 Mybatis 控制-->
            <transactionManager type="JDBC" />
            <!-- 数据库连接池,由Mybatis管理,db_mybatis,Mysql用户名root,123456 -->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver" />
                <property name="url" value="jdbc:mysql://localhost:3306/db_mybatis?characterEncoding=utf-8" />
                <property name="username" value="root" />
                <property name="password" value="123456" />
            </dataSource>
        </environment>
    </environments>
    <!--加载 mapper 文件 路径-->
    <mappers>
        ···
        <mapper resource="mapperDir2/userorders-mapper.xml" />
    </mappers>
</configuration>

2.接口定义
UserOrdersMapper.java

import java.util.List;

/用户及所下订单信息查询接口

public interface UserOrdersMapper {
    List<User> findUserAndOrdersByUserId(int userid) throws  Exception;
}

3.测试


    ···

    @Test
    public void testMore2MoreByResultMap(){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //创建usermapper对象,mybatis自动生成代理对象
        UserOrdersMapper userOrdersMapper = sqlSession.getMapper(UserOrdersMapper.class);
        //调用UserMapper的方法
        List<User> users = null;
        try {
            users = userOrdersMapper.findUserAndOrdersByUserId(1);
            System.out.println(users);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

结果集映射总结

  1. resultType
    按照sql 查询结果的字段名(column)与 resultType 定义的 pojo 类的属性名一对一映射,完成映射。
    通常用于简单的不包含表连接关系的结果映射。

  2. resultMap
    需要完成一对一,一对多,多对多这些特殊的包含表连接关系的复杂结果映射。

  3. association
    将一对一的关联查询信息映射到 pojo 中,使用 resultType 无法完成成员属性为对象的自动映射。
    例:订单 pojo 中包含一个 User 对象,使用 resultType 无法将 sql 的查询结果中的 User 信息自动映射到 User 成员变量中。

  4. collection
    将一对多的关联查询信息映射到一个 List 集合中

使用 resultMap 能对复杂的查询结果集进行面向对象设计,而且可以通过成员变量的形式,大大减少 pojo 类的创建,同时也可以减少冗余信息的存储,方便对结果集进行遍历查询。


参考链接:
http://blog.csdn.net/column/details/13905.html

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,835评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,598评论 1 295
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,569评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,159评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,533评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,710评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,923评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,674评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,421评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,622评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,115评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,428评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,114评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,097评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,875评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,753评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,649评论 2 271

推荐阅读更多精彩内容