SpringBoot基礎(chǔ)系列-整合MyBatis


原創(chuàng)文章琴昆,轉(zhuǎn)載請標(biāo)注出處:《SpringBoot基礎(chǔ)系列-整合MyBatis》


一、步驟

1.1 第一步:添加必要的jar包

<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>1.3.1</version>
</dependency>

1.2 第二步:添加必要的配置

application.properties

#配置數(shù)據(jù)源
spring.datasource.url = jdbc:h2:mem:dbtest
spring.datasource.username = sa
spring.datasource.password = sa
spring.datasource.driverClassName =org.h2.Driver

1.3 第三步:添加配置類

// 該配置類用于配置自動(dòng)掃描器八千,用于掃描自定義的mapper接口,MyBatis會(huì)針對這些接口生成代理來調(diào)用對應(yīng)的XMl中的SQL
@Configuration
@MapperScan("com.example.springbootdemo.mapper")
public class MyBatisConfig {
}

這個(gè)注解必須手動(dòng)配置是因?yàn)閙apper接口的位置完全就是用戶自定義的,自動(dòng)配置的時(shí)候也不可能找到還不存在的位置。

1.4 第四步:定義實(shí)體類型

@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
@EqualsAndHashCode
@Builder
@ApiModel("書籍模型")
public class Book {
    @ApiModelProperty(value = "書籍ID", notes = "書籍ID",example = "1")
    private Integer bookId;
    @ApiModelProperty(value = "書籍頁數(shù)", notes = "書籍頁數(shù)",example = "100")
    private Integer pageNum;
    @ApiModelProperty(value = "書籍名稱", notes = "書籍名稱",example = "Java編程思想")
    private String bookName;
    @ApiModelProperty(value = "書籍類型", notes = "書籍類型",hidden = false)
    private BookType BookType;
    @ApiModelProperty(value = "書籍簡介")
    private String bookDesc;
    @ApiModelProperty(value = "書籍價(jià)格")
    private Double bookPrice;
    @ApiModelProperty(value = "創(chuàng)建時(shí)間",hidden = true)
    private LocalDateTime createTime;
    @ApiModelProperty(value = "修改時(shí)間",hidden = true)
    private LocalDateTime modifyTime;
}

還有一個(gè)枚舉類型

public enum BookType {
    TECHNOLOGY,//技術(shù)
    LITERARY,//文學(xué)
    HISTORY//歷史
    ;
}

實(shí)體類中使用了swagger2和Lombok中的注解瘫证,需要添加對應(yīng)的jar包

1.5 第五步:定義mapper接口

public interface BookRepository {
    int addBook(Book book);
    int updateBook(Book book);
    int deleteBook(int id);
    Book getBook(int id);
    List<Book> getBooks(Book book);
}

1.6 第六步:定義mapper配置

<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.springbootdemo.mapper.BookRepository">
    <insert id="addBook" parameterType="Book">
        INSERT INTO BOOK(
        <if test="pageNum != null">
            PAGE_NUM,
        </if>
        <if test="bookType != null">
            BOOK_TYPE,
        </if>
        <if test="bookName != null">
            BOOK_NAME,
        </if>
        <if test="bookDesc != null">
            BOOK_DESC,
        </if>
        <if test="bookPrice != null">
            BOOK_PRICE,
        </if>
            CREATE_TIME,
            MODIFY_TIME)
        VALUES (
        <if test="pageNum != null">
            #{pageNum},
        </if>
        <if test="bookType != null">
            #{bookType},
        </if>
        <if test="bookName != null">
            #{bookName},
        </if>
        <if test="bookDesc != null">
            #{bookDesc},
        </if>
        <if test="bookPrice != null">
            #{bookPrice},
        </if>
        sysdate,sysdate)
    </insert>
    <update id="updateBook" parameterType="Book">
        UPDATE BOOK SET
        <if test="pageNum != null">
            PAGE_NUM = #{pageNum},
        </if>
        <if test="bookType != null">
            BOOK_TYPE = #{bookType},
        </if>
        <if test="bookDesc != null">
            BOOK_DESC = #{bookDesc},
        </if>
        <if test="bookPrice != null">
            BOOK_PRICE = #{bookPrice},
        </if>
        <if test="bookName != null">
            BOOK_NAME = #{bookName},
        </if>
        MODIFY_TIME=sysdate
        WHERE 1=1
        <if test="bookId != null">
            and BOOK_ID = #{bookId}
        </if>
    </update>
    <delete id="deleteBook" parameterType="int">
        delete from BOOK where BOOK_id=#{bookId}
    </delete>
    <select id="getBook" parameterType="int" resultMap="bookResultMap">
        select * from BOOK where BOOK_ID=#{bookId}
    </select>
    <select id="getBooks" resultMap="bookResultMap">
        select * from BOOK WHERE 1=1
        <if test="bookId != null">
            and BOOK_ID = #{bookId}
        </if>
        <if test="pageNum != null">
            and PAGE_NUM = #{pageNum}
        </if>
        <if test="bookType != null">
            and BOOK_TYPE = #{bookType}
        </if>
        <if test="bookDesc != null">
            and BOOK_DESC = #{bookDesc}
        </if>
        <if test="bookPrice != null">
            and BOOK_PRICE = #{bookPrice}
        </if>
        <if test="bookName != null">
            and BOOK_NAME = #{bookName}
        </if>
    </select>
    <resultMap id="bookResultMap" type="Book">
        <id column="BOOK_ID" property="bookId"/>
        <result column="PAGE_NUM" property="pageNum"/>
        <result column="BOOK_NAME" property="bookName"/>
        <result column="BOOK_TYPE" property="bookType"/>
        <result column="BOOK_DESC" property="bookDesc"/>
        <result column="BOOK_PRICE" property="bookPrice"/>
        <result column="CREATE_TIME" property="createTime"/>
        <result column="MODIFY_TIME" property="modifyTime"/>
    </resultMap>
</mapper>

在這個(gè)配置文件中我們使用了MyBatis的動(dòng)態(tài)SQL和參數(shù)映射

1.7 第七步:再次添加必要的配置

application.properties

#配置Xml配置的位置
mybatis.mapper-locations=classpath*:/mapper/*.xml
#配置實(shí)體類型別名
mybatis.type-aliases-package=com.example.springbootdemo.entity

這里的兩個(gè)配置也和之前的掃描器注解一樣咐容,都是自動(dòng)配置時(shí)未知的舆逃,需要手動(dòng)配置,當(dāng)然可能會(huì)存在默認(rèn)的位置戳粒,但是一旦我們自定義了路狮,就必須手動(dòng)添加配置。

1.8 第八步:定義service和controller

@Service
@Log4j2
public class BookService {
    
    @Autowired
    private BookRepository bookRepository;
    
    public ResponseEntity<Book> addBook(final Book book) {
        int num = bookRepository.addBook(book);
        return ResponseEntity.ok(book);
    }
    
    public ResponseEntity<Integer> updateBook(final Book book){
        return ResponseEntity.ok(bookRepository.updateBook(book));
    }
    
    public ResponseEntity<Integer> deleteBook(final int bookId){
        return ResponseEntity.ok(bookRepository.deleteBook(bookId));
    }
    
    public ResponseEntity<Book> getBook(final int bookId) {
        Book book = bookRepository.getBook(bookId);
        return ResponseEntity.ok(book);
    }
    
    public ResponseEntity<List<Book>> getBooks(final Book book){
        return ResponseEntity.ok(bookRepository.getBooks(book));
    }
    
}
@RestController
@RequestMapping("/book")
@Api(description = "書籍接口")
@Log4j2
public class BookApi {
    @Autowired
    private BookService bookService;
    
    @RequestMapping(value = "/addBook", method = RequestMethod.PUT)
    @ApiOperation(value = "添加書籍", notes = "添加一本新書籍", httpMethod = "PUT")
    public ResponseEntity<Book> addBook(final Book book){
        return bookService.addBook(book);
    }
    
    @RequestMapping(value = "/updateBook", method = RequestMethod.POST)
    @ApiOperation(value = "更新書籍", notes = "根據(jù)條件更新書籍信息", httpMethod = "POST")
    public ResponseEntity<Integer> updateBook(final Book book){
        return bookService.updateBook(book);
    }
    
    @RequestMapping(value = "/deleteBook", method = RequestMethod.DELETE)
    @ApiOperation(value = "獲取一本書籍", notes = "根據(jù)ID獲取書籍", httpMethod = "DELETE")
    public ResponseEntity<Integer> deleteBook(final int bookId){
        return bookService.deleteBook(bookId);
    }
    
    @RequestMapping(value = "/getBook", method = RequestMethod.GET)
    @ApiOperation(value = "獲取一本書籍", notes = "根據(jù)ID獲取書籍", httpMethod = "GET")
    public ResponseEntity<Book> getBook(final int bookId){
        return bookService.getBook(bookId);
    }
    
    @RequestMapping(value = "/getBooks", method = RequestMethod.GET)
    @ApiOperation(value = "獲取書籍", notes = "根據(jù)條件獲取書籍", httpMethod = "GET")
    public ResponseEntity<List<Book>> getBooks(final Book book){
        return bookService.getBooks(book);
    }
}

這里使用了swagger2的注解

至此設(shè)置完畢蔚约。

1.9 第九步:瀏覽器訪問

http://localhost:8080/swagger-ui.html

通過swagger界面可以看到我們定義的接口奄妨。

二、高級(jí)功能

2.1 分頁(兩種苹祟,簡單分頁RowBounds和攔截器分頁砸抛,插件)

2.1.1 RowBounds分頁

使用RowBounds分頁適用于小數(shù)據(jù)量的分頁查詢

使用方式是在查詢的Mapper接口上添加RowBounds參數(shù)即可,service傳參時(shí)需要指定其兩個(gè)屬性苔咪,當(dāng)前頁和每頁數(shù)锰悼。

  1. 定義分頁模型
@Data
@Builder
@ToString
@EqualsAndHashCode
@NoArgsConstructor
@AllArgsConstructor
public class MyPage<T> {
    private Integer pageId;//當(dāng)前頁
    private Integer pageNum;//總頁數(shù)
    private Integer pageSize;//每頁數(shù)
    private Integer totalNum;//總數(shù)目
    private List<T> body;//分頁結(jié)果
    private Integer srartIndex;//開始索引
    private boolean isMore;//是否有下一頁
}
  1. 定義mapper
public interface BookRepository {
    // 省略多余內(nèi)容
    int count(Book book);
    List<Book> getBooks(Book book, RowBounds rowBounds);
}

BookRepository.xml

<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.springbootdemo.mapper.BookRepository">
   
    <!--省略多余內(nèi)容-->
    
    <select id="getBooks" resultMap="bookResultMap">
        select * from BOOK WHERE 1=1
        <if test="bookId != null">
            and BOOK_ID = #{bookId}
        </if>
        <if test="pageNum != null">
            and PAGE_NUM = #{pageNum}
        </if>
        <if test="bookType != null">
            and BOOK_TYPE = #{bookType}
        </if>
        <if test="bookDesc != null">
            and BOOK_DESC = #{bookDesc}
        </if>
        <if test="bookPrice != null">
            and BOOK_PRICE = #{bookPrice}
        </if>
        <if test="bookName != null">
            and BOOK_NAME = #{bookName}
        </if>
    </select>
    <select id="count" resultType="int">
        select count(1) from BOOK WHERE 1=1
        <if test="bookId != null">
            and BOOK_ID = #{bookId}
        </if>
        <if test="pageNum != null">
            and PAGE_NUM = #{pageNum}
        </if>
        <if test="bookType != null">
            and BOOK_TYPE = #{bookType}
        </if>
        <if test="bookDesc != null">
            and BOOK_DESC = #{bookDesc}
        </if>
        <if test="bookPrice != null">
            and BOOK_PRICE = #{bookPrice}
        </if>
        <if test="bookName != null">
            and BOOK_NAME = #{bookName}
        </if>
    </select>
    <resultMap id="bookResultMap" type="Book">
        <id column="BOOK_ID" property="bookId"/>
        <result column="PAGE_NUM" property="pageNum"/>
        <result column="BOOK_NAME" property="bookName"/>
        <result column="BOOK_TYPE" property="bookType"/>
        <result column="BOOK_DESC" property="bookDesc"/>
        <result column="BOOK_PRICE" property="bookPrice"/>
        <result column="CREATE_TIME" property="createTime"/>
        <result column="MODIFY_TIME" property="modifyTime"/>
    </resultMap>
</mapper>

3.定義service

@Service
@Log4j2
public class BookService {
    
    @Autowired
    private BookRepository bookRepository;
    // 省略多余內(nèi)容
    // 使用RowBounds實(shí)現(xiàn)分頁
    public ResponseEntity<MyPage<Book>> getBooksByRowBounds(int pageId,int pageSize){
        MyPage<Book> myPage = new MyPage<>();
        myPage.setPageId(pageId);
        myPage.setPageSize(pageSize);
        List<Book> books = bookRepository.getBooks(Book.builder().build(), new RowBounds(pageId,pageSize));
        int totalNum = bookRepository.count(Book.builder().build());
        myPage.setBody(books);
        myPage.setTotalNum(totalNum);
        return ResponseEntity.ok(myPage);
    }
}
  1. 定義controller
@RestController
@RequestMapping("/book")
@Api(description = "書籍接口")
@Log4j2
public class BookApi {
   
    @Autowired
    private BookService bookService;
    // 省略多余內(nèi)容
    @RequestMapping(value = "/getBooksPageByRowBounds", method = RequestMethod.GET)
    @ApiOperation(value = "分頁獲取書籍", notes = "通過RowBounds分頁獲取書籍", httpMethod = "GET")
    public ResponseEntity<PageInfo<Book>> getBooksPageByRowBounds(final int pageId, final int pageNum){
        return bookService.getBooksByRowBounds(pageId, pageNum);
    }
    
}

2.1.2 攔截器分頁

當(dāng)面對大數(shù)據(jù)量的分頁時(shí),RowBounds就力不從心的团赏,這時(shí)需要我們使用分頁攔截器實(shí)現(xiàn)分頁箕般。

這里其實(shí)可以直接使用插件PageHelper,其就是以攔截器技術(shù)實(shí)現(xiàn)的分頁查詢插件舔清。

具體使用方法見SpringBoot整合MyBatis分頁插件PageHelper

2.2 自定義類型轉(zhuǎn)換器(枚舉轉(zhuǎn)換器)

public class BookTypeEnumHandler extends BaseTypeHandler<BookType> {
    /**
     * 用于定義設(shè)置參數(shù)時(shí)丝里,該如何把Java類型的參數(shù)轉(zhuǎn)換為對應(yīng)的數(shù)據(jù)庫類型
     */
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, BookType parameter, JdbcType jdbcType) throws SQLException {
        int j = 0;
        for (BookType bookType : BookType.values()){
            if(bookType.equals(parameter)){
                ps.setString(i, j +"");
                return;
            }
            j++;
        }
    }
    /**
     * 用于定義通過字段名稱獲取字段數(shù)據(jù)時(shí)曲初,如何把數(shù)據(jù)庫類型轉(zhuǎn)換為對應(yīng)的Java類型
     */
    @Override
    public BookType getNullableResult(ResultSet rs, String columnName) throws SQLException {
        int j = Integer.valueOf(rs.getString(columnName));
        if(j >= BookType.values().length) {
            return null;
        }
        int i = 0;
        for(BookType bookType:BookType.values()){
            if(j == i){
                return bookType;
            }
            i++;
        }
        return null;
    }
    /**
     * 用于定義通過字段索引獲取字段數(shù)據(jù)時(shí),如何把數(shù)據(jù)庫類型轉(zhuǎn)換為對應(yīng)的Java類型
     */
    @Override
    public BookType getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        return null;
    }
    /**
     * 用定義調(diào)用存儲(chǔ)過程后杯聚,如何把數(shù)據(jù)庫類型轉(zhuǎn)換為對應(yīng)的Java類型
     */
    @Override
    public BookType getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        return null;
    }
}

