feat: 引入jpa多租户

多租户查询时,使用aop处理;新增,修改使用Hibernate Filter处理
V0.5.x
tiger 2023-07-15 23:29:47 +08:00
parent 2798c5f879
commit 5b577e3b99
12 changed files with 186 additions and 38 deletions

View File

@ -1,10 +1,16 @@
package cc.iotkit.model.system; package cc.iotkit.model.system;
import cc.iotkit.common.tenant.dao.TenantAware;
import cc.iotkit.common.tenant.listener.TenantListener;
import cc.iotkit.model.BaseModel;
import cc.iotkit.model.Id; import cc.iotkit.model.Id;
import cc.iotkit.model.TenantModel;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import org.hibernate.annotations.Filter;
import org.hibernate.annotations.FilterDef;
import org.hibernate.annotations.ParamDef;
import javax.persistence.EntityListeners;
import java.io.Serializable; import java.io.Serializable;
import java.util.Date; import java.util.Date;
@ -15,7 +21,10 @@ import java.util.Date;
*/ */
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@Data @Data
public class SysDept extends TenantModel implements Id<Long>, Serializable { @FilterDef(name = "tenantFilter", parameters = {@ParamDef(name = "tenantId", type = "string")})
@Filter(name = "tenantFilter", condition = "tenant_id = :tenantId")
@EntityListeners(TenantListener.class)
public class SysDept extends BaseModel implements Id<Long>, Serializable, TenantAware {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/** /**
@ -73,4 +82,10 @@ public class SysDept extends TenantModel implements Id<Long>, Serializable {
*/ */
private Date createTime; private Date createTime;
/**
*
*/
private String tenantId;
} }

View File

