spring data jpa 實戰(zhàn)之增刪改查(干貨蛤铜!你想要的查詢!)

熟悉了mybatis的靈活骡送,可能你對他的動態(tài)查詢很喜歡昂羡,表示各種sql都能勝任。初步接觸jpa時摔踱,你會各種吐槽虐先,不如mybatis來的方便。其實jpa也能幫你完成你的各種需求派敷,至于編寫的復(fù)雜度蛹批,那可能就仁者見仁智者見智了撰洗。習(xí)慣了,其實也一樣了腐芍。

代碼放github和碼云了:spring-data/github spring-data/碼云

save操作(含merge操作差导,即update也在save里)
  • save方法會預(yù)檢查該entity是否持久化,isNew會判斷該對象的Id類型 是否實現(xiàn)Persistable或EntityInformation進(jìn)行重寫isNew方法猪勇,如果Id是Number類型设褐,直接判斷value==0 true 執(zhí)行entityManager.persist 否則執(zhí)行entityManager.merge()
  /**
   * save方法會預(yù)檢查該entity是否持久化,isNew會判斷該對象的Id類型 是否實現(xiàn)Persistable或EntityInformation進(jìn)行
   * 重寫isNew方法泣刹,如果Id是Number類型助析,直接判斷value==0 true 執(zhí)行entityManager.persist 否則執(zhí)行entityManager.merge()
   */
  @Test
  public void insert() {
    Customer customer = new Customer();
    customer.setName("lk");
    customer.setEmail("spring.jpa@163.com");
    customer.setAddress("Shanghai PuDong Area XueYe Road");
    customer.setPhone("13699999999");
    //這里保存以后customer的id會被填充為保存后entity的id
    Customer savedEntity = customerRepository.save(customer);
    //保存并立即刷新數(shù)據(jù)庫,由于customer以及提供id椅您,會執(zhí)行merge方法進(jìn)行保存
//    Customer savedAndFlush = customerRepository.saveAndFlush(customer);
    List<Customer> batchCustomers = Arrays.asList(new Customer(), new Customer());
    //批量保存,saveAll是循環(huán)單挑插入外冀,并不是batch操作,數(shù)據(jù)較大使用時請注意性能
//    List<Customer> batchSaves = customerRepository.saveAll(batchCustomers);
  }
delete操作
  • delte操作會先執(zhí)行查詢(除了batch操作)掀泳,在執(zhí)行刪除雪隧,若查詢不到結(jié)果,拋出異常(EmptyResultDataAccessException)不執(zhí)行刪除
  /**
   * 刪除操作员舵,除了batch操作脑沿,其他方法均先查詢后刪除
   */
  @Test
  public void delete() {
    //select * from customer where id=?;delete from customer where id=?;
    //同delete(entity)
    customerRepository.deleteById(38L);
    //select * from customer;循環(huán)遍歷id單個刪除...delete from customer where id=?...
    customerRepository.deleteAll();
    Customer customer = new Customer();
    customer.setId(Long.valueOf(42L));
    Customer customerOther = new Customer();
    customerOther.setId(41L);
    List<Customer> deleteAll = Arrays.asList(customer,customerOther);
    //循環(huán)執(zhí)行delete(entity)
    customerRepository.deleteAll(deleteAll);
    //不查詢直接:delete from customer;(風(fēng)險較大清空表)
    customerRepository.deleteAllInBatch();
    //不查詢直接:delete from customer where id=? or id=?
    customerRepository.deleteInBatch(deleteAll);
  }

最常用的query操作

