YashanDB持久化框架操纵示例(jpa-hibernate)

打印 上一主题 下一主题

主题 900|帖子 900|积分 2700

1.背景先容

根本概念:
1.JPA(Java Persistence API)是一种标准化的Java ORM(对象关系映射)规范,它定义了一套用于对象和关系数据库之间举行映射的API。 
2.Spring Data JPA是Spring框架对JPA的封装,它通过提供一系列接口和注解,简化了开发者对JPA的使用。
上风:
1.简化数据访问层开发:Spring Data JPA提供了一个自动天生常见数据访问层代码的机制,开发者只需要定义接口和方法命名规则,无需编写详细的实现代码。
2.提高代码的可读性:借助Spring Data JPA提供的接口和方法命名规则,开发者可以通过简朴的方法命名来实现复杂的查询功能,使代码更加简洁和可读。
3.支持多种数据源:Spring Data JPA支持多种数据源(如关系数据库、NoSQL数据库等),开发者可以通过简朴的配置切换数据源。
4.集成其他Spring组件:Spring Data JPA可以很方便地与其他Spring组件(如Spring MVC、Spring Boot等)集成,提供一体化的开发体验。
应用场景 在应用步伐开发中,Spring Data JPA可以用于处理各种数据库操纵,包罗增编削查、复杂查询、分页等。开发者只需要定义实体类和接口,Spring Data JPA会根据方法命名规则自动天生详细的查询语句。此外,Spring Data JPA还支持事务管理,可以包管数据库操纵的同等性和完备性。极大地简化了数据访问层的开发,提高了开发效率和代码质量。
2.环境阐明

以使用Maven为例:

Java环境:Jdk22(安装后需配置)

hibernate-core版本:6.5.2.Final

Springboot版本:3.3.2

Maven版本:3.9.8(安装后需配置)

崖山驱动版本:1.6.9  (官网下载)

Maven的pom.xml文件:(用于验证整个jpa-hibernate与YashanDB的兼容性,以是涵盖很多的依赖包,如只需其中一种大概几种功能,保存相应的依赖即可。)

  1. <parent>
  2.     <groupId>org.springframework.boot</groupId>
  3.     <artifactId>spring-boot-starter-parent</artifactId>
  4.     <version>3.3.2</version>
  5. </parent>
  6. <dependencies>
  7.     <dependency>
  8.         <groupId>org.springframework.boot</groupId>
  9.         <artifactId>spring-boot-starter</artifactId>
  10.     </dependency>
  11.     <dependency>
  12.         <groupId>org.springframework.boot</groupId>
  13.         <artifactId>spring-boot-starter-test</artifactId>
  14.         <scope>test</scope>
  15.     </dependency>
  16. <dependency>
  17.         <groupId>org.springframework.boot</groupId>
  18.         <artifactId>spring-boot-starter-actuator</artifactId>
  19.     </dependency>
  20.     <dependency>
  21.         <groupId>org.springframework.boot</groupId>
  22.         <artifactId>spring-boot-starter-data-jpa</artifactId>
  23.     </dependency>
  24.     <dependency>
  25.         <groupId>org.projectlombok</groupId>
  26.         <artifactId>lombok</artifactId>
  27.     </dependency>
  28.     <dependency>
  29.         <groupId>org.junit.jupiter</groupId>
  30.         <artifactId>junit-jupiter-api</artifactId>
  31.         <version>5.10.2</version>
  32.         <scope>test</scope>
  33.     </dependency>
  34.     <dependency>
  35.         <groupId>junit</groupId>
  36.         <artifactId>junit</artifactId>
  37.         <version>4.13.2</version>
  38.         <scope>test</scope>
  39.     </dependency>
  40.     <dependency>
  41.         <groupId>org.testng</groupId>
  42.         <artifactId>testng</artifactId>
  43.         <version>RELEASE</version>
  44.         <scope>test</scope>
  45.     </dependency>
  46.    </dependencies>
复制代码

3.添加YashanDB驱动


打开Idea的ProjectStructure,使用Libraries添加YashanDB驱动,对于多模块,只需要添加到对应的模块即可。(YashanDB驱动:在产品软件包或安装目录的Drivers文件夹中,查找yasdb-jdbc-版本号.jar文件,比方yasdb-jdbc-1.6.9.jar)

也可以将YashanDB驱动上传到本地的Maven私服,然后在Pom文件中引入。

注:若maven无法识别,直接在工程目录下建一个lib文件夹,把jar包放进去,然后引进来

  1. <dependency>
  2.         <groupId>com.yashandb</groupId>
  3.         <artifactId>yashandb-jdbc</artifactId>
  4.         <version>1.6.9</version>
  5.         <scope>system</scope>
  6.         <systemPath>${project.basedir}/lib/yashandb-jdbc-1.6.9.jar</systemPath>
  7. <!--项目根目录下的lib文件夹下-->
  8.     </dependency>
复制代码
4.数据源和jpa-hibernate配置

