Quarkus PanacheRepository persist() 不存储到 MySQL

问题描述 投票:0回答:1

我是 hibernate-reactive、smallrye mutini、PanacheEntity、PanacheRepository 的新手。

在高水平上我有:

  1. 租户 - 域对象(我不想在其中包含与数据库相关的代码)

  2. TenantDAO - 特定于数据库的 dao 对象

  3. SqlRepository - 存储库的基类,用于存储 dao 并映射 dao <-> 实体

  4. TenantRepository - 扩展 SqlRepository 并提供 TenantDAO 对象

  5. POST 的休息处理程序,调用存储库来存储租户信息。

这是我的代码:

Tenant.java(域实体)

package com.my.platform.model.user;

import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor
public class Tenant {
    private String id; // an application specific id (not the PanacheEntity id)
    private String name;
}

TenantDAO.java(存储在数据库中的对象):

package com.my.platform.repository.user;

import com.my.platform.model.user.Tenant;
import io.quarkus.hibernate.reactive.panache.PanacheEntity;
import jakarta.persistence.Entity;
import jakarta.persistence.Table;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Getter
@Setter
@NoArgsConstructor
@Entity
@Table(name = "Tenants")
public class TenantDAO extends PanacheEntity {
    private String entityId;
    private String name;

    public TenantDAO(Tenant tenant) {
        this.entityId = tenant.getId();
        this.shortName = tenant.getShortName();
    }

    public Tenant getEntity() {
        return new Tenant(entityId, name);
    }
}

我在同一个旧版本中也有这个文件:

package-info.java

@io.quarkus.hibernate.orm.PersistenceUnit("<default>")
package com.my.platform.repository.user;

TenantRepository.java:

package com.my.platform.repository.user;

import com.my.platform.model.user.Tenant;
import com.mys.platform.repository.impl.sql.SqlRepository;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.ws.rs.ext.Provider;

@ApplicationScoped
public class TenantRepository extends SqlRepository<Tenant, TenantDAO> {
    @Override
    public TenantDAO createDAO(Tenant tenant) {
        return new TenantDAO(tenant);
    }
}

Sql存储库:

package com.my.platform.repository.impl.sql;

import java.util.List;

import io.quarkus.hibernate.reactive.panache.PanacheRepository;
import io.quarkus.hibernate.reactive.panache.common.WithSession;
import io.smallrye.mutiny.Multi;
import io.smallrye.mutiny.Uni;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.transaction.Transactional;

@ApplicationScoped
public abstract class SqlRepository<E, DAO> implements PanacheRepository<DAO> {
    @Override
    @WithSession
    public Uni<List<E>> list() {
        return listAll().onItem().transform(entityList -> 
            entityList.stream().map(entityDao -> entityDao.getEntity()).toList()
        );
    }

    @Override
    @WithSession
    public Uni<E> findByEntityId(String id) {
        return find("entityId", id).firstResult().map(dao -> (E)dao.getEntity());
    }

    @Override
    @Transactional
    public Uni<E> add(E entity) {
        DAO dao = createDAO(entity);
        persist(dao);
        return Uni.createFrom().item(dao.getEntity());
    }

    abstract protected DAO createDAO(E);
}

REST资源方法(TenantCreationData是一个简单的POJO,用于获取租户信息):

    @POST
    @Transactional
    public Uni<Response> provision(TenantCreationData tenantCreationData) {
        Tenant tenant = new Tenant(tenantCreationData.getTenantName());
        return tenantRepository.add(tenant)
                .onItem()
                .transform(addedTenant -> (addedTenant != null) ? Response.ok(addedTenant) : Response.status(Response.Status.NOT_FOUND))
                .onItem()
                .transform(Response.ResponseBuilder::build);
    }

注:
我不完全理解@WithSession,因为我找不到很好的文档来准确解释这个会话是什么。我通过将此注释添加到 get() 方法来使代码正常工作(否则它会因某些会话中继错误而出错)。如果我向 add() 方法添加相同的 @WithSession 注释,那么我会收到一个在谷歌搜索中找不到的模糊错误 -

Error id 1aff6b15-313d-47a9-9422-97afdca21e95-1, java.lang.IllegalStateException: HR000068: This method should exclusively be invoked from a Vert.x EventLoop thread; currently running on thread 'executor-thread-1'

无论如何,上面显示的代码不会给我任何错误,但是当向它发送 HTTP 请求时会遍历包括 persist() 在内的所有代码,但它不会保存到数据库中。

我不确定这是否与会话有关—— persist() 不会抛出任何异常,但数据不会保存。与 persistAndFlush() 相同。我调试到 persist() 并深入到 AbstractJpaOperations 的 persist() 方法内部, if(!session.contains(entity)) 处的断点没有命中(见下文)。在会话处理或“会话链”方面失败?我不确定我是否完全理解这里的课程。

    public Uni<Void> persist(Uni<Mutiny.Session> sessionUni, Object entity) {
        return sessionUni.chain(session -> {
            if (!session.contains(entity)) {
                return session.persist(entity);
            }
            return Uni.createFrom().nullItem();
        });
    }

应用程序属性:

# DataSource configuration
quarkus.datasource.url=<mysql db>
quarkus.datasource.driver=com.mysql.cj.jdbc.Driver
quarkus.datasource.username=<username>
quarkus.datasource.password=<password>

# Default persistence unit
quarkus.hibernate-orm.database.generation=none
quarkus.hibernate-orm.datasource=<default>
quarkus.hibernate-orm.log.sql=true
quarkus.hibernate-orm.multitenant=SCHEMA

# Tenant persistence unit
quarkus.hibernate-orm."tenant".database.generation=none
quarkus.hibernate-orm."tenant".datasource=<default>
quarkus.hibernate-orm."tenant".log.sql=true
quarkus.hibernate-orm."tenant".multitenant=SCHEMA

# Hibernate ORM configuration
quarkus.hibernate-orm.database.generation=drop-and-create
quarkus.hibernate-orm.database.default-schema=shared

多租户配置类:

@PersistenceUnitExtension
@RequestScoped
public class DefaultTenantResolver implements TenantResolver {
    private static final String DEFAULT_TENANT = "shared";

    @Override
    public String getDefaultTenantId() {
        return DEFAULT_TENANT;
    }

    @Override
    public String resolveTenantId() {
        return DEFAULT_TENANT;
    }
}
@PersistenceUnitExtension("tenant")
@RequestScoped
public class CustomTenantResolver implements TenantResolver {
    private static final String DEFAULT_TENANT = "shared";

    @Inject
    RoutingContext context;

    @Inject
    UserService userService;

    @Override
    public String getDefaultTenantId() {
        return DEFAULT_TENANT;
    }

    @Override
    public String resolveTenantId() {
        String tenantName = context.request().getHeader("tenant");
        return tenantName;
    }
}

对我所缺少的有什么想法吗?

当我发布到我的资源时,我希望保存数据。但没有保存。

quarkus persist quarkus-panache quarkus-hibernate-reactive
1个回答
0
投票

解决了!

改变了这一点: @覆盖 @事务性 公共Uni add(E实体){ DAO dao = createDAO(实体); 坚持(dao); return Uni.createFrom().item(dao.getEntity()); }

至:

@Override
public Uni<E> add(E entity) {
    DAO dao = createDAO(entity);
    return persist(dao).onItem().transform(addedDao -> (addedDao != null) ? dao.getEntity() : null);
}
© www.soinside.com 2019 - 2024. All rights reserved.