jpa 官方查詢關(guān)鍵字
Keyword Sample JPQL snippet
And findByLastnameAndFirstname … where x.lastname = ?1 and x.firstname = ?2
Or findByLastnameOrFirstname … where x.lastname = ?1 or x.firstname = ?2
Is,Equals findByFirstname,findByFirstnameIs,findByFirstnameEquals … where x.firstname = ?1
Between findByStartDateBetween … where x.startDate between ?1 and ?2
LessThan findByAgeLessThan … where x.age < ?1
LessThanEqual findByAgeLessThanEqual … where x.age <= ?1
GreaterThan findByAgeGreaterThan … where x.age > ?1
GreaterThanEqual findByAgeGreaterThanEqual … where x.age >= ?1
After findByStartDateAfter … where x.startDate > ?1
Before findByStartDateBefore … where x.startDate < ?1
IsNull findByAgeIsNull … where x.age is null
IsNotNull,NotNull findByAge(Is)NotNull … where x.age not null
Like findByFirstnameLike … where x.firstname like ?1
NotLike findByFirstnameNotLike … where x.firstname not like ?1
StartingWith findByFirstnameStartingWith … where x.firstname like ?1 (parameter bound with appended %)
EndingWith findByFirstnameEndingWith … where x.firstname like ?1 (parameter bound with prepended %)
Containing findByFirstnameContaining … where x.firstname like ?1 (parameter bound wrapped in %)
OrderBy findByAgeOrderByLastnameDesc … where x.age = ?1 order by x.lastname desc
Not findByLastnameNot … where x.lastname <> ?1
In findByAgeIn(Collection<Age> ages) … where x.age in ?1
NotIn findByAgeNotIn(Collection<Age> ages) … where x.age not in ?1
True findByActiveTrue() … where x.active = true
False findByActiveFalse() … where x.active = false
IgnoreCase findByFirstnameIgnoreCase … where UPPER(x.firstame) = UPPER(?1)
單表字段查詢
    //select * from customer;
    customerRepository.findAll();
    //select * from customer where id = 1;
    customerRepository.findById(1L);
    //select * from customer where address = "address";
    customerRepository.findCustomerByAddress("address");
    //select * from customer where name = "lk" and phone = "133";
    customerRepository.findCustomersNameAndPhone("133", "lk");
    //select * from customer where name like '%k';
    customerRepository.findCustomersNameLike("k");
    //select * from customer where name like 'k'; 如果需要模糊查詢需要手動拼接 % 連接符
    customerRepository.findCustomersByNameLike("k");
    //select * from customer where name like "%l";
    customerRepository.findCustomersByNameStartingWith("l");
    //select * from customer where name like "%k%";
    customerRepository.findCustomersByNameContains("k");
    / /.....還有很多,不再一一列舉......
分頁固灵,排序
    //select * from customer order by name desc;
    customerRepository.findAll(Sort.by(Direction.DESC, "name"));
    //select * from customer limit 0,10;
    customerRepository.findAll(PageRequest.of(0, 10));
example查詢(場景較少)
    Customer customer = new Customer();
    customer.setAddress("address");
    //select * from customer where address ="address";
    customerRepository.findAll(Example.of(customer));
    customer.setName("lk");
    customer.setPhone("133");
    ExampleMatcher matcher = ExampleMatcher.matching()
        .withMatcher("name", match -> match.contains())
        .withMatcher("phone", match -> match.startsWith());
    //select * from customer where name like '%lk%" and phone like '133%' and address = "address";
    customerRepository.findOne(Example.of(customer, matcher));
namedQuery 也是自定義的@Query的一種
//entity
@Entity(name = "Customer")
@NamedQuery(name = "Customer.findByNameNQ", query = "select c from Customer c where name =?1")
public class Customer {}

//repository定義方法findByNameNQ
List<Customer> findByNameNQ(String name);

//test
//namedQuery:select * from customer where name = "lk";
customerRepository.findByNameNQ("lk");
@Query自定義JQL語句查詢捅伤,語法跟sql類似,但注意基于entity的命名巫玻,如果屬性nativeQuery為ture則丛忆,必須用原生sql語句
  @Query("select c from Customer c where name like %?1")
  List<Customer> findCustomersNameLike(String name);

  @Query("select c from Customer c where name = :name and phone = :phone")
  List<Customer> findCustomersNameAndPhone(@Param("phone") String phone,
      @Param("name") String name);

  @Query(value = "select * from customer where name =?1",nativeQuery = true)
  List<Customer> findByNameSql(String name);
