簡體   English   中英

Spring boot2 JPA SQLite的命名策略

[英]Spring boot2 JPA naming strategy for SQLite

我想用 CrudRepository 實現 spring boot 2 應用程序。 我無法弄清楚我的應用程序中的命名策略發生了什么。 當我調用存儲庫中的方法(例如 findAll())時,它會轉換數據庫中表的名稱,並且查詢崩潰。 當然,我嘗試了類似問題的解決方案: ImprovedNamingStrategy no longer working in Hibernate 5 Hibernate Naming strategy changed table names

spring boot 2.1.8 (spring-boot-starter-data-jpa)

Spring 引導完全忽略 application.properties 文件中的命名策略屬性(其他屬性運行良好)

在 spring boot 2.1.8 的源代碼中,我找到了策略道具的名稱並將它們復制到屬性中:

The fully qualified class name of the physical and the implicit strategy implementations can be configured by setting the spring.jpa.hibernate.naming.physical-strategy and spring.jpa.hibernate.naming.implicit-strategy properties, respectively. 或者,如果ImplicitNamingStrategyPhysicalNamingStrategy bean 在應用程序上下文中可用,則 Hibernate 將自動配置為使用它們。 但它不起作用。

謝謝你。

應用程序屬性

spring.application.name=file parser
driverClassName=org.sqlite.JDBC
url=jdbc:sqlite:C:\\Java\\ParseSite\\sample.db
user=admin
pass=123

#nothing works
spring.jpa.hibernate.naming.implicit-strategy=ru.laz.db.ImplicitNamingStrategyImpl
spring.jpa.hibernate.naming.physical-strategy=ru.laz.db.PhysicalNamingStrategyImpl
spring.jpa.properties.hibernate.physical_naming_strategy = ru.laz.db.PhysicalNamingStrategyImpl

spring.jpa.properties.hibernate.dialect = ru.laz.db.SQLitePrefs.SQLiteDialect

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <properties>
        <spring.boot.version>2.1.8.RELEASE</spring.boot.version>
        <java.version>1.8</java.version>
    </properties>

    <groupId>ru.laz</groupId>
    <artifactId>parse-site</artifactId>
    <version>0.1.0</version>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>${spring.boot.version}</version>
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>${spring.boot.version}</version>
        </dependency>
        <dependency>
            <groupId>org.asynchttpclient</groupId>
            <artifactId>async-http-client</artifactId>
            <version>2.2.0</version>
        </dependency>
        <dependency>
            <groupId>org.jsoup</groupId>
            <artifactId>jsoup</artifactId>
            <version>1.11.3</version>
        </dependency>
        <dependency>
            <groupId>org.xerial</groupId>
            <artifactId>sqlite-jdbc</artifactId>
            <version>3.16.1</version>
        </dependency>
        <!-- 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>${spring.boot.version}</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.10</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

新聞BlockRepo.java

@Repository
public interface NewsBlockRepo extends CrudRepository<NewsBlock,Integer> {

    //only this method works ok
    @Modifying
    @Transactional
    @Query(value = "insert or replace into news_blocks (date, title, url, body, sent) values (:date, :title, :url, :body, :sent)", nativeQuery = true)
    void insertOrIgnore(@Param("date") String date, @Param("title") String title, @Param("url") String url, @Param("body") String body, @Param("sent") int sent);
}

新聞Block.java

package ru.laz.db;


import javax.persistence.*;

@Entity
@Table(name = "news_blocks")
public class NewsBlock {

    @Id
    @Column(name = "id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
        private int id;
    @Column(name = "date")
        private String date = "";//for unique constaint in sqlite
    @Column(name = "title")
        private String title = "";
    @Column(name = "url")
        private String url = "";
    @Column(name = "body")
        private String body = "";
    @Column(name = "sent")
        private int sent = 0;

    public long getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }
    public String getDate() {
        return date;
    }

    public void setDate(String date) {
        this.date = date;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getBody() {
        return body;
    }

    public void setBody(String body) {
        this.body = body;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public int getSent() {
        return sent;
    }

    public void setSent(int sent) {
        this.sent = sent;
    }

    @Override
    public boolean equals(Object o) {
        if (o == this) return true;
        if (!(o instanceof NewsBlock)) {
            return false;
        }
        NewsBlock nb = (NewsBlock) o;
        return this.url.equals(nb.getUrl()) && this.title.equals(nb.getTitle()) && this.body.equals(nb.getBody() );
    }

    @Override
    public String toString() {
        return "date: " + date + " title: "+title + " url: " + url + " text: " + body;
    }
}

我的 PhysicalNamingStrategyImpl

    public class PhysicalNamingStrategyImpl extends PhysicalNamingStrategyStandardImpl implements Serializable {

        public static final PhysicalNamingStrategyImpl INSTANCE = new PhysicalNamingStrategyImpl();

        @Override
        public Identifier toPhysicalTableName(Identifier name, JdbcEnvironment context) {
            String nameModified = name.getText();
            // Do whatever you want with the name modification
            return new Identifier(nameModified, name.isQuoted());
        }
}

甚至 ImplicitNamingStrategyImpl

public class ImplicitNamingStrategyImpl extends ImplicitNamingStrategyJpaCompliantImpl {

        @Override
    protected Identifier toIdentifier(String stringForm, MetadataBuildingContext buildingContext) {
        return super.toIdentifier(stringForm, buildingContext);
    }
}

最后 controller 從存儲庫調用方法

    @RequestMapping("/getUnsent")
    public String getUnsent() throws Exception {
        return objectMapper.writeValueAsString(newsBlockRepo.findAll());
    }

錯誤:

org.sqlite.SQLiteException: [SQLITE_ERROR] SQL error or missing database (no such column: newsblock0_.id)

錯誤是no such column: newsblock0_.id 很明顯,它在news_block塊表中說,沒有id ,這意味着 spring-boot 考慮了您的實體 class 中的id ,因為您聲明了它。 實體 class 或多或少等於您的表。

它要求您聲明的所有變量都必須在表中,但有時您聲明的變量不需要在表中。 所以你應該表示@Transient

@Transient注解用於指示一個字段不被持久化在數據庫中。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM