简体   繁体   English

带有eclipse链接的多租户

[英]multi-tenant with eclipse link

I'm trying to implement a multitenant architecture, using eclipselink. 我正在尝试使用eclipselink实现多租户架构。 I have a table Entidade, the name of the Entidade will be the tenant. 我有一个表Entidade,Entidade的名称将为租户。 I have a Usuario table, where each usuario is connected to an Entidade. 我有一个Usuario表,其中每个usuario连接到一个Entidade。 The table Usuario and Entidade have a tenant default, because when login with a Usuario, I have no way to know which Entidade that Usuario belongs. 该表Usuario和Entidade具有租户默认值,因为使用Usuario登录时,我无法知道Usuario属于哪个Entidade。 By inserting the entities in the database, does not give any problem. 通过将实体插入数据库,不会出现任何问题。 The problem is to query the user class, especially when the search is made of the child class, Entidade, throw the following exception: 问题是查询用户类,尤其是在搜索子类Entidade时,抛出以下异常:

 [EL Warning]: metadata: 2013-09-18 11:39:50.976--ServerSession(20689274)--The tenant discriminator context property for the tenant discriminator column [USUARIO.id_tenant] on the element [class teste.Usuario] is being defaulted to: eclipselink.tenant-id. [EL Warning]: metadata: 2013-09-18 11:39:50.993--ServerSession(20689274)--The tenant discriminator context property for the tenant discriminator column [ENTIDADE.id_tenant] on the element [class teste.Entidade] is being defaulted to: eclipselink.tenant-id. [EL Info]: 2013-09-18 11:39:51.604--ServerSession(20689274)--EclipseLink, version: Eclipse Persistence Services - 2.5.0.v20130507-3faac2b [EL Warning]: metadata: 2013-09-18 11:39:51.823--ServerSession(20689274)--Reverting the lazy setting on the OneToOne or ManyToOne attribute [entidade] for the entity class [class teste.Usuario] since weaving was not enabled or did not occur. [EL Info]: connection: 2013-09-18 11:39:51.894--ServerSession(20689274)--file:/D:/java/workspaceweb/TesteTenant/bin/_teste login successful [EL Fine]: sql: 2013-09-18 11:39:51.93--ServerSession(20689274)--Connection(29390792)--SELECT id_usuario, id_tenant, nome, id_entidade FROM USUARIO WHERE (id_tenant = ?) bind => [usuario] [EL Warning]: 2013-09-18 11:39:51.957--ServerSession(20689274)--Exception [EclipseLink-6174] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.QueryException Exception Description: No value was provided for the session property [eclipselink.tenant-id]. This exception is possible when using additional criteria or tenant discriminator columns without specifying the associated contextual property. These properties must be set through Entity Manager, Entity Manager Factory or persistence unit properties. If using native EclipseLink, these properties should be set directly on the session. Query: ReadObjectQuery(name="readEntidade" referenceClass=Entidade sql="SELECT id_entidade, id_tenant, nome FROM ENTIDADE WHERE ((id_entidade = ?) AND (id_tenant = ?))") Exception in thread "main" javax.persistence.PersistenceException: Exception [EclipseLink-6174] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.QueryException Exception Description: No value was provided for the session property [eclipselink.tenant-id]. This exception is possible when using additional criteria or tenant discriminator columns without specifying the associated contextual property. These properties must be set through Entity Manager, Entity Manager Factory or persistence unit properties. If using native EclipseLink, these properties should be set directly on the session. Query: ReadObjectQuery(name="readEntidade" referenceClass=Entidade sql="SELECT id_entidade, id_tenant, nome FROM ENTIDADE WHERE ((id_entidade = ?) AND (id_tenant = ?))") at org.eclipse.persistence.internal.jpa.QueryImpl.getResultList(QueryImpl.java:479) at teste.TesteBuscaMain.main(TesteBuscaMain.java:29) Caused by: Exception [EclipseLink-6174] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.QueryException Exception Description: No value was provided for the session property [eclipselink.tenant-id]. This exception is possible when using additional criteria or tenant discriminator columns without specifying the associated contextual property. These properties must be set through Entity Manager, Entity Manager Factory or persistence unit properties. If using native EclipseLink, these properties should be set directly on the session. Query: ReadObjectQuery(name="readEntidade" referenceClass=Entidade sql="SELECT id_entidade, id_tenant, nome FROM ENTIDADE WHERE ((id_entidade = ?) AND (id_tenant = ?))") at org.eclipse.persistence.exceptions.QueryException.missingContextPropertyForPropertyParameterExpression(QueryException.java:260) at org.eclipse.persistence.internal.expressions.ParameterExpression.getValue(ParameterExpression.java:269) at org.eclipse.persistence.internal.databaseaccess.DatabaseCall.translate(DatabaseCall.java:1102) at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:241) at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:228) at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.selectOneRow(DatasourceCallQueryMechanism.java:714) at org.eclipse.persistence.internal.queries.ExpressionQueryMechanism.selectOneRowFromTable(ExpressionQueryMechanism.java:2777) at org.eclipse.persistence.internal.queries.ExpressionQueryMechanism.selectOneRow(ExpressionQueryMechanism.java:2730) at org.eclipse.persistence.queries.ReadObjectQuery.executeObjectLevelReadQuery(ReadObjectQuery.java:526) at org.eclipse.persistence.queries.ObjectLevelReadQuery.executeDatabaseQuery(ObjectLevelReadQuery.java:1155) at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:899) at org.eclipse.persistence.queries.ObjectLevelReadQuery.execute(ObjectLevelReadQuery.java:1114) at org.eclipse.persistence.queries.ReadObjectQuery.execute(ReadObjectQuery.java:429) at org.eclipse.persistence.internal.sessions.AbstractSession.internalExecuteQuery(AbstractSession.java:3207) at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1797) at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1779) at org.eclipse.persistence.internal.indirection.NoIndirectionPolicy.valueFromQuery(NoIndirectionPolicy.java:326) at org.eclipse.persistence.mappings.ForeignReferenceMapping.valueFromRowInternal(ForeignReferenceMapping.java:2234) at org.eclipse.persistence.mappings.OneToOneMapping.valueFromRowInternal(OneToOneMapping.java:1790) at org.eclipse.persistence.mappings.ForeignReferenceMapping.valueFromRow(ForeignReferenceMapping.java:2120) at org.eclipse.persistence.mappings.ForeignReferenceMapping.readFromRowIntoObject(ForeignReferenceMapping.java:1455) at org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildAttributesIntoObject(ObjectBuilder.java:455) at org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildObject(ObjectBuilder.java:862) at org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildWorkingCopyCloneFromRow(ObjectBuilder.java:1948) at org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildObjectInUnitOfWork(ObjectBuilder.java:726) at org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildObject(ObjectBuilder.java:629) at org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildObject(ObjectBuilder.java:587) at org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildObject(ObjectBuilder.java:571) at org.eclipse.persistence.queries.ObjectLevelReadQuery.buildObject(ObjectLevelReadQuery.java:782) at org.eclipse.persistence.queries.ReadAllQuery.registerResultInUnitOfWork(ReadAllQuery.java:848) at org.eclipse.persistence.queries.ReadAllQuery.executeObjectLevelReadQuery(ReadAllQuery.java:490) at org.eclipse.persistence.queries.ObjectLevelReadQuery.executeDatabaseQuery(ObjectLevelReadQuery.java:1155) at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:899) at org.eclipse.persistence.queries.ObjectLevelReadQuery.execute(ObjectLevelReadQuery.java:1114) at org.eclipse.persistence.queries.ReadAllQuery.execute(ReadAllQuery.java:402) at org.eclipse.persistence.queries.ObjectLevelReadQuery.executeInUnitOfWork(ObjectLevelReadQuery.java:1202) at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2894) at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1797) at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1779) at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1744) at org.eclipse.persistence.internal.jpa.QueryImpl.executeReadQuery(QueryImpl.java:258) at org.eclipse.persistence.internal.jpa.QueryImpl.getResultList(QueryImpl.java:468) ... 1 more 