@ -1,16 +1,18 @@
package cc.iotkit.data.model; package cc.iotkit.data.model;
import cc.iotkit.common.tenant.dao.TenantAware;
import cc.iotkit.common.tenant.listener.TenantListener;
import cc.iotkit.model.system.SysConfig; import cc.iotkit.model.system.SysConfig;
import io.github.linpeilie.annotations.AutoMapper; import io.github.linpeilie.annotations.AutoMapper;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import org.hibernate.annotations.Filter;
import org.hibernate.annotations.FilterDef;
import org.hibernate.annotations.GenericGenerator; import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.ParamDef;
import javax.persistence.Entity; import javax.persistence.*;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
/** /**
* sys_config * sys_config
@ -23,7 +25,10 @@ import javax.persistence.Table;
@Entity @Entity
@Table(name = "sys_config") @Table(name = "sys_config")
@AutoMapper(target = SysConfig.class) @AutoMapper(target = SysConfig.class)
public class TbSysConfig extends BaseEntity { @FilterDef(name = "tenantFilter", parameters = {@ParamDef(name = "tenantId", type = "string")})
@Filter(name = "tenantFilter", condition = "tenant_id = :tenantId")
@EntityListeners(TenantListener.class)
public class TbSysConfig extends BaseEntity implements TenantAware {
/** /**
* *

View File

@ -1,18 +1,20 @@
package cc.iotkit.data.model; package cc.iotkit.data.model;
import cc.iotkit.common.constant.UserConstants; import cc.iotkit.common.constant.UserConstants;
import cc.iotkit.common.tenant.dao.TenantAware;
import cc.iotkit.common.tenant.listener.TenantListener;
import cc.iotkit.model.system.SysDept; import cc.iotkit.model.system.SysDept;
import io.github.linpeilie.annotations.AutoMapper; import io.github.linpeilie.annotations.AutoMapper;
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import org.hibernate.annotations.Filter;
import org.hibernate.annotations.FilterDef;
import org.hibernate.annotations.GenericGenerator; import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.ParamDef;
import javax.persistence.Entity; import javax.persistence.*;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
/** /**
* sys_dept * sys_dept
@ -26,7 +28,10 @@ import javax.persistence.Table;
@Table(name = "sys_dept") @Table(name = "sys_dept")
@AutoMapper(target = SysDept.class) @AutoMapper(target = SysDept.class)
@ApiModel(value = "部门表") @ApiModel(value = "部门表")
public class TbSysDept extends BaseEntity { @FilterDef(name = "tenantFilter", parameters = {@ParamDef(name = "tenantId", type = "string")})
@Filter(name = "tenantFilter", condition = "tenant_id = :tenantId")
@EntityListeners(TenantListener.class)
public class TbSysDept extends BaseEntity implements TenantAware {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/** /**

View File

@ -1,5 +1,6 @@
package cc.iotkit.common.tenant.dao; package cc.iotkit.common.tenant.dao;
public interface TenantAware { public interface TenantAware {
void setTenantId(String tenantId); void setTenantId(String tenantId);
} }

View File

@ -0,0 +1,82 @@
package cc.iotkit.common.tenant.entiry;
import cc.iotkit.common.tenant.dao.TenantAware;
import cc.iotkit.common.tenant.listener.TenantListener;
import lombok.Data;
import org.hibernate.annotations.Filter;
import org.hibernate.annotations.FilterDef;
import org.hibernate.annotations.ParamDef;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.annotation.LastModifiedDate;
import javax.persistence.Column;
import javax.persistence.EntityListeners;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import javax.validation.constraints.Size;
import java.io.Serializable;
import java.util.Date;
/**
* ...
*
* @author Tiger Chen
* created on 2023/7/15 20:53
*/
@MappedSuperclass
@Data
@FilterDef(name = "tenantFilter", parameters = {@ParamDef(name = "tenantId", type = "string")})
@Filter(name = "tenantFilter", condition = "tenant_id = :tenantId")
@EntityListeners(TenantListener.class)
public abstract class BaseTenantEntity implements TenantAware, Serializable {
private static final long serialVersionUID = 1L;
@Id
private Long id;
@Size(max = 30)
@Column(name = "tenant_id")
private String tenantId;
/**
*
*/
private Long createDept;
/**
*
*/
@CreatedBy
@Column(name = "create_by", updatable = false)
private Long createBy;
/**
*
*/
@CreatedDate
@Column(name = "create_time", updatable = false)
private Date createTime;
/**
*
*/
@LastModifiedBy
@Column(name = "update_by")
private Long updateBy;
/**
*
*/
@LastModifiedDate
@Column(name = "update_time")
private Date updateTime;
public BaseTenantEntity(String tenantId) {
this.tenantId = tenantId;
}
}

View File

@ -1,20 +0,0 @@
package cc.iotkit.common.tenant.exception;
import cc.iotkit.common.exception.BizException;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
*
*
* @author Lion Li
*/
@EqualsAndHashCode(callSuper = true)
@Data
public class TenantException extends BizException {
public TenantException(Integer code, String message) {
super("tenant", code, message);
}
}

View File

@ -3,7 +3,9 @@ package cc.iotkit.common.tenant.listener;
import cc.iotkit.common.satoken.utils.LoginHelper; import cc.iotkit.common.satoken.utils.LoginHelper;
import cc.iotkit.common.tenant.dao.TenantAware; import cc.iotkit.common.tenant.dao.TenantAware;
import lombok.extern.slf4j.Slf4j;
import javax.persistence.PostLoad;
import javax.persistence.PrePersist; import javax.persistence.PrePersist;
import javax.persistence.PreRemove; import javax.persistence.PreRemove;
import javax.persistence.PreUpdate; import javax.persistence.PreUpdate;
@ -15,14 +17,17 @@ import javax.persistence.PreUpdate;
* created on 2023/7/14 20:50 * created on 2023/7/14 20:50
*/ */
@Slf4j
public class TenantListener { public class TenantListener {
@PreUpdate @PreUpdate
@PreRemove @PreRemove
@PrePersist @PrePersist
@PostLoad
public void setTenant(TenantAware entity) { public void setTenant(TenantAware entity) {
final String tenantId = LoginHelper.getTenantId(); final String tenantId = LoginHelper.getTenantId();
log.info("Hibernate 监听器设置租户ID{}", tenantId);
entity.setTenantId(tenantId); entity.setTenantId(tenantId);
} }
} }

