Springboot-Version ist 2.3.4.RELEASE
Die Persistenzschicht übernimmt JPA
Da alle Mandanten der Saas-Anwendung denselben Dienst und dieselbe Datenbank verwenden, um Mandantendaten zu isolieren, eine BaseSaasEntity wird hier erstellt
Es gibt nur ein Feld „tenantId“ inpublic abstract class BaseSaasEntity { @JsonIgnore @Column(nullable = false, updatable = false) protected Long tenantId; }
, das der Mieter-ID entspricht. Alle Mandanten-Geschäftseinheiten erben diese übergeordnete Klasse. Schließlich wird die „tenantId“ verwendet, um zu unterscheiden, zu welchem Mandanten die Daten gehören.
Wie üblich sollte nach der Erstellung der Tabelle der CURD des entsprechenden Moduls befolgt werden. Die grundlegendste Anforderung für Saas-Anwendungen ist jedoch die Isolierung der Mandantendaten, d von: Fügen Sie wheremieter=? zu allen Mandantengeschäfts-SQL hinzu, um die Mandantendatenfilterung zu implementieren.
Wenn wir unserem Unternehmen Mandanten-SQL-Filtercode hinzufügen, ist nicht nur die Arbeitsbelastung enorm, sondern auch die Fehlerwahrscheinlichkeit hoch. Ideal ist es, das gefilterte SQL-Splicing zusammenzuarbeiten und die SQL-Filterung auf der Mandanten-Geschäftsschnittstelle zu aktivieren. Da JPA von Hibernate implementiert wird, können wir hier einige Funktionen von Hibernate nutzen. Hibernate-Filter sind global gültige, benannte Filter, die Parameter annehmen können. Sie können wählen, ob ein Filter für eine bestimmte Hibernate-Sitzung aktiviert (oder deaktiviert) werden soll.
Es ist ersichtlich, dass diese Schnittstelle auf der Methode platziert ist, die der Controller-Ebene entspricht. Die Bedeutung des Hinzufügens der Transaktionsanmerkung @Transactional besteht darin, dass eine Transaktion aktiviert sein muss, um den Ruhezustandsfilter zu aktivieren. Die Standardeinstellung ist hier eine schreibgeschützte Transaktion. Definieren Sie abschließend einen Aspekt, um den Filter zu aktivierenHier definieren wir eine SQL-Filterbedingung über @FilterDef und @Filter vor. Verwenden Sie dann eine @TenantFilter-Annotation, um zu identifizieren, dass die Schnittstelle eine Datenfilterung erfordert
@MappedSuperclass @Data @FilterDef(name = "tenantFilter", parameters = {@ParamDef(name = "tenantId", type = "long")}) @Filter(condition = "tenant_id=:tenantId", name = "tenantFilter") public abstract class BaseSaasEntity { @JsonIgnore @Column(nullable = false, updatable = false) protected Long tenantId; @PrePersist public void onPrePersist() { if (getTenantId() != null) { return; } Long tenantId = TenantContext.getTenantId(); Check.notNull(tenantId, "租户不存在"); setTenantId(tenantId); } }Nach dem Login kopieren
@Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented @Transactional public @interface TenantFilter { boolean readOnly() default true; }
@Aspect @Slf4j @RequiredArgsConstructor public class TenantSQLAspect { private static final String FILTER_NAME = "tenantFilter"; private final EntityManager entityManager; @SneakyThrows @Around("@annotation(com.lvjusoft.njcommon.annotation.TenantFilter)") public Object aspect(ProceedingJoinPoint joinPoint) { Session session = entityManager.unwrap(Session.class); try { Long tenantId = TenantContext.getTenantId(); Check.notNull(tenantId, "租户不存在"); session.enableFilter(FILTER_NAME).setParameter("tenantId", tenantId); return joinPoint.proceed(); } finally { session.disableFilter(FILTER_NAME); } } }
Das obige ist der detaillierte Inhalt vonSo erstellen Sie ein mandantenfähiges Springboot-SaaS. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!