the class that create a EntityManagerFactory and the EntityManager: 创建EntityManagerFactory和EntityManager的类:


public class JPAUtil {

    private static JPAUtil instance = null;

    private static EntityManagerFactory emf;
    private static EntityTransaction transaction;

    private static ThreadLocal entityManagers = new ThreadLocal();

    static {
        instance = new JPAUtil();
    }

    private JPAUtil() {
        emf = Persistence.createEntityManagerFactory("PUAequalis");
    }

    public static JPAUtil getInstance() {

        if (instance == null) {
            instance = new JPAUtil();
        }
        return instance;
    }

    public static void openEntityManager(String tenant) {
        if (entityManagers == null || entityManagers.get() == null
                || !entityManagers.get().isOpen()) {
            HashMap properties = new HashMap();

            EntityManager em = emf.createEntityManager();
            em.setProperty("eclipselink.tenant-id", tenant);
            em.setProperty(PersistenceUnitProperties.MULTITENANT_PROPERTY_DEFAULT, tenant);
            entityManagers.set(em);

        } else {
            closeOpenEntityManager(tenant);
        }
    }

    public EntityManager getEntityManager() {
        return entityManagers.get();
    }

    public static void closeEntityManager() {

        if (entityManagers != null && entityManagers.get().isOpen()) {
            entityManagers.get().close();
        }
    }