View File

@ -14,11 +14,9 @@ import cc.iotkit.system.service.ISysOssConfigService;
import cn.dev33.satoken.annotation.SaCheckPermission; import cn.dev33.satoken.annotation.SaCheckPermission;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List; import java.util.List;
@ -32,6 +30,8 @@ import java.util.List;
@Validated @Validated
@RequiredArgsConstructor @RequiredArgsConstructor
@RestController @RestController
@Controller
@ResponseBody
@RequestMapping("/resource/oss/config") @RequestMapping("/resource/oss/config")
public class SysOssConfigController extends BaseController { public class SysOssConfigController extends BaseController {

View File

@ -213,7 +213,26 @@
<groupId>cn.hutool</groupId> <groupId>cn.hutool</groupId>
<artifactId>hutool-core</artifactId> <artifactId>hutool-core</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
</dependency>
</dependencies> </dependencies>
@ -269,6 +288,18 @@
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<agents>
<agent>${project.build.directory}/spring-instrument-${spring-framework.version}.jar</agent>
<agent>${project.build.directory}/aspectjweaver-${aspectj.version}.jar</agent>
</agents>
</configuration>
</plugin>
</plugins> </plugins>
</build> </build>

View File

@ -14,7 +14,9 @@ import cc.iotkit.config.EmbeddedRedisConfig;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.cloud.openfeign.EnableFeignClients; import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.EnableLoadTimeWeaving;
import org.springframework.transaction.annotation.EnableTransactionManagement; import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.EnableWebMvc;
@ -23,7 +25,8 @@ import org.springframework.web.servlet.config.annotation.EnableWebMvc;
@EnableTransactionManagement @EnableTransactionManagement
@EnableWebMvc @EnableWebMvc
@EnableFeignClients(basePackages = {"cc.iotkit.baetyl.feign"}) @EnableFeignClients(basePackages = {"cc.iotkit.baetyl.feign"})
public class Application { @EnableLoadTimeWeaving(aspectjWeaving = EnableLoadTimeWeaving.AspectJWeaving.ENABLED)
public class Application extends SpringBootServletInitializer {
public static void main(String[] args) { public static void main(String[] args) {
System.setProperty("disabledEmbeddedEs", "true"); System.setProperty("disabledEmbeddedEs", "true");

View File

@ -0,0 +1,12 @@
<aspectj>
<weaver options="-Xreweavable -Xset:weaveJavaxPackages=true">
<include within="cc.iotkit.common.tenant.aspect.TenantFilterAspect"/>
<include within="org.hibernate.internal.SessionFactoryImpl.SessionBuilderImpl"/>
</weaver>
<aspects>
<aspect name="cc.iotkit.common.tenant.aspect.TenantFilterAspect"/>
</aspects>
</aspectj>

11
pom.xml
View File

@ -3,11 +3,20 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.11</version>
<relativePath/>
</parent>
<groupId>cc.iotkit</groupId> <groupId>cc.iotkit</groupId>
<artifactId>iotkit-parent</artifactId> <artifactId>iotkit-parent</artifactId>
<version>${revision}</version> <version>${revision}</version>
<name>${project.artifactId}</name> <name>${project.artifactId}</name>
<description>奇特物联是一个开源的物联网基础开发平台,提供了物联网及相关业务开发的常见基础功能, 能帮助你快速搭建自己的物联网相关业务平台。</description> <description>奇特物联是一个开源的物联网基础开发平台,提供了物联网及相关业务开发的常见基础功能,
能帮助你快速搭建自己的物联网相关业务平台。
</description>
<url>https://gitee.com/iotkit-open-source/iotkit-parent</url> <url>https://gitee.com/iotkit-open-source/iotkit-parent</url>
<packaging>pom</packaging> <packaging>pom</packaging>