Spring Data JPA-基礎篇(二)

前置文章:

Spring Data JPA-基礎篇(一)

前言:

前置文章中我們已經介紹了基礎JPA的使用方式,JPA是操作數據庫的一種ORM規范,而文章中使用的Hibernate是其具體的實現。
本文則是使用Spring Data JPA來進行具體的CRUD操作。

零、本文綱要

一、基礎準備

  1. pom.xml配置
  2. applicationContext.xml
  3. Customer實體類
  4. CustomerDao接口

二、基礎CRUD

  1. 測試準備
  2. 測試查詢
  3. 測試保存
  4. 測試刪除
  5. 測試查詢所有
  6. 測試聚合查詢
  7. 判斷是否存在

三、JPQL形式查詢

  1. 條件查詢
  2. 多條件查詢
  3. 更新操作

四、SQL形式查詢

  1. 查詢全部
  2. 模糊匹配

五、方法命名規則查詢

  1. 條件查詢
  2. 模糊匹配
  3. 多條件查詢

一、基礎準備

1. pom.xml配置

① 屬性控制
    <!--屬性控制-->
    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <spring.version>5.1.20.RELEASE</spring.version>
        <hibernate.version>5.0.7.Final</hibernate.version>
        <javax.el.version>2.2.4</javax.el.version>
        <slf4j.version>1.6.6</slf4j.version>
    </properties>
② 依賴管理

此處依賴部分并沒有過多說明,因為現在大家使用的Spring Boot、Spring Cloud都在淡化我們依賴配置的內容,更關注代碼開發本身。

    <!--依賴管理-->
    <dependencies>
        <!--Junit-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <!--Spring-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.6.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-jpa</artifactId>
            <version>1.9.0.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <!--el-->
        <dependency>
            <groupId>javax.el</groupId>
            <artifactId>javax.el-api</artifactId>
            <version>${javax.el.version}</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.web</groupId>
            <artifactId>javax.el</artifactId>
            <version>${javax.el.version}</version>
        </dependency>
        <!--hibernate-->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>${hibernate.version}</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>${hibernate.version}</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>5.2.1.Final</version>
        </dependency>
        <!--MySQL-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.30</version>
        </dependency>
        <!--c3p0數據庫連接池-->
        <dependency>
            <groupId>c3p0</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.1.2</version>
        </dependency>
        <!--log-->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>${slf4j.version}</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>${slf4j.version}</version>
        </dependency>
    </dependencies>

2. applicationContext.xml

① 基礎約束準備

引入了beans、aop、context、jdbc、tx、jpa這些命名空間。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:jdbc="http://www.springframework.org/schema/jdbc"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:jpa="http://www.springframework.org/schema/data/jpa"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/jdbc
       http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
       http://www.springframework.org/schema/tx
       http://www.springframework.org/schema/tx/spring-tx.xsd
       http://www.springframework.org/schema/data/jpa
       http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">

</beans>
② 數據源配置
    <!-- 1. 創建數據庫連接池 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="com.mysql.cj.jdbc.Driver"/>
        <property name="jdbcUrl" value="jdbc:mysql:///test"/>
        <property name="user" value="root"/>
        <property name="password" value="root"/>
    </bean>
③ 創建entityManagerFactory對象
    <!-- 2. 創建entityManagerFactory對象 -->
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <!-- ① 配置數據源 -->
        <property name="dataSource" ref="dataSource"/>

        <!-- ② 指定實體類所在的包 -->
        <property name="packagesToScan" value="com.stone.domain"/>

        <!-- ③ 配置JPA的實現廠商(供應商) -->
        <property name="persistenceProvider">
            <bean class="org.hibernate.jpa.HibernatePersistenceProvider"/>
        </property>

        <!-- ④ JPA的供應商適配器 -->
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <!-- a、配置是否自動創建數據庫表 -->
                <property name="generateDdl" value="false"/>
                <!-- b、指定數據庫類型 -->
                <property name="database" value="MYSQL"/>
                <!-- c、數據庫方言:支持的特有語法,MySQL分頁limit,Oracle分頁ROWNUM -->
                <property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect"/>
                <!-- d、是否顯示SQL語句 -->
                <property name="showSql" value="true"/>
            </bean>
        </property>

        <!--⑤ JPA方言:高級特性-->
        <property name="jpaDialect">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/>
        </property>
    </bean>
④ 配置事務管理器
    <!-- 3. 配置事務管理器 -->
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"/>
    </bean>
⑤ 整合Spring Data JPA
    <!-- 4. 整合Spring Data JPA -->
    <jpa:repositories base-package="com.stone.dao" transaction-manager-ref="transactionManager"
                      entity-manager-factory-ref="entityManagerFactory"/>
⑥ 聲明式事務

此處非必要

    <!-- txAdvice -->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="save" propagation="REQUIRED"/>
            <tx:method name="insert" propagation="REQUIRED"/>
            <tx:method name="update" propagation="REQUIRED"/>
            <tx:method name="delete" propagation="REQUIRED"/>
            <tx:method name="get*" read-only="true"/>
            <tx:method name="find*" read-only="true"/>
            <tx:method name="*" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>
    <!-- aop -->
    <aop:config>
        <aop:pointcut id="pointcut" expression="execution(* com.stone.service.*.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut"/>
    </aop:config>
⑦ 配置包掃描
    <context:component-scan base-package="com.stone"/>
⑧ 整合其他配置文件

此處暫時沒有。

3. Customer實體類

/**
 * 客戶實體類
 * → 配置映射關系
 *      1. 實體類和表的映射關系;
 *      2. 實體類中屬性和表中字段的映射關系;
 * → 實體類和表的映射關系
 *      ① @Entity:聲明實體類;
 *      ② @Table:配置實體類和表的映射關系;
 *          → name:配置數據庫表名稱;
 * → 實體類中屬性和表中字段的映射關系
 *      ① @Id:聲明主鍵的配置;
 *      ② @GeneratedValue:配置主鍵生成策略;
 *          → strategy:主鍵策略
 *              a、 GenerationType.IDENTITY  自增,MySQL數據庫;
 *                  底層數據庫必須支持自動增長,采用數據庫自增方式對ID進行自增。
 *              b、 GenerationType.SEQUENCE  序列,Oracle數據庫;
 *                  底層數據庫支持序列。
 *              c、 GenerationType.TABLE
 *                  JPA提供的一種機制,通過一張數據庫表的形式幫助完成主鍵自增。
 *              d、 GenerationType.AUTO
 *                  由程序自動選擇主鍵生成策略。
 *      ③ Column:實體類屬性與表字段映射
 *          → name:數據庫表字段名稱
 */
@Table(name = "cst_customer")
@Entity
public class Customer {

    /*客戶主鍵*/
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "cust_id")
    private Long custId;

    /*客戶名稱*/
    @Column(name = "cust_name")
    private String custName;

    /*客戶資源來源*/
    @Column(name = "cust_source")
    private String custSource;

    /*客戶級別*/
    @Column(name = "cust_level")
    private String custLevel;

    /*客戶所屬行業*/
    @Column(name = "cust_industry")
    private String custIndustry;

    /*客戶的聯系方式*/
    @Column(name = "cust_phonoe")
    private String custPhone;

    /*客戶地址*/
    @Column(name = "cust_address")
    private String custAddress;

    ...

}

4. CustomerDao接口

NOTE
JpaRepository<T, ID>,該接口封裝了基礎CRUD操作:
→ T:操作的實體類類型;
→ ID:實體類中主鍵屬性的類型。

JpaSpecificationExecutor<T>,該接口封裝了復雜查詢(分頁):
→ T:操作的實體類類型。

/**
 * 符合SpringDataJpa規范的接口
 * → JpaRepository<T, ID>,該接口封裝了基礎CRUD操作
 * T:操作的實體類類型;
 * ID:實體類中主鍵屬性的類型。
 * → JpaSpecificationExecutor<T>,該接口封裝了復雜查詢(分頁)
 * T:操作的實體類類型。
 */
public interface CustomerDao extends JpaRepository<Customer, Long>, 
JpaSpecificationExecutor<Customer> {
    ...
}

二、基礎CRUD

1. 測試準備

@RunWith(SpringJUnit4ClassRunner.class) //聲明Spring提供的單元測試環境
@ContextConfiguration(locations = "classpath:applicationContext.xml") //指定Spring容器配置信息
public class CustomerDaoTest {

    @Autowired
    private CustomerDao customerDao;

    ...

}

2. 測試查詢

NOTE
findOne → em.find() → 立即加載;
getOne → em.getReference() → 延遲加載;

    /**
     * 測試跟據ID查詢,findOne方法
     */
    @Test
    public void testFindOne() {
        Customer customer = customerDao.findOne(1L);
        System.out.println(customer);
    }

    /**
     * 跟據ID從數據庫查詢,getOne方法需要使用@Transactional注解
     * findOne → em.find():立即加載
     * getOne → em.getReference():延遲加載
     */
    @Test
    @Transactional
    public void testGetOne() {
        Customer customer = customerDao.getOne(5L);
        System.out.println(customer);
    }

3. 測試保存

NOTE
① 實體對象未設置主鍵屬性值:直接保存;
② 實體對象設置主鍵屬性值:
→ a、主鍵存在,進行更新;
→ b、主鍵不存在,跟據主鍵策略生成主鍵進行插入(保存)。

    /**
     * 測試更新|保存,save方法
     * → 先查詢,后更新|保存
     * 如果沒有設置ID屬性,則進行保存操作;如果設置了ID屬性,則會進行更新|保存。
     * ① 如果指定ID數據存在,則進行更新操作;
     * ② 如果指定ID數據不存在,則進行保存操作(注意:保存時主鍵會依據主鍵策略自動生成,而不是指定的主鍵)。
     */
    @Test
    public void testSave() {
        Customer customer = new Customer();
        customer.setCustId(22L);
        customer.setCustName("Stone");
        customerDao.save(customer);
    }

4. 測試刪除

    /**
     * 測試刪除delete
     * → 先查詢,后刪除
     */
    @Test
    public void testDelete() {
        customerDao.delete(21L);
    }

5. 測試查詢所有

    /**
     * 測試查詢所有findAll
     */
    @Test
    public void testFindAll() {
        List<Customer> customers = customerDao.findAll();
        for (Customer customer : customers) {
            System.out.println(customer);
        }
    }

6. 測試聚合查詢

    /**
     * 測試聚合(統計)查詢
     */
    @Test
    public void testCount() {
        long count = customerDao.count();
        System.out.println(count);
    }

7. 判斷是否存在

    /**
     * 測試查詢判斷是否存在
     * 傳統方式:
     * ① 判斷查詢結果是否為空null;
     * ② 判斷查詢結果條數是否大于0;【JPA采用此方式】
     */
    @Test
    public void testExists() {
        boolean exists = customerDao.exists(4L);
        System.out.println(exists);
    }

三、JPQL形式查詢

1. 條件查詢

① 接口方法準備
    /**
     * 跟據客戶名稱查詢客戶信息
     * JPQL:FROM Customer WHERE custName = ?
     * 注意:在@Query注解的value屬性中,需要使用"?1"來指定具體占位。
     *
     * @param custName 客戶名稱
     * @return 客戶信息
     */
    @Query(value = "FROM Customer WHERE custName = ?1")
    public Customer findJpql(String custName);
② 測試
    /**
     * 測試JPQL查詢
     */
    @Test
    public void testJpql() {
        Customer yinRui = customerDao.findJpql("Yin Rui");
        System.out.println(yinRui);
    }

2. 多條件查詢

① 接口方法準備
    /**
     * JPQL:FROM Customer WHERE custName = ? AND custId = ?
     *
     * @param custName 客戶名稱
     * @param custId   客戶ID
     * @return 客戶信息
     */
    @Query(value = "FROM Customer WHERE custName = ?1 AND custId = ?2")
    public Customer findCustNameAndCustId(String custName, Long custId);
② 測試
    /**
     * 測試JPQL多條件查詢
     */
    @Test
    public void testJpqlAnd() {
        Customer nicholasDunn = customerDao.findCustNameAndCustId("Nicholas Dunn", 19L);
        System.out.println(nicholasDunn);
    }

3. 更新操作

① 接口方法準備

NOTE
相比于查詢方法,此處需要配合 @Modifying 注解一起使用。

    /**
     * 更新客戶姓名(@Query:代表進行查詢;@Modifying:代表當前執行方法進行更新操作。)
     * SQL:UPDATE cst_customer SET cust_name = ? WHERE cust_id = ?
     * JPQL:UPDATE Customer SET custName = ? WHERE custId = ?
     *
     * @param custName
     * @param custId
     */
    @Query(value = "UPDATE Customer SET custName = ?1 WHERE custId = ?2")
    @Modifying //(@Modifying+@Query)一起使用,代表更新操作。
    public void updateCustomer(String custName, Long custId);
② 測試
    /**
     * 測試JPQL更新操作
     * → SpringDataJpa中使用jpql完成 更新|刪除操作 需要手動添加事務支持;
     * → 在@Test注解下,默認SpringDataJpa執行完成會進行數據回滾;
     * → 使用@Rollback(value = false),關閉自動回滾。
     */
    @Test
    @Transactional //添加事務支持
    @Rollback(value = false)
    public void testUpdate() {
        customerDao.updateCustomer("Jeff Stone", 1L);
    }

四、SQL形式查詢

1. 查詢全部

① 接口方法準備
    /**
     * SQL:SELECT * FROM cst_customer
     * → 使用@Query注解,配置:
     * ① value屬性:sql;
     * ② nativeQuery屬性:使用本地sql查詢,true;反之,false。
     *
     * @return 查詢對象集合
     */
    @Query(value = "SELECT * FROM cst_customer", nativeQuery = true)
    public List<Object[]> findSql();
② 測試
    /**
     * 測試使用本地SQL查詢全部客戶信息
     */
    @Test
    public void testSql() {
        List<Object[]> objects = customerDao.findSql();
        for (Object[] object : objects) {
            System.out.println(Arrays.toString(object));
        }
    }

2. 模糊匹配

① 接口方法準備
    /**
     * 使用SQL查詢,進行模糊匹配
     * SQL:SELECT * FROM cst_customer WHERE cust_name LIKE ?
     *
     * @param custName 客戶名稱
     * @return 客戶信息
     */
    @Query(value = "SELECT * FROM cst_customer WHERE cust_name LIKE ?1", nativeQuery = true)
    public List<Object[]> findSqlLike(String custName);
② 測試
    /**
     * 測試SQL查詢,模糊匹配
     */
    @Test
    public void testSqlLike() {
        List<Object[]> objects = customerDao.findSqlLike("%Hicks");
        for (Object[] object : objects) {
            System.out.println(Arrays.toString(object));
        }
    }

五、方法命名規則查詢

1. 條件查詢

① 接口方法準備

NOTE
查詢方法寫法:findBy + 屬性名稱(field_name),等值匹配

    /**
     * 方法命名規則查詢,是對JPQL查詢的更深層的封裝,使用該規則可以不用再寫JPQL語句。
     * → 查詢方法寫法:findBy + 屬性名稱(field_name),等值匹配
     * ① 以findBy開頭;
     * ② 拼接對象中的屬性,屬性首字母改為大寫;
     *
     * @param custName 客戶名稱
     * @return 客戶信息
     */
    public Customer findByCustName(String custName);
② 測試
    /**
     * 測試按照方法命名規則查詢
     */
    @Test
    public void testFindByCustName() {
        Customer itoRiku = customerDao.findByCustName("Ito Riku");
        System.out.println(itoRiku);
    }

2. 模糊匹配

① 接口方法準備

NOTE
查詢方法寫法:findBy + 屬性名稱(field_name) + 查詢方式[Like|Isnull]

    /**
     * 跟據方法命名規則,進行模糊匹配
     * → 查詢方法寫法:findBy + 屬性名稱(field_name) + 查詢方式[Like|Isnull]
     *
     * @param custName 客戶名稱
     * @return 客戶信息
     */
    public List<Customer> findByCustNameLike(String custName);
② 測試
    /**
     * 測試模糊匹配查詢(注意:由于時占位符的形式進行填充,"%"的位置信息需要自己判斷。)
     */
    @Test
    public void testFindByCustNameLike() {
        List<Customer> customers = customerDao.findByCustNameLike("%Yuito");
        for (Customer customer : customers) {
            System.out.println(customer);
        }
    }

3. 多條件查詢

① 接口方法準備

NOTE
查詢方法寫法:findBy + 屬性名稱(field_name) + 查詢方式[Like|Isnull] + 多條件連接符(And|Or) + 屬性名稱(field_name) + 查詢方式[Like|Isnull]

    /**
     * 跟據方法命名規則,進行多條件查詢
     * → 查詢方法寫法:findBy + 屬性名稱(field_name) + 查詢方式[Like|Isnull] + 多條件連接符(And|Or)
     * + 屬性名稱(field_name) + 查詢方式[Like|Isnull]
     *
     * @param CustName 客戶名稱
     * @param CustAddress 客戶地址
     * @return 客戶信息
     */
    public List<Customer> findByCustNameLikeAndCustAddress(String CustName, String CustAddress);
② 測試
    /**
     * 測試多條件查詢
     */
    @Test
    public void testFindByCustNameLikeAndCustAddress() {
        List<Customer> customers =
                customerDao.findByCustNameLikeAndCustAddress("Xue%", "536 Wall Street");
        for (Customer customer : customers) {
            System.out.println(customer);
        }
    }

六、結尾

以上即為Spring Data JPA-基礎篇(二)的全部內容,感謝閱讀。

?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,572評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,071評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,409評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,569評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,360評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,895評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,979評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,123評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,643評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,559評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,742評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,250評論 5 356
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,981評論 3 346
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,363評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,622評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,354評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,707評論 2 370

推薦閱讀更多精彩內容