H2 - Long um eins falsch

krgewb

Top Contributor
Ich habe eine H2-Datenbank mit einer Tabelle namens Project.
Die Id (long) endet mit 80, aber wenn ich sie aus der DB hole und ausgebe, endet sie mit 81.

Ausschnitt aus dem RestController:
Java:
@RequestMapping(value = "get_projects", method = RequestMethod.POST)
public List<ProjectDTO> get_projects(HttpSession session) {
    logger.info("ProjectRestController.get_projects() called");
    return service.findAllProjects();
}
 

mrBrown

Super-Moderator
Mitarbeiter
Ganz spontan: irgendwo hast du wahrscheinlich irgendwas falsch gemacht :) Warum bist du dir denn sicher, dass die ID auf 80 und nicht doch auf 81 endet?


Du könntest über die h2-Web-Console mal direkt die Datenbank ansprechen, was genau dort hinterlegt ist. Ansonsten wären zumindest die SQL-Querys und die Entitäten interessant, der Controller hilft da am wenigsten :)
 

krgewb

Top Contributor
Ich habe das Problem auch ohne H2. Bei H2 ist es aber krasser. Die ID ist z.B. 2056919897295828992, aber da steht 2056919897295829000.



Java:
import javax.persistence.*;
import java.util.Date;

@Entity
@Table(name = "project")
public class ProjectEntity {

    @Id
    private Long id;

    @Column(name = "caption", nullable = false)
    private String caption;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getCaption() {
        return caption;
    }

    public void setCaption(String caption) {
        this.caption = caption;
    }

    @Transient
    public static ProjectEntity loadFromDTO(ProjectDTO dto) {
        ProjectEntity entity = new ProjectEntity();
        entity.setId(dto.getId());
        entity.setCaption(dto.getCaption());
        return entity;
    }

}

Java:
import java.io.Serializable;
import java.util.Date;

public class ProjectDTO implements Serializable {

    private Long id;
    private String caption;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getCaption() {
        return caption;
    }

    public void setCaption(String caption) {
        this.caption = caption;
    }
}

Java:
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface ProjectRepository extends JpaRepository<ProjectEntity, Long> {

}

Java:
@Override
public List<ProjectDTO> findAllProjects() {
    List<ProjectEntity> result = projectRepository.findAll();
    return ProjectWrapper.toDTO(result);
}

Java:
@POST
@Path("get_projects")
void get_projects(UsermanagementAbstractDisplayCallback<List<ProjectDTO>> async);

Java:
import java.util.ArrayList;
import java.util.List;

public class ProjectWrapper {

    public static List<ProjectDTO> toDTO(List<ProjectEntity> entities) {
        List<ProjectDTO> dtos = new ArrayList<>();
        for (ProjectEntity entity : entities) {
            dtos.add(ProjectWrapper.toDTO(entity));
        }
        return dtos;
    }

    public static ProjectDTO toDTO(ProjectEntity entity) {
        if (entity == null) {
            return null;
        }
        ProjectDTO dto = new ProjectDTO();
        dto.setId(entity.getId());
        dto.setCaption(entity.getCaption());
        return dto;
    }

}
 

mrBrown

Super-Moderator
Mitarbeiter
Die ID ist z.B. 2056919897295828992, aber da steht 2056919897295829000.
Warum bist du der Meinung, dass die ID eigentlich 2_056_919_897_295_828_992 ist?
Wo steht 2_056_919_897_295_829_000?
Wie schreibst du in die Datenbank?


Einfach blind hingeklatschter Java-Code ist dabei keine Hilfe. Entweder ein ganzes, ausführbares Projekt, mit dem man den Fehler nachstellen kann – oder detaillierte Antworten auf gestellte Fragen.
 

LimDul

Top Contributor
Ergänzend - die ID ist nicht als GeneratedValue annotiert (und hat dementsprechend einen setter). Wann und wo wird überall dieser Setter aufgerufen. Denn im DTO wird das drinstehen, was in der Entität drinsteht.

Dadurch das kein GeneratedValue dran steht, musst du ja irgendwo selber implementiert haben, wie die ID gesetzt wird. Und entweder wird die Methode zu oft oder nicht korrekt aufgerufen. Gibt es einen Grund Long zu nehmen und denn nicht als GeneratedValue zu setzen?

Gefühlt hat man damit zwar den Vorteil, dass ich eine ID habe, bevor es persistiert ist, aber auch immense Nachteile: Ich muss selber sicherstellen, dass die IDs konsistent sind, auch ggf. bei Clusterung, Neustarts, Multi-Threading etc.

Normalerweise kenne ich so - entweder Long + GeneratedValue oder Selber Setzen als UUID.
 

krgewb

Top Contributor
Wo steht 2_056_919_897_295_829_000?
In den Entwicklerwerkzeugen von Firefox unter Netzwerkanalyse -> get_projects -> Antwort.

@LimDul
Ich erstelle den Long-Wert per Zufall. In Zukunft versuche ich es mit Strings und UUID. Ich möchte aber trotzdem meinen Fehler verstehen.

Es ist zwar absolut möglich, aber sehr unwahrscheinlich, dass so viele der zufällig erzeugten Werte mit 000 enden.
Java:
long randomNumber = 1 + (long) (Math.random() * (Long.MAX_VALUE - 1));

Ich schreibe im Backend wie folgt in die Datenbank:
Java:
@Override
public void saveProjectEntry(ProjectDTO dto) {
    projectRepository.save(ProjectEntity.loadFromDTO(dto));
}

Ich wollte gerade mit IntelliJ in die Datenbank schauen, aber meine Zugangsdaten werden plötzlich nicht mehr akzeptiert.
User: sa
Password:
URL: jdbc:h2:~/test

Die Anwendung kann aber auf die Datenbank zugreifen. In der application.properties steht:
Java:
spring.h2.console.enabled=true
spring.datasource.url=jdbc:h2:file:~/test;DB_CLOSE_ON_EXIT=FALSE;AUTO_SERVER=TRUE
spring.datasource.username=sa
spring.datasource.password=
spring.datasource.driver-class-name=org.h2.Driver
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect
 

mrBrown

Super-Moderator
Mitarbeiter
Ne, du hast bisher kein Mal gesagt, woher du die "ID die es eigentlich sein sollts" kennst. Du hast nur mehrmals erwähnt, dass nur die falsche angezeigt wird, aber woher du die richtige kommst oder weißt, dass die richtige anders ist, hast du bisher verschwiegen.
 

LimDul

Top Contributor
An welcher Stelle im Programmablauf ist welche ID vorhanden. Die Aussage fehlt.

Dein gezeigter Code sagt - in der DB wird die ID gespeichert, die im DTO steht. Du sagst nein, aber woher kommt diese Info?
Soweit ich das sehe wird eine per Request übergebene Entität gespeichert

* Welcher Request wird abgeschickt? Welche ID steht in dem Request?
* Welche ID steht im DTO?
* Welche ID steht in der Entität?
* Welche ID steht in der Datenbank
 
K

kneitzel

Gast
Ich erstelle den Long-Wert per Zufall. In Zukunft versuche ich es mit Strings und UUID. Ich möchte aber trotzdem meinen Fehler verstehen.
Das scheint mir ein sehr schlechter Weg zu sein. Für kleine Tests oder Spielereien mag die Chance, eine ID doppelt zu haben, zwar gering zu sein, aber da könnte man auch jede andere vernünftige ID vergeben.

Aber das nur am Rande ans Anmerkung.
 

Ähnliche Java Themen

Neue Themen


Oben