2.3 使用@Mapper(不常用臼婆,可不看)

注意:使用@Mapper注解的時(shí)候是不需要添加xml配置Mapper文件的,SQL腳本在接口方法的注解內(nèi)部定義

  1. 第一步:定義實(shí)體類
@Data
@Builder
@ToString
@EqualsAndHashCode
@NoArgsConstructor
@AllArgsConstructor
public class Tree {
    private Integer treeId;
    private String treeName;
    private Integer treeAge;
    private Double treeHight;
    private TreeType treeType;
    private TreeState treeState;
    private String treeDesc;
}
  1. 第二步:定義持久層
@Mapper
public interface TreeRepository {
    
    @Insert("INSERT INTO TREE (TREE_NAME,TREE_AGE,TREE_HIGHT,TREE_TYPE,TREE_STATE,TREE_DESC) VALUES (#{treeName},#{treeAge},#{treeHight},#{treeType},#{treeState},#{treeDesc}) ")
    int addTree(Tree tree);
    
    // 此處treeState是一個(gè)枚舉幌绍,此處執(zhí)行一直報(bào)錯(cuò)
    @Update("UPDATE TREE SET TREE_STATE=#{treeState} WHERE TREE_ID=#{treeId}")
    int updateState(final int treeId, final TreeState treeState);
    
    @Delete("DELETE FROM TREE WHERE TREE_ID=#{treeId}")
    int deleteTree(final int treeId);
    
    @Results({
            @Result(id = true, column = "TREE_ID",property = "treeId"),
            @Result(column = "TREE_NAME",property = "treeName"),
            @Result(column = "TREE_AGE", property = "treeAge"),
            @Result(column = "TREE_HIGHT",property = "treeHight"),
            @Result(column = "TREE_TYPE",property = "treeType",typeHandler = EnumOrdinalTypeHandler.class),
            @Result(column = "TREE_STATE",property = "treeState",typeHandler = EnumOrdinalTypeHandler.class),
            @Result(column = "TREE_DESC", property = "treeDesc")
    })
    @Select("SELECT * FROM TREE WHERE TREE_ID=#{treeId}")
    Tree getTree(final int treeId);
    
    @Results({
            @Result(id = true, column = "TREE_ID",property = "treeId"),
            @Result(column = "TREE_NAME",property = "treeName"),
            @Result(column = "TREE_AGE", property = "treeAge"),
            @Result(column = "TREE_HIGHT",property = "treeHight"),
            @Result(column = "TREE_TYPE",property = "treeType",typeHandler = EnumOrdinalTypeHandler.class),
            @Result(column = "TREE_STATE",property = "treeState",typeHandler = EnumOrdinalTypeHandler.class),
            @Result(column = "TREE_DESC", property = "treeDesc")
    })
    @Select("SELECT * FROM TREE")
    List<Tree> getTrees(RowBounds rowBounds);
}

注意:重點(diǎn)就在這個(gè)接口中颁褂,我們添加接口注解@Mapper,表示這是一個(gè)持久層Mapper,它的實(shí)例化依靠SpringBoot自動(dòng)配置完成傀广。
在接口方法上直接添加對應(yīng)的執(zhí)行注解颁独,在注解中直接定義SQL,這種SQL仍然可以使用表達(dá)式#{}來獲取參數(shù)的值伪冰。
注意@Result注解中定義的兩個(gè)關(guān)于枚舉的類型處理器EnumOrdinalTypeHandler誓酒,其實(shí)其為MyBatis內(nèi)部自帶的兩種枚舉處理器之一,用于存儲(chǔ)枚舉序號(hào)贮聂,還有一個(gè)EnumTypeHandler用于存儲(chǔ)枚舉名稱靠柑。

  1. 第三步:定義service和controller
@Service
@Log4j2
public class TreeService {
    
    @Autowired
    private TreeRepository treeRepository;
    
    public ResponseEntity<Tree> addTree(final Tree tree){
        treeRepository.addTree(tree);
        return ResponseEntity.ok(tree);
    }
    
