完成spring jpa的存储适配
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
package com.lanyuanxiaoyao.flowable.jpa;
|
||||
|
||||
import com.lanyuanxiaoyao.flowable.core.manager.FlowableManager;
|
||||
import com.lanyuanxiaoyao.flowable.core.repository.FlowableRepository;
|
||||
import java.util.UUID;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* @author lanyuanxiaoyao
|
||||
* @version 20241231
|
||||
*/
|
||||
@Service
|
||||
public class SpringFlowableManager extends FlowableManager {
|
||||
public SpringFlowableManager(FlowableRepository flowableRepository) {
|
||||
super(flowableRepository, () -> UUID.randomUUID().toString());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
package com.lanyuanxiaoyao.flowable.jpa;
|
||||
|
||||
import com.lanyuanxiaoyao.flowable.core.model.FlowableHistory;
|
||||
import com.lanyuanxiaoyao.flowable.core.model.FlowableInstance;
|
||||
import com.lanyuanxiaoyao.flowable.core.model.FlowableNode;
|
||||
import com.lanyuanxiaoyao.flowable.core.repository.FlowableRepository;
|
||||
import com.lanyuanxiaoyao.flowable.jpa.entity.JpaFlowableHistory;
|
||||
import com.lanyuanxiaoyao.flowable.jpa.entity.JpaFlowableInstance;
|
||||
import com.lanyuanxiaoyao.flowable.jpa.entity.JpaFlowableNode;
|
||||
import com.lanyuanxiaoyao.flowable.jpa.repository.JpaFlowableHistoryRepository;
|
||||
import com.lanyuanxiaoyao.flowable.jpa.repository.JpaFlowableInstanceRepository;
|
||||
import com.lanyuanxiaoyao.flowable.jpa.repository.JpaFlowableNodeRepository;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.transaction.Transactional;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* @author lanyuanxiaoyao
|
||||
* @version 20241231
|
||||
*/
|
||||
@Service
|
||||
public class SpringJpaFlowableRepository implements FlowableRepository {
|
||||
private final JpaFlowableNodeRepository jpaFlowableNodeRepository;
|
||||
private final JpaFlowableInstanceRepository jpaFlowableInstanceRepository;
|
||||
private final JpaFlowableHistoryRepository jpaFlowableHistoryRepository;
|
||||
|
||||
public SpringJpaFlowableRepository(JpaFlowableNodeRepository jpaFlowableNodeRepository, JpaFlowableInstanceRepository jpaFlowableInstanceRepository, JpaFlowableHistoryRepository jpaFlowableHistoryRepository) {
|
||||
this.jpaFlowableNodeRepository = jpaFlowableNodeRepository;
|
||||
this.jpaFlowableInstanceRepository = jpaFlowableInstanceRepository;
|
||||
this.jpaFlowableHistoryRepository = jpaFlowableHistoryRepository;
|
||||
}
|
||||
|
||||
@Transactional(rollbackOn = Exception.class)
|
||||
@Override
|
||||
public void saveNode(FlowableNode node) {
|
||||
jpaFlowableNodeRepository.save(new JpaFlowableNode(node));
|
||||
}
|
||||
|
||||
@Transactional(rollbackOn = Exception.class)
|
||||
@Override
|
||||
public void saveNode(List<FlowableNode> nodes) {
|
||||
jpaFlowableNodeRepository.saveAll(nodes.stream().map(JpaFlowableNode::new).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public FlowableNode getNode(String nodeId) {
|
||||
return jpaFlowableNodeRepository.findById(nodeId)
|
||||
.map(JpaFlowableNode::toFlowableNode)
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FlowableNode> listNodes() {
|
||||
return jpaFlowableNodeRepository.findAll()
|
||||
.stream()
|
||||
.map(JpaFlowableNode::toFlowableNode)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Transactional(rollbackOn = Exception.class)
|
||||
@Override
|
||||
public void saveInstance(FlowableInstance instance) {
|
||||
jpaFlowableInstanceRepository.save(new JpaFlowableInstance(instance));
|
||||
}
|
||||
|
||||
@Override
|
||||
public FlowableInstance getInstance(String instantId) {
|
||||
return jpaFlowableInstanceRepository.findById(instantId)
|
||||
.map(JpaFlowableInstance::toFlowableInstance)
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FlowableInstance> listInstances() {
|
||||
return jpaFlowableInstanceRepository.findAll()
|
||||
.stream()
|
||||
.map(JpaFlowableInstance::toFlowableInstance)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Transactional(rollbackOn = Exception.class)
|
||||
@Override
|
||||
public void saveHistory(FlowableHistory history) {
|
||||
jpaFlowableHistoryRepository.save(new JpaFlowableHistory(history));
|
||||
}
|
||||
|
||||
@Override
|
||||
public FlowableHistory getHistory(String historyId) {
|
||||
return jpaFlowableHistoryRepository.findById(historyId)
|
||||
.map(JpaFlowableHistory::toFlowableHistory)
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FlowableHistory> listHistories(String instanceId) {
|
||||
return jpaFlowableHistoryRepository.findAllByInstanceId(instanceId)
|
||||
.stream()
|
||||
.map(JpaFlowableHistory::toFlowableHistory)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Transactional(rollbackOn = Exception.class)
|
||||
@Override
|
||||
public void saveInstanceAndHistory(FlowableInstance instance, FlowableHistory history) {
|
||||
saveInstance(instance);
|
||||
saveHistory(history);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.lanyuanxiaoyao.flowable.jpa.entity;
|
||||
|
||||
import com.lanyuanxiaoyao.flowable.core.model.FlowableAction;
|
||||
import com.lanyuanxiaoyao.flowable.core.model.FlowableHistory;
|
||||
import java.time.LocalDateTime;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.EntityListeners;
|
||||
import javax.persistence.EnumType;
|
||||
import javax.persistence.Enumerated;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
import org.hibernate.annotations.DynamicUpdate;
|
||||
import org.springframework.data.annotation.CreatedDate;
|
||||
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
|
||||
|
||||
/**
|
||||
* @author lanyuanxiaoyao
|
||||
* @version 20250102
|
||||
*/
|
||||
@NoArgsConstructor
|
||||
@ToString
|
||||
@Getter
|
||||
@Setter
|
||||
@Entity
|
||||
@Table(name = "flowable_history")
|
||||
@DynamicUpdate
|
||||
@EntityListeners(AuditingEntityListener.class)
|
||||
public class JpaFlowableHistory {
|
||||
@Id
|
||||
private String historyId;
|
||||
@Column(nullable = false)
|
||||
private String instanceId;
|
||||
@Enumerated(EnumType.STRING)
|
||||
private FlowableAction action;
|
||||
private String comment;
|
||||
@CreatedDate
|
||||
private LocalDateTime createdTime;
|
||||
|
||||
public JpaFlowableHistory(FlowableHistory history) {
|
||||
this.historyId = history.getHistoryId();
|
||||
this.instanceId = history.getInstanceId();
|
||||
this.action = history.getAction();
|
||||
this.comment = history.getComment();
|
||||
}
|
||||
|
||||
public FlowableHistory toFlowableHistory() {
|
||||
return new FlowableHistory(historyId, instanceId, action, comment, createdTime);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package com.lanyuanxiaoyao.flowable.jpa.entity;
|
||||
|
||||
import com.lanyuanxiaoyao.flowable.core.model.FlowableInstance;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Map;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.EntityListeners;
|
||||
import javax.persistence.EnumType;
|
||||
import javax.persistence.Enumerated;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Lob;
|
||||
import javax.persistence.Table;
|
||||
import lombok.Cleanup;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.ToString;
|
||||
import org.hibernate.annotations.DynamicUpdate;
|
||||
import org.springframework.data.annotation.CreatedDate;
|
||||
import org.springframework.data.annotation.LastModifiedDate;
|
||||
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
|
||||
|
||||
/**
|
||||
* @author lanyuanxiaoyao
|
||||
* @version 20250102
|
||||
*/
|
||||
@NoArgsConstructor
|
||||
@ToString
|
||||
@Getter
|
||||
@Setter
|
||||
@Entity
|
||||
@Table(name = "flowable_instance")
|
||||
@DynamicUpdate
|
||||
@EntityListeners(AuditingEntityListener.class)
|
||||
public class JpaFlowableInstance {
|
||||
@Id
|
||||
private String instanceId;
|
||||
@Lob
|
||||
private byte[] metadata;
|
||||
@Column(nullable = false)
|
||||
private String currentNodeId;
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Column(nullable = false)
|
||||
private FlowableInstance.Status status = FlowableInstance.Status.RUNNING;
|
||||
|
||||
@CreatedDate
|
||||
private LocalDateTime createdTime;
|
||||
@LastModifiedDate
|
||||
private LocalDateTime updatedTime;
|
||||
|
||||
@SneakyThrows
|
||||
public JpaFlowableInstance(FlowableInstance instance) {
|
||||
this.instanceId = instance.getInstanceId();
|
||||
this.metadata = objectToBytes(instance.getMetadata());
|
||||
this.currentNodeId = instance.getCurrentNodeId();
|
||||
this.status = instance.getStatus();
|
||||
}
|
||||
|
||||
private static byte[] objectToBytes(Object object) throws IOException {
|
||||
@Cleanup
|
||||
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
||||
@Cleanup
|
||||
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
|
||||
objectOutputStream.writeObject(object);
|
||||
return byteArrayOutputStream.toByteArray();
|
||||
}
|
||||
|
||||
private static Object bytesToObject(byte[] bytes) throws IOException, ClassNotFoundException {
|
||||
@Cleanup
|
||||
java.io.ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
|
||||
@Cleanup
|
||||
java.io.ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
|
||||
return objectInputStream.readObject();
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
public FlowableInstance toFlowableInstance() {
|
||||
return new FlowableInstance(
|
||||
instanceId,
|
||||
currentNodeId,
|
||||
(Map<String, Object>) bytesToObject(this.metadata),
|
||||
status,
|
||||
createdTime,
|
||||
updatedTime
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package com.lanyuanxiaoyao.flowable.jpa.entity;
|
||||
|
||||
import com.lanyuanxiaoyao.flowable.core.model.FlowableAction;
|
||||
import com.lanyuanxiaoyao.flowable.core.model.FlowableNode;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Map;
|
||||
import javax.persistence.CollectionTable;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.ConstraintMode;
|
||||
import javax.persistence.ElementCollection;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.EntityListeners;
|
||||
import javax.persistence.EnumType;
|
||||
import javax.persistence.Enumerated;
|
||||
import javax.persistence.ForeignKey;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.MapKeyColumn;
|
||||
import javax.persistence.Table;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
import org.hibernate.annotations.DynamicUpdate;
|
||||
import org.springframework.data.annotation.CreatedDate;
|
||||
import org.springframework.data.annotation.LastModifiedDate;
|
||||
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
|
||||
|
||||
/**
|
||||
* @author lanyuanxiaoyao
|
||||
* @version 20241231
|
||||
*/
|
||||
@NoArgsConstructor
|
||||
@ToString
|
||||
@Getter
|
||||
@Setter
|
||||
@Entity
|
||||
@Table(name = "flowable_node")
|
||||
@DynamicUpdate
|
||||
@EntityListeners(AuditingEntityListener.class)
|
||||
public class JpaFlowableNode {
|
||||
@Id
|
||||
private String nodeId;
|
||||
@Column(nullable = false)
|
||||
private String name;
|
||||
private String description;
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Column(nullable = false)
|
||||
private FlowableNode.RunType runType;
|
||||
@ElementCollection(fetch = javax.persistence.FetchType.EAGER)
|
||||
@MapKeyColumn(name = "action")
|
||||
@Column(name = "nodeId")
|
||||
@CollectionTable(foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
|
||||
private Map<FlowableAction, String> nextNodes;
|
||||
@CreatedDate
|
||||
private LocalDateTime createdTime;
|
||||
@LastModifiedDate
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
public JpaFlowableNode(FlowableNode node) {
|
||||
this.nodeId = node.getNodeId();
|
||||
this.name = node.getName();
|
||||
this.description = node.getDescription();
|
||||
this.runType = node.getRunType();
|
||||
this.nextNodes = node.getNextNodes();
|
||||
}
|
||||
|
||||
public FlowableNode toFlowableNode() {
|
||||
FlowableNode node = new FlowableNode(nodeId, name, description, runType, nextNodes, null, createdTime);
|
||||
node.setUpdatedTime(updateTime);
|
||||
return node;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.lanyuanxiaoyao.flowable.jpa.repository;
|
||||
|
||||
import com.lanyuanxiaoyao.flowable.jpa.entity.JpaFlowableHistory;
|
||||
import java.util.List;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
/**
|
||||
* @author lanyuanxiaoyao
|
||||
* @version 20250102
|
||||
*/
|
||||
@Repository
|
||||
public interface JpaFlowableHistoryRepository extends JpaRepository<JpaFlowableHistory, String> {
|
||||
List<JpaFlowableHistory> findAllByInstanceId(String instanceId);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.lanyuanxiaoyao.flowable.jpa.repository;
|
||||
|
||||
import com.lanyuanxiaoyao.flowable.jpa.entity.JpaFlowableInstance;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
/**
|
||||
* @author lanyuanxiaoyao
|
||||
* @version 20250102
|
||||
*/
|
||||
@Repository
|
||||
public interface JpaFlowableInstanceRepository extends JpaRepository<JpaFlowableInstance, String> {
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.lanyuanxiaoyao.flowable.jpa.repository;
|
||||
|
||||
import com.lanyuanxiaoyao.flowable.jpa.entity.JpaFlowableNode;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
/**
|
||||
* @author lanyuanxiaoyao
|
||||
* @version 20250102
|
||||
*/
|
||||
@Repository
|
||||
public interface JpaFlowableNodeRepository extends JpaRepository<JpaFlowableNode, String> {
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.lanyuanxiaoyao.flowable.jpa;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
|
||||
|
||||
/**
|
||||
* @author lanyuanxiaoyao
|
||||
* @version 20250102
|
||||
*/
|
||||
@SpringBootApplication
|
||||
@EnableJpaAuditing
|
||||
public class SpringFlowableApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(SpringFlowableApplication.class, args);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.lanyuanxiaoyao.flowable.jpa;
|
||||
|
||||
import com.lanyuanxiaoyao.flowable.core.manager.FlowableManager;
|
||||
import com.lanyuanxiaoyao.flowable.core.test.TestFlowableManager;
|
||||
import javax.annotation.Resource;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
/**
|
||||
* @author lanyuanxiaoyao
|
||||
* @version 20250102
|
||||
*/
|
||||
@SpringBootTest
|
||||
public class TestSpringFlowableManager extends TestFlowableManager {
|
||||
@Resource
|
||||
private SpringFlowableManager flowableManager;
|
||||
|
||||
@Override
|
||||
protected FlowableManager flowableManager() {
|
||||
return flowableManager;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
spring:
|
||||
datasource:
|
||||
url: jdbc:h2:mem:testdb
|
||||
username: flowable
|
||||
password: flowable
|
||||
driver-class-name: org.h2.Driver
|
||||
jpa:
|
||||
show-sql: true
|
||||
hibernate:
|
||||
ddl-auto: create
|
||||
logging:
|
||||
level:
|
||||
root: info
|
||||
org:
|
||||
hibernate:
|
||||
orm:
|
||||
jdbc:
|
||||
bind: trace
|
||||
Reference in New Issue
Block a user