Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

添加List转Note功能 #16

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
.DS_Store
.DS_Store
/.idea/
.idea/
JpaNestedSet.iml
86 changes: 47 additions & 39 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
<artifactId>maven-compiler-plugin</artifactId>
<version>2.1</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
<source>1.7</source>
<target>1.7</target>
<showWarnings>true</showWarnings>
<showDeprecation>true</showDeprecation>
<verbose>true</verbose>
Expand Down Expand Up @@ -47,46 +47,15 @@
<dependencies>
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.0-api</artifactId>
<version>1.0.1.Final</version>
<artifactId>hibernate-jpa-2.1-api</artifactId>
<version>1.0.0.Final</version>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>eclipselink</artifactId>
<version>2.0.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>1.8.0.7</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.18</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>5.10</version>
<scope>test</scope>
<classifier>jdk15</classifier>
</dependency>
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>javax.persistence</artifactId>
<version>2.0.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.jcip</groupId>
<artifactId>jcip-annotations</artifactId>
Expand All @@ -95,14 +64,53 @@
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.5.10</version>
<version>1.7.21</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.3.11.Final</version>
<scope>provided</scope>
<exclusions>
<!--<exclusion>
<groupId>antlr</groupId>
<artifactId>antlr</artifactId>
</exclusion>-->
<exclusion>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jms_1.1_spec</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>0.9.18</version>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.3.11.Final</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jms_1.1_spec</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>2.2.9</version>
<scope>test</scope>
</dependency>
<!--<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.39</version>
</dependency>-->
</dependencies>
</project>

Expand Down
105 changes: 73 additions & 32 deletions src/main/java/org/code_factory/jpa/nestedset/JpaNestedSetManager.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
* LICENSE
*
* <p>
* This source file is subject to the MIT license that is bundled
* with this package in the file MIT.txt.
* It is also available through the world-wide-web at this URL:
Expand All @@ -22,15 +22,18 @@
import javax.inject.Inject;
import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import net.jcip.annotations.NotThreadSafe;
import org.code_factory.jpa.nestedset.annotations.LeftColumn;
import org.code_factory.jpa.nestedset.annotations.LevelColumn;
import org.code_factory.jpa.nestedset.annotations.RightColumn;
import org.code_factory.jpa.nestedset.annotations.RootColumn;
import org.hibernate.transform.AliasToEntityMapResultTransformer;

/**
* @author Roman Borschel <[email protected]>
Expand All @@ -41,6 +44,7 @@ public class JpaNestedSetManager implements NestedSetManager {
private final EntityManager em;
private final Map<Key, Node<?>> nodes;
private final Map<Class<?>, Configuration> configs;
private final Long defaultRootId = 1L;

@Inject
public JpaNestedSetManager(EntityManager em) {
Expand Down Expand Up @@ -78,14 +82,14 @@ public Collection<Node<?>> getNodes() {
*/
@Override
public <T extends NodeInfo> List<Node<T>> fetchTreeAsList(Class<T> clazz) {
return fetchTreeAsList(clazz, 0);
return fetchTreeAsList(clazz, defaultRootId);
}