本文采用application.properties文件举行参数配置。请将下例中的host_ip、port、dbname、username和password修改为实际值。 

  1. spring.application.name=demo
  2. spring.datasource.url=jdbc:yasdb://127.0.0.1:1688/yasdb
  3. spring.datasource.username=regress
  4. spring.datasource.password=regress
  5. spring.datasource.driver-class-name=com.yashandb.jdbc.Driver
  6. #方言设置
  7. spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.OracleDialect
  8. #是否自动建表
  9. spring.jpa.properties.hibernate.hbm2ddl.auto=create
  10. #字段名和数据库中对象名的映射关系:
  11. spring.jpa.properties.hibernate.naming-strategy=org.hibernate.cfg.ImprovedNamingStrategy
  12. spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults = false
复制代码
5.jpa-hibernate功能验证

创建entity

创建User用户的entity,并使其与Table对应。

  1. package com.example.pojo;
  2. import lombok.Data;
  3. import org.hibernate.annotations.ColumnDefault;
  4. import jakarta.persistence.*;
  5. @Data
  6. @Entity
  7. @Table(name = "user1")
  8. public class User {
  9.     @Id //hibernate要求必须要一个id(主键),不然会报错
  10.     @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "ID_GENERATOR")
  11.     @SequenceGenerator(name = "ID_GENERATOR", sequenceName = "user_sequence")
  12.     @ColumnDefault("user_sequence.nextval")
  13.     private int id;
  14.     @Column(name = "name")
  15.     private String name;
  16.     public User() {
  17.     }
  18.     public User(String name) {
  19.         this.name = name;
  20.     }
  21.     public User(int id, String name) {
  22.         this.id = id;
  23.         this.name = name;
  24.     }}