    public ResponseEntity<Tree> updateTree(final int treeId, final TreeState treeState){
        treeRepository.updateState(treeId,treeState);
        return ResponseEntity.ok(Tree.builder().treeId(treeId).treeState(treeState).build());
    }
    
    public ResponseEntity<Integer> deleteTree(final int treeId){
        return ResponseEntity.ok(treeRepository.deleteTree(treeId));
    }
    
    public ResponseEntity<Tree> getTree(final int treeId){
        return ResponseEntity.ok(treeRepository.getTree(treeId));
    }
   
    public ResponseEntity<MyPage<Tree>> getTrees(final int pageId,final int pageSize){
        List<Tree> trees = treeRepository.getTrees(new RowBounds(pageId,pageSize));
        MyPage<Tree> treeMyPage = new MyPage<>();
        treeMyPage.setPageId(pageId);
        treeMyPage.setPageSize(pageSize);
        treeMyPage.setBody(trees);
        return ResponseEntity.ok(treeMyPage);
    }
}
@RestController
@RequestMapping("/tree")
@Api(description = "樹木接口")
public class TreeApi {
   
    @Autowired
    private TreeService treeService;
    
    @RequestMapping(value = "/addTree",method = RequestMethod.PUT)
    @ApiOperation(value = "添加樹木",notes = "添加新樹木",httpMethod = "PUT")
    public ResponseEntity<Tree> addTree(final Tree tree){
        return treeService.addTree(tree);
    }
    
    @RequestMapping(value = "/updateTree",method = RequestMethod.POST)
    @ApiOperation(value = "更新狀態(tài)",notes = "修改樹木狀態(tài)",httpMethod = "POST")
    public ResponseEntity<Tree> updateTree(final int treeId,final TreeState treeState){
        return treeService.updateTree(treeId,treeState);
    }
    
    @ApiOperation(value = "獲取樹木",notes = "根據(jù)ID獲取一棵樹",httpMethod = "GET")
    @RequestMapping(value = "/getTree",method = RequestMethod.GET)
    public ResponseEntity<Tree> getTree(final int treeId){
        return treeService.getTree(treeId);
    }
}

注意:這個(gè)例子中更新狀態(tài)的時(shí)候還是無法成功,這個(gè)狀態(tài)是枚舉值吓懈。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末歼冰,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子骄瓣,更是在濱河造成了極大的恐慌停巷,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件榕栏,死亡現(xiàn)場離奇詭異,居然都是意外死亡蕾各,警方通過查閱死者的電腦和手機(jī)扒磁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來式曲,“玉大人妨托,你說我怎么就攤上這事×咝撸” “怎么了兰伤?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長钧排。 經(jīng)常有香客問我敦腔,道長,這世上最難降的妖魔是什么恨溜? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任符衔,我火速辦了婚禮找前,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘判族。我一直安慰自己躺盛,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布形帮。 她就那樣靜靜地躺著槽惫,像睡著了一般。 火紅的嫁衣襯著肌膚如雪辩撑。 梳的紋絲不亂的頭發(fā)上躯枢,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天,我揣著相機(jī)與錄音槐臀,去河邊找鬼锄蹂。 笑死,一個(gè)胖子當(dāng)著我的面吹牛水慨,可吹牛的內(nèi)容都是我干的得糜。 我是一名探鬼主播,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼晰洒,長吁一口氣:“原來是場噩夢啊……” “哼朝抖!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起谍珊,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤治宣,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后砌滞,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體侮邀,經(jīng)...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年贝润,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了绊茧。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,722評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡打掘,死狀恐怖华畏,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情尊蚁,我是刑警寧澤亡笑,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站横朋,受9級(jí)特大地震影響仑乌,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一绝骚、第九天 我趴在偏房一處隱蔽的房頂上張望耐版。 院中可真熱鬧,春花似錦压汪、人聲如沸粪牲。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽腺阳。三九已至,卻和暖如春穿香,著一層夾襖步出監(jiān)牢的瞬間亭引,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工皮获, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留焙蚓,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓洒宝,卻偏偏與公主長得像购公,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子雁歌,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,614評論 2 353