/**
* {@inheritDoc}
*/
@Override
public <T extends NodeInfo> List<Node<T>> fetchTreeAsList(Class<T> clazz, int rootId) {
public <T extends NodeInfo> List<Node<T>> fetchTreeAsList(Class<T> clazz, Long rootId) {
Configuration config = getConfig(clazz);
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<T> cq = cb.createQuery(clazz);
Expand All @@ -104,17 +108,54 @@ public <T extends NodeInfo> List<Node<T>> fetchTreeAsList(Class<T> clazz, int ro
return tree;
}

@Override
public <T extends NodeInfo> List<Map<String, Object>> fetchTreeAsAdjacencyList(Class<T> clazz) {
return fetchTreeAsAdjacencyList(clazz, defaultRootId, 0);
}

@Override
public <T extends NodeInfo> List<Map<String, Object>> fetchTreeAsAdjacencyList(Class<T> clazz, Long rootId) {
return fetchTreeAsAdjacencyList(clazz, rootId, 0);
}

@Override
public <T extends NodeInfo> List<Map<String, Object>> fetchTreeAsAdjacencyList(Class<T> clazz, Long rootId, int maxLevel) {
Configuration config = getConfig(clazz);

StringBuilder sb = new StringBuilder();
sb.append("SELECT node.*,")
.append(" parent.id parent_id ")
.append(" FROM ").append(config.getEntityName()).append(" node ")
.append(" JOIN ").append(config.getEntityName()).append(" parent ")
.append(" ON node.").append(config.getLeftFieldName())
.append(" BETWEEN parent.").append(config.getLeftFieldName()).append(" AND parent.").append(config.getRightFieldName())
.append(" WHERE node.").append(config.getLevelFieldName()).append(" = parent.").append(config.getLevelFieldName()).append(" + 1")
.append(" AND node.").append(config.getRootIdFieldName()).append(" = ").append(rootId);

if (maxLevel > 0) {
sb.append(" AND node.").append(config.getLevelFieldName()).append(" < ").append(maxLevel);
}

Query query = em.createNativeQuery(sb.toString());

org.hibernate.Query hibernateQuery = ((org.hibernate.jpa.HibernateQuery) query)
.getHibernateQuery();
hibernateQuery.setResultTransformer(AliasToEntityMapResultTransformer.INSTANCE);

return hibernateQuery.list();
}

/**
* {@inheritDoc}
*/
@Override
public <T extends NodeInfo> Node<T> fetchTree(Class<T> clazz, int rootId) {
public <T extends NodeInfo> Node<T> fetchTree(Class<T> clazz, Long rootId) {
return fetchTreeAsList(clazz, rootId).get(0);
}

@Override
public <T extends NodeInfo> Node<T> fetchTree(Class<T> clazz) {
return fetchTree(clazz, 0);
return fetchTree(clazz, defaultRootId);
}

/**
Expand Down Expand Up @@ -178,10 +219,13 @@ public <T extends NodeInfo> Node<T> createRoot(T root) {
root.setLeftValue(maximumRight + 1);
root.setRightValue(maximumRight + 2);
root.setLevel(0);
if (root.getRootValue() == null) {
root.setRootValue(defaultRootId);
}
em.persist(root);
return getNode(root);
}

/**
* {@inheritDoc}
*/
Expand Down Expand Up @@ -213,22 +257,19 @@ public <T extends NodeInfo> Node<T> getNode(T nodeInfo) {
Configuration getConfig(Class<?> clazz) {
if (!this.configs.containsKey(clazz)) {
Configuration config = new Configuration();

Entity entity = clazz.getAnnotation(Entity.class);
String name = entity.name();
config.setEntityName( (name != null && name.length()>0) ? name : clazz.getSimpleName());
String name = entity.name();
config.setEntityName((name != null && name.length() > 0) ? name : clazz.getSimpleName());

for (Field field : clazz.getDeclaredFields()) {
if (field.getAnnotation(LeftColumn.class) != null) {
config.setLeftFieldName(field.getName());
}
else if (field.getAnnotation(RightColumn.class) != null) {
} else if (field.getAnnotation(RightColumn.class) != null) {
config.setRightFieldName(field.getName());
}
else if (field.getAnnotation(LevelColumn.class) != null) {
} else if (field.getAnnotation(LevelColumn.class) != null) {
config.setLevelFieldName(field.getName());
}
else if (field.getAnnotation(RootColumn.class) != null) {
} else if (field.getAnnotation(RootColumn.class) != null) {
config.setRootIdFieldName(field.getName());
}
}
Expand All @@ -238,18 +279,18 @@ else if (field.getAnnotation(RootColumn.class) != null) {

return this.configs.get(clazz);
}

int getMaximumRight(Class<? extends NodeInfo> clazz) {
Configuration config = getConfig(clazz);
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<? extends NodeInfo> cq = cb.createQuery(clazz);
Configuration config = getConfig(clazz);
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<? extends NodeInfo> cq = cb.createQuery(clazz);
Root<? extends NodeInfo> queryRoot = cq.from(clazz);
cq.orderBy(cb.desc(queryRoot.get(config.getRightFieldName())));
List<? extends NodeInfo>highestRows = em.createQuery(cq).setMaxResults(1).getResultList();
List<? extends NodeInfo> highestRows = em.createQuery(cq).setMaxResults(1).getResultList();
if (highestRows.isEmpty()) {
return 0;
return 0;
} else {
return highestRows.get(0).getRightValue();
return highestRows.get(0).getRightValue();
}
}

Expand All @@ -260,9 +301,9 @@ int getMaximumRight(Class<? extends NodeInfo> clazz) {
* @param cq
* @param rootId
*/
void applyRootId(Class<?> clazz, CriteriaQuery<?> cq, int rootId) {
void applyRootId(Class<?> clazz, CriteriaQuery<?> cq, Long rootId) {
Configuration config = getConfig(clazz);
if (config.getRootIdFieldName() != null) {
if (config.getRootIdFieldName() != null && rootId != null) {
Root<?> root = cq.getRoots().iterator().next();
CriteriaBuilder cb = em.getCriteriaBuilder();
Predicate p = cq.getRestriction();
Expand All @@ -276,9 +317,9 @@ void applyRootId(Class<?> clazz, CriteriaQuery<?> cq, int rootId) {
*
* @param minLeft The lower bound (inclusive) of the left values to update.
* @param maxLeft The upper bound (inclusive) of the left values to update.
* @param delta The delta to apply on the left values within the range.
* @param delta The delta to apply on the left values within the range.
*/
void updateLeftValues(int minLeft, int maxLeft, int delta, int rootId) {
void updateLeftValues(int minLeft, int maxLeft, int delta, Long rootId) {
for (Node<?> node : this.nodes.values()) {
if (node.getRootValue() == rootId) {
if (node.getLeftValue() >= minLeft && (maxLeft == 0 || node.getLeftValue() <= maxLeft)) {
Expand All @@ -295,9 +336,9 @@ void updateLeftValues(int minLeft, int maxLeft, int delta, int rootId) {
*
* @param minRight The lower bound (inclusive) of the right values to update.
* @param maxRight The upper bound (inclusive) of the right values to update.
* @param delta The delta to apply on the right values within the range.
* @param delta The delta to apply on the right values within the range.
*/
void updateRightValues(int minRight, int maxRight, int delta, int rootId) {
void updateRightValues(int minRight, int maxRight, int delta, Long rootId) {
for (Node<?> node : this.nodes.values()) {
if (node.getRootValue() == rootId) {
if (node.getRightValue() >= minRight && (maxRight == 0 || node.getRightValue() <= maxRight)) {
Expand All @@ -312,11 +353,11 @@ void updateRightValues(int minRight, int maxRight, int delta, int rootId) {
* INTERNAL:
* Updates the level values of all nodes currently known to the manager.
*
* @param left The lower bound left value.
* @param left The lower bound left value.
* @param right The upper bound right value.
* @param delta The delta to apply on the level values of the nodes within the range.
*/
void updateLevels(int left, int right, int delta, int rootId) {
void updateLevels(int left, int right, int delta, Long rootId) {
for (Node<?> node : this.nodes.values()) {
if (node.getRootValue() == rootId) {
if (node.getLeftValue() > left && node.getRightValue() < right) {
Expand All @@ -327,7 +368,7 @@ void updateLevels(int left, int right, int delta, int rootId) {
}
}

void removeNodes(int left, int right, int rootId) {
void removeNodes(int left, int right, Long rootId) {
Set<Key> removed = new HashSet<Key>();
for (Node<?> node : this.nodes.values()) {
if (node.getRootValue() == rootId) {
Expand All @@ -341,7 +382,7 @@ void removeNodes(int left, int right, int rootId) {
n.setLeftValue(0);
n.setRightValue(0);
n.setLevel(0);
n.setRootValue(0);
n.setRootValue(null);
this.em.detach(n.unwrap());
}
}
Expand Down
Loading