@Modify 配合 @Query實現(xiàn) 修改部分字段
  @Modifying
  @Query("update Customer c set c.name = :name where c.id = :id")
  int modifyByPhone(@Param("name") String name,@Param("id") Long id);

  @Modifying
  @Query("delete from Customer c  where c.id = ?1")
  int deleteCustomer(Long id);

自定義返回值,基于JQL語法仍秤,在拼裝返回結(jié)果集時熄诡,是根據(jù)構(gòu)造函數(shù)進(jìn)行組裝的,可以基于接口或者類诗力,要保證屬性是entity內(nèi)的屬性凰浮。也可以借助@Query,使用 new map()返回map苇本,或者new Class返回想要的結(jié)果袜茧。

  //repository

  List<NameOnlyI> findCustomersByName(String name);

  List<NameOnly> findByName(String name);

  @Query("select new com.spring.jpa.beans.NameOnly(name,address) from Customer where name = ?1")
  List<NameOnly> findByName4Obj(String name);

  @Query("select new map(name as myname,address as myaddress) from Customer where name = :name")
  List<Map<String, Object>> findByName4Map(@Param("name") String name);

//test

    //基于接口的返回值
    List<NameOnlyI> interfaces = customerRepository.findCustomersByName("lk1");
    //基于類的返回值,如果有兩個構(gòu)造函數(shù)會報錯瓣窄,無法解析轉(zhuǎn)換
    List<NameOnly> nameOnlies = customerRepository.findByName("lk1");
    //基于類的返回值笛厦,@Query顯式聲明返回bean
    List<NameOnly> objs = customerRepository.findByName4Obj("lk1");
    //@Query返回map 用as做key,不用as默認(rèn)key是0俺夕,1裳凸,2...
    List<Map<String, Object>> maps = customerRepository.findByName4Map("lk1");

復(fù)雜關(guān)聯(lián)關(guān)系查詢 @OneToOne @ManyToMany @ManyToOne @OneToMany

customer 顧客表贱鄙,和customer_group 多對一
customer_group 顧客分組表
book 書籍表,customer是多對多姨谷。
book_detail 書籍詳細(xì)表逗宁,和book是一對一

  • 四張表沒任何業(yè)務(wù),假象出來的梦湘,單純?yōu)榱蓑炞Cjpa查詢方式
表關(guān)系注解參數(shù)(@OneToOne @ManyToMany @ManyToOne @OneToMany )
Cascade 級聯(lián)操作
CascadeType. PERSIST 級聯(lián)持久化 ( 保存 ) 操作
CascadeType. MERGE 級聯(lián)更新 ( 合并 ) 操作
CascadeType. REFRESH 級聯(lián)刷新操作瞎颗,只會查詢獲取操作
CascadeType. REMOVE 級聯(lián)刪除操作
CascadeType. ALL 級聯(lián)以上全部操作
  • Fetch
    抓取是否延遲加載,默認(rèn)情況一的方為立即加載践叠,多的一方為延遲加載言缤,可以手動指定Fetch.EAGER/Fetch.LAZY
  • mappedBy
    關(guān)聯(lián)關(guān)系由此方屬性維護(hù)嚼蚀,可以理解成一對注解使用mappedBy的一方由另一方維護(hù)禁灼,且必須是注解作用下的屬性名。
可以根據(jù)關(guān)聯(lián)表的屬性作為條件查詢轿曙,結(jié)果同樣是根據(jù)兩次sql查詢出來的弄捕。通過關(guān)聯(lián)表的屬性進(jìn)行查詢時,使用關(guān)聯(lián) entityName_columnName方式导帝,或者直接使用 _columnName進(jìn)行查詢守谓。如果不想級聯(lián)查詢時,在一方不適用注解即可您单。

@OneToOne

一對一關(guān)聯(lián)關(guān)系斋荞,有三種形式存在:

  • 兩張表共享主鍵pk,使用@PrimaryKeyJoinColumn來建立關(guān)聯(lián)關(guān)系
@Entity
public class A {
  @Id
  private Long id;
  @OneToOne(cascade = CascadeType.ALL)
  @PrimaryKeyJoinColumn
  private B b;
}

@Entity
public class B {
  @Id
  private Long id;
}
  • 通過中間表建立關(guān)聯(lián)關(guān)系虐秦,使用@JoinTable注解平酿,joinColumns指定本表和關(guān)聯(lián)表的外鍵,inverseJoinColumns指定關(guān)聯(lián)關(guān)系另一方和關(guān)聯(lián)表的外鍵
@Entity
public class A {
  @Id
  private Long id;
  @OneToOne(cascade = CascadeType.ALL)
  joinColumns = @JoinColumn(name="a_fk"),
  inverseJoinColumns = @JoinColumn(name="b_fk")
  private B b;
}

@Entity
public class B {
  @Id
  private Long id;
  @OneToOne(mappedBy="b")
  private A a;
}
  • 通過外鍵悦陋,唯一約束指定關(guān)聯(lián)關(guān)系蜈彼,使用@JoinColumn注解,如果不寫該注解俺驶,默認(rèn)會在此表中自動創(chuàng)建連接列:主表屬性_關(guān)聯(lián)表主鍵名稱
@Entity(name = "book")
public class Book {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;

  private String name;
  private Integer count;

  @OneToOne(cascade = CascadeType.ALL)
  @JoinColumn(name = "detail_id",referencedColumnName = "id")
//referencedColumnName 不寫默認(rèn)是主鍵幸逆,當(dāng)不是主鍵是可以用此聲明,但必須保證連接鍵在連接表是唯一約束的
  private BookDetail bookDetail;

//setter getter
}

@Entity(name = "book_detail")
public class BookDetail {

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;
  private String size;
//不需要依賴book可以不寫關(guān)聯(lián)屬性

//setter getter
}

public interface BookRepository extends JpaRepository<Book, Long> {

  //可以查出關(guān)聯(lián)表的實體暮现,結(jié)果是根據(jù)兩次sql查詢出來的还绘,即select * from book where name = ?;->查出detail_id->select * from book_detail where id = ?;
  List<Book> findByName(String name);
  //可以根據(jù)關(guān)聯(lián)表的屬性作為條件查詢,結(jié)果同樣是根據(jù)兩次sql查詢出來的栖袋。通過關(guān)聯(lián)表的屬性進(jìn)行查詢時拍顷,使用關(guān)聯(lián) entityName_columnName方式,或者直接使用 _columnName進(jìn)行查詢栋荸。
  List<Book> findByNameAndBookDetail_Id(String name, Long id);

  //自定義返回值菇怀,一次查詢返回結(jié)果
  @Query("select new com.spring.jpa.beans.BookResult(b.id as id,b.name as name ,d.size as size) from Book as b left join BookDetail as d on b.bookDetail = d.id")
  List<BookResult> findResults();

}
@ManyToMany
  • 通過@ManyToMany 注解定義多對多關(guān)系凭舶,同時通過 @JoinTable 注解描述關(guān)聯(lián)表和關(guān)聯(lián)條件。
// 維護(hù)端注解
@Entity
public class A {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;
  @ManyToMany (cascade = CascadeType.REFRESH)
  @JoinTable (
           name =  "a_b" , //關(guān)聯(lián)表名
           inverseJoinColumns =  @JoinColumn (name =  "a_id" ),//被維護(hù)端外鍵
           joinColumns =  @JoinColumn (name =  "b_id" ))//維護(hù)端外鍵被維護(hù)端注解
   private B b;

//setter getter
}

@Entity
public class B {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;
  @ManyToMany(cascade = CascadeType.REFRESH,
            mappedBy = "b",//通過維護(hù)端的屬性關(guān)聯(lián)
            fetch = FetchType.LAZY)
// 關(guān)系維護(hù)端刪除時爱沟,如果中間表存在些紀(jì)錄的關(guān)聯(lián)信息帅霜,則會刪除該關(guān)聯(lián)信息;
// 關(guān)系被維護(hù)端刪除時,如果中間表存在些紀(jì)錄的關(guān)聯(lián)信息呼伸,則會刪除失敗 .
  private A a;

//setter getter
}
  • 默認(rèn)joinColumn值:關(guān)聯(lián)表名:主表表名 + 下劃線 + 從表表名身冀;關(guān)聯(lián)表到主表的外鍵:主表表名 + 下劃線 + 主表中主鍵列名;關(guān)聯(lián)表到從表的外鍵名:主表中用于關(guān)聯(lián)的屬性名+ 下劃線 + 從表的主鍵列名