复制代码
定义Repository接口,可以继承JpaRepository,也可以继承CrudRepository,视个人使用习惯大概团队要求自由选择,本例子中使用JpaRepository:

  1. package com.example.dao;
  2. import com.example.pojo.User;
  3. import org.springframework.data.jpa.repository.JpaRepository;
  4. import org.springframework.stereotype.Repository;
  5. @Repository
  6. public interface UserRepository extends JpaRepository<User,Integer> {//注意JpaRepository<User,Integer>这里传入的泛型类型,第一个是我们上面定义的Entity,第二个是Entity的主键的类型//里面可以不实现任何接口,JpaRepository的默认接口已经足够我们使用了。}
复制代码
主类

  1. package com.example.demo;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. import org.springframework.boot.autoconfigure.domain.EntityScan;
  5. import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
  6. @SpringBootApplication
  7. @EnableJpaRepositories(basePackages = "com.example.dao")
  8. @EntityScan(basePackages = "com.example.pojo")
  9. public class DemoApplication {
  10.     public static void main(String[] args) {
  11.         SpringApplication.run(DemoApplication.class, args);
  12.     }
  13. }
复制代码
创建单元测试类

  1. package com.example;
  2. import com.example.dao.UserRepository;
  3. import com.example.pojo.User;
  4. import org.junit.Before;
  5. import org.junit.Test;
  6. import org.junit.runner.RunWith;
  7. import org.springframework.beans.factory.annotation.Autowired;
  8. import org.springframework.boot.test.context.SpringBootTest;
  9. import org.springframework.test.context.junit4.SpringRunner;
  10. import java.util.List;
  11. import static org.junit.Assert.assertEquals;
  12. @RunWith(SpringRunner.class)
  13. @SpringBootTest
  14. public class UserTest {
  15.     @Autowired
  16.     private UserRepository repository;
  17.     @Before
  18.     public void deleteAllUser(){
  19.         repository.deleteAll();
  20.     }
  21.     @Test
  22.     public void testAddUser() {
  23.         User user = new User("sasa");
  24.         repository.save(user);
  25.         List<User> list = repository.findAll();
  26.         assertEquals(1, list.size());
  27.     }}
复制代码
6.常见问题

(1) 重新加载maven项目后YashanDB驱动包丢失

通过Libraries添加的YashanDB驱动和方言包在重新加载maven项目后可能会丢失导致报错

解决方法:直接在工程目录下建一个lib文件夹,把jar包放进去,然后引进来

  1. <dependency>
  2.         <groupId>com.yashandb</groupId>
  3.         <artifactId>yashandb-jdbc</artifactId>
  4.         <version>1.6.9</version>
  5.         <scope>system</scope>
  6.         <systemPath>${project.basedir}/lib/yashandb-jdbc-1.6.9.jar</systemPath>
  7. <!--项目根目录下的lib文件夹下-->
  8. </dependency>
复制代码
(2)Spring Data JPA 非常 “IllegalArgumentException: Not a Managed Type”

有如下两种可能出现的环境:
1.从 javax.persistance 迁徙jakarta.persistance

在将应用迁徙到 Jakarta Persistence API 时,可能会碰到这种非常环境。

重现问题

假设有如下实体:

  1. import jakarta.persistence.Entity;
  2. import jakarta.persistence.Id;
  3. @Entity
  4. public class EntityWithJakartaAnnotation {    
  5. @Id    
  6. private Long id;
  7. }
复制代码
如上,使用了 jakarta.persistence 包,但我们仍在使用  Spring Boot 2,再以与上一节雷同的方式创建 Repository 和 Application 类,运行后,“Not a managed type” 非常出现。 JPA 实体扫描器(Entity Scanner)希望我们使用 javax.persistence.Entity 注解,而不是 jakarta.persistence.Entity 注解。

修复问题

在这种环境下,有两种可能的解决方案。

1.升级到  Spring Boot 3,然后使用 jakarta.persistence。
2.如果还没准备好升级,就继续使用 javax.persistence.Entity。
2.缺少或错误配置了 @EntityScan

另一种可能碰到 “Not a managed type” 非常的常见环境是, JPA 实体扫描器(Entity Scanner)无法在预期路径中找到实体。

重现问题

首先,创建另一个实体:

  1. package com.baeldung.spring.entity;
  2. @Entity
  3. public class CorrectEntity {    
  4. @Id    
  5. private Long id;
  6. }
复制代码
它带有 @Entity 注解,并被置于 entity 包中。现在,创建一个 Repository:

  1. package com.baeldung.spring.repository;
  2. public interface CorrectEntityRepository extends JpaRepository<CorrectEntity, Long> {
  3. }
复制代码
Repository 接口放在 repository 包中。最后,创建一个 Application 类:

  1. package com.baeldung.spring.app;
  2. @SpringBootApplication
  3. @EnableJpaRepositories(basePackages = "com.baeldung.spring.repository")
  4. public class WrongEntityScanApplication {
  5. }
复制代码
它在 app 包中。默认环境下, Spring Data 会扫描 main 类所在包及其子包下的 Repository 接口。因此,我们需要使用 @EnableJpaRepositories 的 basePackages 属性指定 Repository 接口所在的包。云云运行后,再次碰到了 “Not a managed type” 非常。原因是实体扫描的逻辑与 Repository 扫描的逻辑相同。我们扫描了 app 包下的组件,但没有发现任何实体,因此在构建 CorrectEntityRepository 时出现了非常。

修复问题

要解决这个问题,可以使用 @EntityScan 注解。

再创建一个 Application 类:

  1. @SpringBootApplication
  2. @EnableJpaRepositories(basePackages =  "com.baeldung.spring.repository")
  3. @EntityScan("com.baeldung.spring.entity")
  4. public class WrongEntityScanFixedApplication {
  5. }
复制代码
如上,使用 @EnableJpaRepositories 注解指定 Repository 所在包,并使用 @EntityScan 注解指定实体包。

测试通过。我们从 Context 中成功获取到了 CorrectEntityRepository,并且 CorrectEntity 已被成功识别为  JPA 实体。

(3) 自增主键的使用

一般环境下,在使用Hibernate持久化框架时,需要定义Entity实体类,实体类中存在一个Id属性,将该属性作为业务表的自增主键列,示比方下:
  1. @Id
  2. @SequenceGenerator(name="generator",sequenceName="user_sequence", allocationSize =1)
  3. @ColumnDefault("user_sequence.nextval")
  4. @GeneratedValue(strategy= GenerationType.AUTO, generator = "generator")
  5. private int id;
复制代码
在上述示例中,user_sequence为序列名,由您自定义命名。
   Note:
  

  • 注意保持@SequenceGenerator参数sequenceName和@ColumnDefault中的序列名称同等。
  • 如果sequenceName指定的序列名是驼峰格式,hibernate会把它改成下划线,和表名,列名等一样处理;但是@ColumnDefault这个注解的value是不处理驼峰格式的,以是就会导致sequenceName和ColumnDefault里面序列器名称差别等,启动时建表会失败,以是注意这里不要用驼峰命名,直接用下划线风格命名。
  此外,也可以不指定@ColumnDefault,和@SequenceGenerator。
这时hibernate使用默认序列hibernate_sequence去自增,示比方下:
  1. @Id
  2. @GeneratedValue(strategy= GenerationType.AUTO)
  3. private int id;
复制代码
(4) 服务启动失败

使用hibernate配置hbm2ddl.auto=validate时,服务启动时会举行校验;当数据库表结构数据类型与Java实体类数据类型差别等时,Schema-validation校验失败;从而导致容器初始化Hibernate SessionFactory时失败。
  1. spring.jpa.properties.hibernate.hbm2ddl.auto=validate
复制代码
出现这个问题时,我们需要修改数据库表结构,或修改Java实体类数据类型,保持数据库表结构与Java实体类数据类型同等。
大概,将hbm2ddl.auto配置设置为none,服务启动时不举行校验。
(5) 不支持TEXT数据类型

MySQL迁徙前,业务中可能使用了TEXT这一数据类型,示比方下:
  1. @Column(name = "file_types", columnDefinition = "TEXT")
  2. private String fileTypes;
复制代码
迁徙后,YashanDB不支持TEXT数据类型,导致报错。
YashanDB虽不支持TEXT类型,但支持CLOB类型,用于保存大量字符数据。因此,建议将TEXT改为CLOB,即columnDefinition = "TEXT"改为columnDefinition = "CLOB"。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

傲渊山岳

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表