返回介绍

11.2 数据存取功能实现原理

发布于 2025-04-26 13:26:36 字数 6675 浏览 0 评论 0 收藏

与数据库服务器建立连接之后,就可以对数据库执行一些存取操作,对数据库实现管理的功能。数据存取的操作大体上都包含两个方面的内容,即实体建模和持久化。不管是关系型数据库,还是 NoSQL 数据库,都遵循这一设计规范。

11.2.1 实体建模源代码分析

实体建模的原理简单地说,即将 Java 的普通对象和关系映射为数据库表及其相关的关系。而这种映射在 Spring Boot 中,主要是通过注解的方式来实现。几种数据库中主要的注解定义如表 11-1 所示。

表 11-1 实体建模主要注解定义

这种映射机制是双向的,当向数据库存入数据时,是将 Java 对象映射为数据库对象,而从数据库取出数据时,却将数据库中的数据还原为 Java 对象。

例如对于 Neo4j 来说,在实体建模中的主要注解 @NodeEntity 的定义如代码清单 11-6 所示。在一个类定义中使用这个注解,表示这个类定义就是一个节点实体的建模。

代码清单 11-6 @NodeEntity 源代码

package org.neo4j.ogm.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Inherited
public @interface NodeEntity {
    String CLASS = "org.neo4j.ogm.annotation.NodeEntity";
    String LABEL = "label";
    String label() default "";
}

Neo4j 是一个图形数据库,所以程序中的实体对象要存入数据库时,将被映射为数据库图形。代码清单 11-7 是这种映射的部分实现代码。它的实现原理是,将实体对象转化为数据库可以识别的查询语句,实现对象到数据的转换。

代码清单 11-7 实体对象映射为数据库图形的部分源代码

package org.neo4j.ogm.mapper;
......
public class EntityGraphMapper implements EntityToGraphMapper {
    public CypherContext map(Object entity, int horizon) {
        if(entity == null) {
            throw new NullPointerException("Cannot map null object");
        } else {
            SingleStatementCypherCompiler compiler = new SingleStatementCypher
Compiler();
            Iterator i$ = this.mappingContext.mappedRelationships().iterator();
            while(i$.hasNext()) {
                MappedRelationship mappedRelationship = (MappedRelationship)
i$.next();
                this.logger.debug("context-init: (${})-[:{}]->(${})", new Object
[]{Long.valueOf(mappedRelationship.getStartNodeId()), mappedRelationship.getRelationshipType(), Long.valueOf(mappedRelationship.getEndNodeId())});
                compiler.context().registerRelationship(mappedRelationship);
            }
            this.logger.debug("context initialised with {} relationships", Integer.valueOf(this.mappingContext.mappedRelationships().size()));
            if(this.isRelationshipEntity(entity)) {
                entity = this.entityAccessStrategy.getStartNodeReader(this.metaData.classInfo(entity)).read(entity);
                if(entity == null) {
                    throw new RuntimeException("@StartNode of relationship entity may not be null");
                }
            }
            this.mapEntity(entity, horizon, compiler);
            this.deleteObsoleteRelationships(compiler);
            return compiler.compile();
        }
    }
    ......
}

当从 Neo4j 数据库中读取数据时,Neo4j 将数据库中的图形还原为实体对象。代码清单 11-8 是实现这种功能的部分源代码,即将从数据库中查询得到的数据集合转化为实体对象,实现从数据到对象的转换。

代码清单 11-8 数据库中图形还原为实体对象的部分源代码

package org.neo4j.ogm.mapper;
......
public class GraphEntityMapper implements GraphToEntityMapper<GraphModel> {
        private void mapNodes(GraphModel graphModel, List<Long> nodeIds) {
        Iterator i$ = graphModel.getNodes().iterator();
        while(i$.hasNext()) {
            NodeModel node = (NodeModel)i$.next();
            Object entity = this.mappingContext.getNodeEntity(node.getId());
            try {
                if(entity == null) {
                    entity = this.mappingContext.registerNodeEntity(this.entity
Factory.newObject(node), node.getId());
                }
                this.setIdentity(entity, node.getId());
                this.setProperties(node, entity);
                this.mappingContext.remember(entity);
                nodeIds.add(node.getId());
            } catch (BaseClassNotFoundException var7) {
                this.logger.debug(var7.getMessage());
            }
        }
    }
    ......
}

11.2.2 持久化实现原理

关系型数据库都使用了 JPA 的一套执行标准,它结合使用 Hibernate 实现了实体的持久化。后续的数据库管理设计都遵循了 JPA 这一个标准规范,提供相同的访问数据库的 API。图 11-1 是 JPA、MongoDB、Neo4j 三种不同的资源库接口定义的相同的继承关系。

图 11-1 数据库资源库接口的继承关系

这就不难理解,为什么在 Spring Boot 中使用数据库,对于不同种类的数据库,几乎都可以使用相同的方法来访问。但是,上面不同数据库的资源库接口定义虽然有相同的继承关系,它们的实现方法却是不同的,JPA 由 SimpleJpaRepository 实现了 JpaRepository,如代码清单 11-9 所示。

代码清单 11-9 JPA 数据库持久化源代码片段

package org.springframework.data.jpa.repository.support;
......
@Repository
@Transactional(
    readOnly = true
)
public class SimpleJpaRepository<T, ID extends Serializable> implements JpaRepository<T, ID>, JpaSpecificationExecutor<T> {
    private static final String ID_MUST_NOT_BE_NULL = "The given id must not be null!";
    private final JpaEntityInformation<T, ?> entityInformation;
    private final EntityManager em;
    private final PersistenceProvider provider;
    private CrudMethodMetadata metadata;
    public SimpleJpaRepository(JpaEntityInformation<T, ?> entityInformation, Entity
Manager entityManager) {
        Assert.notNull(entityInformation);
        Assert.notNull(entityManager);
        this.entityInformation = entityInformation;
        this.em = entityManager;
        this.provider = PersistenceProvider.fromEntityManager(entityManager);
    }
    ……





    public T findOne(ID id) {
        Assert.notNull(id, "The given id must not be null!");
        Class domainType = this.getDomainClass();
        if(this.metadata == null) {
            return this.em.find(domainType, id);
        } else {
            LockModeType type = this.metadata.getLockModeType();
            Map hints = this.getQueryHints();
            return type == null?this.em.find(domainType, id, hints):this.em.
find(domainType, id, type, hints);
        }
    }
    ......
}

而对于 Neo4j 来说,它使用 GraphRepositoryImpl 实现了 GraphRepository,如代码清单 11-10 所示。

代码清单 11-10 Neo4j 数据库持久化源代码片段

package org.springframework.data.neo4j.repository;
......
@Repository
public class GraphRepositoryImpl<T> implements GraphRepository<T> {
    private static final int DEFAULT_QUERY_DEPTH = 1;
    private final Class<T> clazz;
    private final Session session;
    public GraphRepositoryImpl(Class<T> clazz, Session session) {
        this.clazz = clazz;
        this.session = session;
    }
    ......
    public T findOne(Long id) {
        return this.session.load(this.clazz, id);
    }
    ......
}

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。