@ManyToOne @OneToMany
  • 注解和上面都差不多括享,無非就是誰關(guān)聯(lián)誰
@Entity
@NamedQuery(name = "Customer.findByNameNQ", query = "select c from Customer c where name =?1")
public class Customer {

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;
  private String name;
  private String email;
  private String address;
  private String phone;

//  //targetEntity 默認(rèn)是關(guān)聯(lián)實體搂根,若使用接口作為關(guān)聯(lián)實體時,應(yīng)指明targetEntity的實現(xiàn)類铃辖,且接口應(yīng)繼承Serializable剩愧,否則無法被解析
//  @ManyToOne(fetch = FetchType.EAGER,targetEntity = CustomerGroup.class)
//  @JoinColumn(name = "group_type",referencedColumnName = "type")
//  private CustomerGroupInterface customerGroup;

  //manyToOne 單向關(guān)聯(lián)或 oneToMany雙向關(guān)聯(lián)
//  //這里使用非主鍵作為外鍵關(guān)聯(lián),type在customer_group表中唯一約束娇斩,也可以使用@JoinTable 處理關(guān)聯(lián)表做連接這里不再演示
  @ManyToOne(fetch = FetchType.EAGER,cascade = CascadeType.ALL)
  @JoinColumn(name = "group_type",referencedColumnName = "type")
  private CustomerGroup customerGroup;

  //customerGroup為一的一方仁卷,單向關(guān)聯(lián)customer(多方)
//  @Column(name = "group_type")
//  private String type;

//setter getter
}

@Entity
@Table(name = "customer_group")
public class CustomerGroup implements CustomerGroupInterface {

  private static final long serialVersionUID = -6956725658881048590L;
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;
  @Column(unique = true)
  private String type;
  private String name;
  private Integer level;

  //oneToMany 單向關(guān)聯(lián),customer中無需注解犬第,注意joinColumn是table中的name
//  @OneToMany(fetch = FetchType.EAGER)
//  @JoinColumn(name = "group_type")

  //oneToMany 雙向關(guān)聯(lián)锦积,customer中無需注解,mappedBy必須指向entity中的屬性名,即標(biāo)有@ManyToOne的屬性名歉嗓,且此處不可再使用@JoinColumn丰介。
  @OneToMany(fetch = FetchType.EAGER, mappedBy = "customerGroup")
  private List<Customer> customers;

//setter getter
}
其他注解
注解 解釋
@Entity 聲明一個類為實體Bean。
@Table 說明此實體類映射的表名鉴分,目錄哮幢,schema的名字。
@Id 聲明此表的主鍵冠场。
@GeneratedValue 定義主鍵的增長策略家浇。我這里一般交給底層數(shù)據(jù)庫處理,所以調(diào)用了名叫g(shù)enerator的增長方式碴裙,由下邊的@GenericGenerator實現(xiàn)钢悲。
@GenericGenerator hibernate內(nèi)部的主鍵增長方式。
@Version 注解用于支持樂觀鎖版本控制舔株。一般可以用 數(shù)字 或者 timestamp 類型來支持 version.
@Column name 可選莺琳,列名(默認(rèn)值是屬性名); unique 可選,是否在該列上設(shè)置唯一約束(默認(rèn)值false);nullable 可選载慈,是否設(shè)置該列的值可以為空(默認(rèn)值true); insertable 可選惭等,該列是否作為生成的insert語句中的一個列(默認(rèn)值true);updatable 可選,該列是否作為生成的update語句中的一個列(默認(rèn)值true); columnDefinition 可選办铡,為這個特定列覆蓋SQL DDL片段 (這可能導(dǎo)致無法在不同數(shù)據(jù)庫間移植); table 可選辞做,定義對應(yīng)的表(默認(rèn)為主表);length 可選琳要,列長度(默認(rèn)值255);precision 可選,列十進(jìn)制精度(decimal precision)(默認(rèn)值0);scale 可選秤茅,如果列十進(jìn)制數(shù)值范圍(decimal scale)可用,在此設(shè)置(默認(rèn)值0)
@Index 某一字段加索引 @Table(name = "customer", indexes = {@Index(columnList = "name")})稚补,給name字段加上索引
@Transient 被注解成 @Transient 的 getter 方法或?qū)傩裕瑢⒉粫怀志没ㄗ约簻y試框喳,只有放在getter方法內(nèi)才起作用)
@Basic 所有沒有定義注解的屬性课幕,等價于在其上面添加了 @Basic注解可以聲明屬性的獲取策略 ( fetch strategy ),fetch:抓取策略,延時加載與立即加載,optional:指定在生成數(shù)據(jù)庫結(jié)構(gòu)時字段是否允許為 null.
@Temporal 在核心的 Java API 中并沒有定義時間精度 ( temporal precision )五垮。因此處理時間類型數(shù)據(jù)時乍惊,你還需要定義將其存儲在數(shù)據(jù)庫中所預(yù)期的精度。
@Enumerated 枚舉類型成員屬性映射,EnumType.STRING指定屬性映射為字符串,EnumType.ORDINAL指定屬性映射為數(shù)據(jù)序
@Lob 用于標(biāo)注字段類型為Clob和Blob類型放仗,Clob(Character Large Ojects)類型是長字符串類型,實體的類型可為char[]润绎、Character[]、或者String類型匙监,Blob(Binary Large Objects)類型是字節(jié)類型,實體的類型可為byte[]凡橱、Byte[]、或者實現(xiàn)了Serializable接口的類亭姥。通常使用惰性加載的方式,@Basic(fetch=FetchType.LAZY)
@SecondaryTable (@javax.persistence.SecondaryTable)將一個實體映射到多個數(shù)據(jù)庫表中

最后寫的比較急躁,代碼放github和碼云了:spring-data/github spring-data/碼云

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末顾稀,一起剝皮案震驚了整個濱河市达罗,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌静秆,老刑警劉巖粮揉,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異抚笔,居然都是意外死亡扶认,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進(jìn)店門殊橙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來辐宾,“玉大人,你說我怎么就攤上這事膨蛮〉疲” “怎么了?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵敞葛,是天一觀的道長誉察。 經(jīng)常有香客問我,道長惹谐,這世上最難降的妖魔是什么持偏? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任驼卖,我火速辦了婚禮,結(jié)果婚禮上鸿秆,老公的妹妹穿的比我還像新娘款慨。我一直安慰自己,他們只是感情好谬莹,可當(dāng)我...
    茶點故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布檩奠。 她就那樣靜靜地躺著,像睡著了一般附帽。 火紅的嫁衣襯著肌膚如雪埠戳。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天蕉扮,我揣著相機(jī)與錄音整胃,去河邊找鬼。 笑死喳钟,一個胖子當(dāng)著我的面吹牛屁使,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播奔则,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼蛮寂,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了易茬?” 一聲冷哼從身側(cè)響起酬蹋,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎抽莱,沒想到半個月后范抓,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡食铐,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年匕垫,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片虐呻。...
    茶點故事閱讀 38,100評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡象泵,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出铃慷,到底是詐尸還是另有隱情单芜,我是刑警寧澤,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布犁柜,位于F島的核電站洲鸠,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜扒腕,卻給世界環(huán)境...
    茶點故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一绢淀、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧瘾腰,春花似錦皆的、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至栖雾,卻和暖如春楞抡,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背析藕。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工召廷, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人账胧。 一個月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓竞慢,卻偏偏與公主長得像,于是被迫代替她去往敵國和親治泥。 傳聞我的和親對象是個殘疾皇子筹煮,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,834評論 2 345

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