    public static void closeOpenEntityManager(String tenant) {
        if (entityManagers != null && entityManagers.get().isOpen()) {
            entityManagers.get().close();
            entityManagers.remove();
            HashMap properties = new HashMap();
            properties.put("eclipselink.tenant-id", tenant);
            entityManagers.set(emf.createEntityManager(properties));
        }
    }

    public static void closeEntityManagerFactory() {
        if (emf != null && emf.isOpen()) {
            emf.close();
        }
    }

    public EntityTransaction getTransaction() {
        if (transaction == null || !transaction.isActive()) {
            transaction = entityManagers.get().getTransaction();
        }
        return transaction;
    }

}

the persistence.xml: persistence.xml:

  <?xml version="1.0" encoding="UTF-8"?> <persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> <persistence-unit name="teste" transaction-type="RESOURCE_LOCAL"> <provider> org.eclipse.persistence.jpa.PersistenceProvider</provider> <exclude-unlisted-classes>false</exclude-unlisted-classes> <properties> <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/teste" /> <property name="javax.persistence.jdbc.user" value="root" /> <property name="javax.persistence.jdbc.password" value="root" /> <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" /> <property name="eclipselink.multitenant.tenants-share-cache" value="true" /> <!-- <property name="eclipselink.ddl-generation" value="create-tables" /> --> <property name="eclipselink.logging.level.sql" value="ALL" /> <property name="eclipselink.logging.parameters" value="true" /> <property name="eclipselink.logging.session" value="true"/> </properties> </persistence-unit> </persistence> 

and de Entities: 和实体:



    @Entity
    @Multitenant
    @TenantDiscriminatorColumn(name = "id_tenant")
    public class Entidade implements Serializable {

    private static final long serialVersionUID = 8179478584980079687L;

    @Id
    @Column(name = "id_entidade", length = 10)
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer idEntidade;

    @Column(name = "nome")
    private String nome;

    @Column(name = "id_tenant", insertable=false, updatable=false)
    private String idTenant;

    ...get and setters

}


    @Entity
    @Multitenant
    @TenantDiscriminatorColumn(name = "id_tenant")
    public class Usuario implements Serializable {
    private static final long serialVersionUID = 8956344014336399968L;
    @Id
    @Column(name = "id_usuario", length = 10)
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer idUsuario;

    @Column(name = "nome")
    private String nome;

    @Column(name = "senha")
    private String senha;

    @Column(name = "nomeCompleto")
    private String nomeCompleto;

    @Column(name = "email")
    private String email;

    @Column(name = "tipo_usuario")
    @Enumerated(EnumType.STRING)
    private TipoUsuario tipoUsuario;

    @ManyToOne(fetch = FetchType.LAZY,cascade = CascadeType.ALL, optional = false, targetEntity = Entidade.class)
    @JoinColumn(name = "id_entidade")
    private Entidade entidade;

    @Column(name = "id_tenant", insertable = false, updatable = false)
    private String idTenant;

    ...get and setters
    }

has anyone had this problem? 有人遇到过这个问题吗?

That's probably because you need to set the context-property with the tenant value AFTER the begin of transaction. 这可能是因为您需要在交易开始后使用承租人值设置上下文属性。

http://codecrafters.blogspot.it/2013/03/multi-tenant-cloud-applications-with.html http://codecrafters.blogspot.it/2013/03/multi-tenant-cloud-applications-with.html

Let me know... 让我知道...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM