<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                [TOC] # 簡介 Spring Data JPA 是 Spring 基于 ORM 框架、JPA 規范的基礎上封裝的一套JPA應用框架,可使開發者用極簡的代碼即可實現對數據的訪問和操作。它提供了包括增刪改查等在內的常用功能,且易于擴展!學習并使用 Spring Data JPA 可以極大提高開發效率! > spring data jpa讓我們解脫了DAO層的操作,基本上所有CRUD都可以依賴于它來實現 ~~~ <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-jpa --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> <version>2.2.1.RELEASE</version> </dependency> <!-- 錢相關 --> <dependency> <groupId>org.joda</groupId> <artifactId>joda-money</artifactId> <version>1.0.1</version> </dependency> <!-- 類型映射相關 --> <dependency> <groupId>org.jadira.usertype</groupId> <artifactId>usertype.core</artifactId> <version>6.0.1.GA</version> </dependency> <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <!-- <version>5.1.48</version>--> <version>8.0.18</version> </dependency> ~~~ ![](https://img.kancloud.cn/8a/3e/8a3e71d9f6108395fd3a1a36211a6894_1428x910.png) # 配置 ~~~ spring.datasource.url=jdbc:mysql://localhost:3306/test?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true spring.datasource.username=root spring.datasource.password=root spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.jpa.properties.hibernate.hbm2ddl.auto=create spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect #spring.jpa.show-sql=true #SQL 輸出 spring.jpa.properties.hibernate.show_sql=true #format ?下 SQL 進?輸出 spring.jpa.properties.hibernate.format_sql=true #顯示綁定參數 logging.level.org.hibernate.type.descriptor.sql.BasicBinder=trace ~~~ `hibernate.hbm2ddl.auto` 參數的作?主要?于:?動創建、更新、驗證數據庫表結構,有四個值 * create:每次加載 Hibernate 時都會刪除上?次?成的表,然后根據 model 類再重新來?成新表,哪怕 兩次沒有任何改變也要這樣執?,這就是導致數據庫表數據丟失的?個重要原因。 * `create-drop`:每次加載 Hibernate 時根據 model 類?成表,但是 sessionFactory?關閉,表就?動刪除。 * update:最常?的屬性,第?次加載 Hibernate 時根據 model 類會?動建?起表的結構(前提是先建? 好數據庫),以后加載 Hibernate 時根據 model 類?動更新表結構,即使表結構改變了,但表中的?仍然存在,不會刪除以前的?。要注意的是當部署到服務器后,表結構是不會被馬上建?起來的,是要等應?第?次運?起來后才會。 * validate :每次加載 Hibernate 時,驗證創建數據庫表結構,只會和數據庫中的表進??較,不會創建 新表,但是會插?新值 其中 * dialect:主要是指定?成表名的存儲引擎為 InnoDB * show-sql: 是否在?志中打印出?動?成的 SQL,?便調試的時候查看 # 創建實體配置 ~~~ @Entity @Table(name = "user") @Data public class User { //主鍵 @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; //@Column(nullable = false, unique = true) private String username; } ~~~ * `@Entity(name="EntityName")`必須,?來標注?個數據庫對應的實體,數據庫中創建的表名默 認和類名?致。其中,name 為可選,對應數據庫中?個表,使?此注解標記 Pojo 是?個 JPA 實體。 * `@Table(name="",catalog="",schema="")` 可選,?來標注?個數據庫對應的實體,數據庫 中創建的表名默認和類名?致。通常和 @Entity 配合使?,只能標注在實體的 class 定義處,表示實體 對應的數據庫表的信息。 * @Id 必須,@Id 定義了映射到數據庫表的主鍵的屬性,?個實體只能有?個屬性被映射為主鍵。 * `@GeneratedValue(strategy=GenerationType,generator="")` 可選,strategy: 表示主鍵 ?成策略,有 AUTO、INDENTITY、SEQUENCE 和 TABLE 4 種,分別表示讓 ORM 框架?動選擇, generator: 表示主鍵?成器的名稱。 * `@Column(name = "user_code", nullable = false, length=32)` 可選,@Column 描 述了數據庫表中該字段的詳細定義,這對于根據 JPA 注解?成數據庫表結構的?具。name: 表示數據庫 表中該字段的名稱,默認情形屬性名稱?致;nullable: 表示該字段是否允許為 null,默認為 true; * unique: 表示該字段是否是唯?標識,默認為 false;length: 表示該字段的??,僅對 String 類型的字段 有效。 * @Transient 可選,@Transient 表示該屬性并??個到數據庫表的字段的映射,ORM 框架將忽略該 屬性。 * @Enumerated 可選,使?枚舉的時候,我們希望數據庫中存儲的是枚舉對應的 String 類型,?不是 枚舉的索引值,需要在屬性上?添加 @Enumerated(EnumType.STRING) 注解 # 基本查詢 基本查詢也分為兩種,一種是spring data默認已經實現,一種是根據查詢的方法來自動解析成SQL。 ## 預先生成方法 spring data jpa 默認預先生成了一些基本的CURD的方法,例如:增、刪、改等等 1. 繼承JpaRepository ~~~ @Repository public interface UserRepository extends JpaRepository<User, Long> {} ~~~ 2. 默認方法 ![](https://img.kancloud.cn/1b/83/1b830d58ad591462b27d8a05251191ff_1922x1634.png) ## 自定義簡單查詢 自定義的簡單查詢就是根據方法名來自動生成SQL,主要的語法是`findXXBy`,`readAXXBy`,`queryXXBy`,`countXXBy`,`getXXBy`后面跟屬性名稱: ~~~ User findByUserName(String userName); ~~~ 也使用一些加一些關鍵字`And`、`Or` ~~~ User findByUserNameOrEmail(String username, String email); ~~~ 修改、刪除、統計也是類似語法 ~~~ Long deleteById(Long id); Long countByUserName(String userName) ~~~ 修改、刪除、統計也是類似語法 ~~~ Long deleteById(Long id); Long countByUserName(String userName) ~~~ 基本上SQL體系中的關鍵詞都可以使用,例如:`LIKE`、`IgnoreCase`、`OrderBy`。 ~~~ List<User> findByEmailLike(String email); User findByUserNameIgnoreCase(String userName); List<User> findByUserNameOrderByEmailDesc(String email); ~~~ **具體的關鍵字,使用方法和生產成SQL如下表所示** | 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 | 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 ages) | … where x.age in ?1 | | NotIn | findByAgeNotIn(Collection age) | … 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) | # jdk9 如果是jdk9,執行報錯如下: ![](https://img.kancloud.cn/22/3e/223e808f120a66cf774ff7a07808a9f6_812x87.png) 原因: 缺少相應的jar 解決方案: 手動導入對應的maven坐標 ~~~ <dependency> <groupId>javax.xml.bind</groupId> <artifactId>jaxb-api</artifactId> <version>2.3.0</version> </dependency> ~~~ # 其他 ## 使用枚舉 使用枚舉的時候,我們希望數據庫中存儲的是枚舉對應的String類型,而不是枚舉的索引值,需要在屬性上面添加`@Enumerated(EnumType.STRING)`注解 ~~~ @Enumerated(EnumType.STRING) @Column(nullable = true) private UserType type; ~~~ ## 不需要和數據庫映射的屬性 正常情況下我們在實體類上加入注解`@Entity`,就會讓實體類和表相關連如果其中某個屬性我們不需要和數據庫來關聯只是在展示的時候做計算,只需要加上`@Transient`屬性既可。 ~~~ @Transient private String userName; ~~~ ## 創建配置類 ~~~ import org.springframework.boot.autoconfigure.domain.EntityScan; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.transaction.annotation.EnableTransactionManagement; @Order(Ordered.HIGHEST_PRECEDENCE)//定義組件的加載順序,這里為最高級 @Configuration//表明這是一個配置類 @EnableTransactionManagement(proxyTargetClass = true)//啟用JPA的事物管理 @EnableJpaRepositories(basePackages = "com.example.springbootjpa.repository")//啟動JPA資源庫并設置接口資源庫的位置 @EntityScan(basePackages = "com.example.springbootjpa.pojo")//實體類位置 public class JpaConfiguration { /** * @Description: 這里說明為什么要聲明一個PersistenceExceptionTranslationPostProcessor 的Bean對象,引用Spring官方文檔的一句話: * (1)scanned by Spring component-scanning * (2)catch platformspecific exceptions and rethrow them as one of Spring’s unified unchecked exceptions But if you’re using Hibernate contextual sessions and not a Hibernate template,how can the exception translation take place? 翻譯過來就是:@Repository有兩作用: (1):用于被容器掃描: (2):捕獲平臺特定的異常并將它們重新拋出,作為Spring的一個未檢查的異常。(用于事務的管理,例如捕獲異常回滾) 但是,如果您使用的是Hibernate contextual sessions上下文會話而不是Hibernate template,那么異常轉換是如何發生的呢? 那么,這就是配置這個類的作用。 * @return */ @Bean PersistenceExceptionTranslationPostProcessor persistenceExceptionTranslationPostProcessor(){ return new PersistenceExceptionTranslationPostProcessor(); } } ~~~ ## @EntityScan和@EnableJpaRepositories `@EntityScan`用來掃描和發現指定包及其子包中的`Entity`定義。其用法如下: ~~~ @EntityScan(basePackages = {"com.department.entities","come.employee.entities"}) ~~~ 如果多處使用@EntityScan,它們的basePackages集合能覆蓋所有被Repository使用的Entity即可,集合有交集也沒有關系。但是如果不能覆蓋被Repository使用的Entity,應用程序啟動是會出錯,比如: > Not a managed type: com.customer.entities.Customer --- @EnableJpaRepositories 1. **basePackage用于配置掃描Repositories所在的package及子package** @EnableJpaRepositories用來掃描和發現指定包及其子包中的`Repository`定義。其用法如下: ~~~ @EnableJpaRepositories(basePackages = {"com.department.repositories","come.employee.repositories"}) ~~~ 如果多處使用@EnableJpaRepositories,它們的basePackages集合不能有交集,并且要能覆蓋所有需要的Repository定義。 如果有交集,相應的Repository會被嘗試反復注冊,從而遇到如下錯誤: ~~~ The bean ‘OrderRepository’, defined in xxx, could not be registered. A bean with that name has already been defined in xxx and overriding is disabled. ~~~ 如果不能覆蓋所有需要的Repository定義,會遇到啟動錯誤: ~~~ Parameter 0 of method setCustomerRepository in com.service.CustomerService required a bean of type ‘come.repo.OrderRepository’ that could not be found. ~~~ 2. **basePackageClasses指定 Repository類** 3. **includeFilters過濾器,該過濾區采用ComponentScan的過濾器類** 4. **excludeFilters不包含過濾器** 5. **repositoryImplementationPostfix實現類追加的尾部**, 比如ShopRepository,對應的為ShopRepositoryImpl 6. **namedQueriesLocation:named SQL存放的位置**,默認為META-INF/jpa-named-queries.properties 7. **queryLookupStrategy構建條件查詢的策略** 我們配置了多種Query,Spring Data JPA 如何來查找這些 Query 呢? 包含三種方式CREATE,USE\_DECLARED\_QUERY,CREATE\_IF\_NOT\_FOUND * CREATE:嘗試從查詢?法名構造特定于存儲的查詢。?般的?法是從?法名中刪除?組已知的前綴, 并解析?法的其余部分。 * `USE_DECLARED_QUERY`:嘗試查找已聲明的查詢,如果找不到,則拋出異常。查詢可以通過某個地 ?的注釋定義,也可以通過其他?式聲明。 * `CREATE_IFNOTFOUND`(默認):CREATE 和 `USE_DECLARED_QUERY` 的組合,它?先查找?個 已聲明的查詢,如果沒有找到已聲明的查詢,它將創建?個?定義?法基于名稱的查詢。它允許通過? 法名進?快速查詢定義,還可以根據需要引?聲明的查詢來定制這些查詢調優。 8. **repositoryFactoryBeanClass: 指定Repository的工廠類** 9. **entityManagerFactoryRef: 實體管理工廠引用名稱,對應到@Bean注解對應的方法** 10. **transactionManagerRef: 事務管理工廠引用名稱,對應到@Bean注解對應的方法** **完整的配置** ~~~ @EnableJpaRepositories( // basePackages 支持多包掃描,用文本數組的形式就可以 // 比如這樣 {"com.simply.zuozuo.repo","com.simply.zuozuo.mapper"} basePackages = { "com.simply.zuozuo.repo" }, value = {}, // 指定里面的存儲庫類 basePackageClasses = {}, // 包含的過濾器 includeFilters = { @ComponentScan.Filter(type = FilterType.ANNOTATION, value = Repository.class) }, // 不包含的過濾器 excludeFilters = { @ComponentScan.Filter(type = FilterType.ANNOTATION, value = Service.class), @ComponentScan.Filter(type = FilterType.ANNOTATION, value = Controller.class) }, // 通過什么后綴來命名實現類,比如接口A的實現,名字叫AImpl repositoryImplementationPostfix = "Impl", // named SQL存放的位置,默認為META-INF/jpa-named-queries.properties namedQueriesLocation = "", // 枚舉中有三個值, // CREATE_IF_NOT_FOUND,先搜索用戶聲明的,不存在則自動構建 // USE_DECLARED_QUERY,用戶聲明查詢 // CREATE,按照接口名稱自動構建查詢 queryLookupStrategy = QueryLookupStrategy.Key.CREATE_IF_NOT_FOUND, // 指定Repository的工廠類 repositoryFactoryBeanClass = JpaRepositoryFactoryBean.class, // 指定Repository的Base類 repositoryBaseClass = DefaultRepositoryBaseClass.class, // 實體管理工廠引用名稱,對應到@Bean注解對應的方法 entityManagerFactoryRef = "entityManagerFactory", // 事務管理工廠引用名稱,對應到@Bean注解對應的方法 transactionManagerRef = "transactionManager", // 是否考慮嵌套存儲庫 considerNestedRepositories = false, // 開啟默認事務 enableDefaultTransactions = true ) public class JPAConfig { } ~~~ # 索引 ~~~java @Entity(name = "t_user") // 定義數據庫表名稱 @Table(indexes = { // 定義數據庫索引 // 唯一索引。 @Index(name = "ux_user_login_name", columnList = "loginName", unique = true), // 非唯一索引。 @Index(name = "idx_user_age", columnList = "age"), }) public class User { ~~~ @Table 里面定義了這個表的索引, 一個 @Index 注解定義了一個索引, name 屬性表示數據庫表中索引的名稱, columnList 表示對應的 java 屬性名稱, unique = true 表示此索引是唯一索引。 比如上面的 `@Index(name = "ux_user_login_name", columnList = "loginName", unique = true)` 表示對 loginName 屬性所對應的字段(映射到數據庫表中應該是 login\_name 字段)建立唯一索引,索引名為ux\_user\_login\_name columnList 中可以放多個java屬性,中間用逗號隔開,表示聯合索引,如:`@Index(name = "idx_user_age_name", columnList = "age,loginName")` 表示建立 age 與 login\_name 字段的聯合索引 注意:** java 屬性名都是駝峰命名法(如 loginName),而數據庫表字段都是下劃線命名法(如 login\_name)**, **JPA會自動根據java屬性名的駝峰命名法映射成數據庫表字段的下劃線命名法**
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看