【问题标题】:jpa persist() function giving error in TABLE_PER_TENANT (multi_schema) multi-tenant strategyjpa persist() 函数在 TABLE_PER_TENANT (multi_schema) 多租户策略中给出错误
【发布时间】:2017-07-23 14:37:08
【问题描述】:

我正在使用 java、jpa(eclipselink)、mysql 开发具有“共享数据库/单独模式”方法的多租户 Web 应用程序。我的持久性文件如下所示:

    <persistence-unit name="GroupBuilderPU" transaction-type="RESOURCE_LOCAL">
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
            <exclude-unlisted-classes>false</exclude-unlisted-classes>
            <properties>
                <property name="eclipselink.cache.shared.default" value="false"/>
                <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/?"/>
                <property name="eclipselink.ddl-generation" value="create-or-extend-tables"/>
<--- Here goes other properties definition -->
        </persistence-unit>

现在这里是我的 EntityMangerFactory 和 EntityManager:

emfForTenant = Persistence.createEntityManagerFactory("GroupBuilderPU");
EntityManager em = emfForTenant.createEntityManager();
        em.setProperty("eclipselink.tenant-id", schemaNameAsTenantId);

我有一个实体 MaterialUnit:

@Entity
@Multitenant(MultitenantType.TABLE_PER_TENANT)
@TenantTableDiscriminator(type = TenantTableDiscriminatorType.SCHEMA, contextProperty = PersistenceUnitProperties.MULTITENANT_PROPERTY_DEFAULT)
public class MaterialUnit implements Serializable {
    //private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @NotNull
    @Size(min = 1, max = 128)
    @Column(unique=true)
    private String unitName;

现在操作报错:

MaterialUnit mu = new MaterialUnit();
mu.setUnitName("New Unit");
em.persist(mu);

错误是:

Internal Exception: java.sql.SQLException: No database selected
Error Code: 1046
Call: UPDATE SEQUENCE SET SEQ_COUNT = SEQ_COUNT + ? WHERE SEQ_NAME = ?
    bind => [50, SEQ_GEN]
Query: ValueReadQuery(name="SEQUENCE" sql="SELECT SEQ_COUNT FROM SEQUENCE WHERE SEQ_NAME = ?")
Severe:   Local Exception Stack: 
Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLException: No database selected
Error Code: 1046
Call: UPDATE SEQUENCE SET SEQ_COUNT = SEQ_COUNT + ? WHERE SEQ_NAME = ?
    bind => [50, SEQ_GEN]
Query: ValueReadQuery(name="SEQUENCE" sql="SELECT SEQ_COUNT FROM SEQUENCE WHERE SEQ_NAME = ?")
    at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:331)

那么这个持久化操作将如何工作呢? 任何帮助或建议将不胜感激:)

【问题讨论】:

  • 逻辑会建议,如果每个租户都有不同的架构,那么每个租户都有不同的 EMF。如果您说 EclipseLink 通过一个 EMF 支持这一点,请查看他们的文档以了解您如何定义它
  • 你能推荐任何资源或任何文档吗?
  • Errm,EclipseLink 的文档。如果您选择了该实现,那么您应该能够找到您使用的软件的文档

标签: java mysql jpa multi-tenant


【解决方案1】:

错误说没有选择数据库..

我认为你的问题出在这一行:

<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/?"

当它执行时,它连接到 mysql 但不知道你需要什么模式...如果你想拥有多个模式(持久单元),我建议根据需要创建尽可能多的持久单元,像这样:

<persistence-unit name="PersistenceUnitONE" transaction-type="RESOURCE_LOCAL">
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    <exclude-unlisted-classes>false</exclude-unlisted-classes>
    <properties>
        <property name="eclipselink.cache.shared.default" value="false"/>
        <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/schema1"/>
        <property name="eclipselink.ddl-generation" value="create-or-extend-tables"/>
    </properties>
</persistence-unit>

<persistence-unit name="PersistenceUnitTWO" transaction-type="RESOURCE_LOCAL">
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    <exclude-unlisted-classes>false</exclude-unlisted-classes>
    <properties>
        <property name="eclipselink.cache.shared.default" value="false"/>
        <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/schema2"/>
        <property name="eclipselink.ddl-generation" value="create-or-extend-tables"/>
    </properties>
</persistence-unit>

然后通过更改此行来调用您需要的单元:

emfForTenant = Persistence.createEntityManagerFactory("PersistenceUnitONE");
emfForTenant = Persistence.createEntityManagerFactory("PersistenceUnitTWO");

【讨论】:

  • 在多模式策略中,可能有数百个模式(每个租户代表自己的模式),然后为每个模式(租户)添加一个持久化单元不会是一个有效的解决方案:)。不是吗?
  • 好吧,在这种情况下,您必须在 &lt;property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/?... 行中传递架构名称...否则它将不起作用
  • 但是部署完成后你不能更改persistence.xml。或者有什么办法吗?
  • jeje,老实说,我不知道这是否可能......但这就是你的问题所在...... jeje
猜你喜欢
  • 2019-04-16
  • 1970-01-01
  • 2020-08-17
  • 2012-09-24
  • 2017-11-14
  • 2012-03-31
  • 1970-01-01
  • 2016-09-07
  • 1970-01-01
相关资源
最近更新 更多