精华内容
下载资源
问答
  • <p>I have seen many checkbox examples, but not this one.... <p>I need a checkbox to remain checked if data is present in specific <code><input></code> fields. So it would need to be something ...
  • 如何启用和使用Apache Ignite的持久性持久内存功能,该功能可以将缓存数据持久保存到文件磁盘中,以免崩溃或重新启动,从而避免数据丢失。 如何通过点火缓存执行SQL查询 如何使用Spring Boot点燃单元测试和集成测试...
  •  【IT168技术】OrmLite提供了一些轻量级持久化Java对象到SQL数据库,同时也避免了复杂和更多的标准的ORM包的开销功能。它支持的SQL数据库使用JDBC的数量,还支持原生的Andr??oid操作系统数据库API调用sqlite。 ...

    Android中如何使用OrmLite持久化

      【IT168技术】OrmLite提供了一些轻量级持久化Java对象到SQL数据库,同时也避免了复杂性和更多的标准的ORM包的开销功能。它支持的SQL数据库使用JDBC的数量,还支持原生的Andr??oid操作系统数据库API调用sqlite。

      相信大家应该都知道,在Android系统中,保存数据的方法多种,但应该可以一起概括为四种方式:

      • Preferences

      • Files

      • Databases

      • Network

      今天我们来看看Databases这种方式。在Android系统中内置了一款轻量级数据库sqlite,关于它的介绍相信网上一定多得数不清,所以我这里就不废话了。

      因为有些朋友不熟悉SQL语句,或者说不想写,再或者说怎么写都不对,这里就引出了今天我要介绍的OrmLite:Object Relational Mapping Lite (ORM Lite)。

      OrmLite提供了一些轻量级持久化Java对象到SQL数据库,同时也避免了复杂性和更多的标准的ORM包的开销功能。它支持的SQL数据库使用JDBC的数量,还支持原生的Andr??oid操作系统数据库API调用sqlite。首先我们要使用它呢,就要去它的官方http://ormlite.com下载你想要的版本,这里我下载了最新的4.30。接下来我们来写一个简单的项目,同时对它的使用方法进行一个详细的介绍。

      建立好项目后呢,我们加入OrmLite的jar包,然后建立两个实体类,我用的例子是客户和订单,一个客户对应多个订单这样的关系。

      

      接着为这两个实体类添加属性和字段,需要注意的是,一定要有一个无参的构造函数,OrmLite创建对象时需要使用。

      Account: int aId,String aName;Order:int oid,String oName,Account account。

      接着就到了添加ORMLite注解了。注解是特殊的代码标志已在Java版本开始,要指定什么类和字段存储在数据库中,ORMLite支持其自己的注解(@ DatabaseTable @ DatabaseField)或更多的标准注解从javax.persistence包。注解是最简单的方法来配置你的类,但你也可以使用Java代码或Spring的XML配置类 。以下是注解的详细介绍:

      @ DatabaseTable注解可以有一个可选的TableName的参数指定类对应的表的名称。如果没有指定表名的情况下,默认情况下使用类名作为对应的表名。例如:

      @DatabaseTable(tableName = "accounts")

      public class Account {...} 像这样的话,Account类对应的表名就是accounts,如果不指定则为account。

      @ DatabaseField注解可以有以下字段:

      columnName 列名,未指定时为字段名

      dataType DataType类的类型的字段。通常的类型是从Java类的领域,并不需要指定。

      defaultValue 默认值

      width 宽度 默认是0,表示不限

      canBeNull 是否允许为空,默认为true

      id 主键 默认为false

      generatedId 自增长的主键 默认值是false

      generatedIdSequence 字符串名称的序列号 类同generatedId,但您可以指定序列的名称使用。默认为null

      foreign 外键,默认为false,字段不能是一个原始类型。在外键对象的类中,必须要有一个ID字段(ID, generatedId,generatedIdSequence)

      useGetSet 应用get和set方法访问。默认为false

      unknownEnumName 表示该字段是一个Java的枚举类型

      throwIfNull 如果为空值,抛出一个异常 默认为false

      persisted 是否在数据库中存储这个领域 默认为true

      format 指定某一特定领域的信息格式,如指定日期字符串的格式

      unique 唯一约束,默认为false

      uniqueCombo 唯一行,该行内所有字段成为一个唯一约束,如有firstName 和 lastName两个字段,为"张"和"梅",那么该表内不可再插 入"张","梅", 但你可插入"张","全梅"。

      index 是否建立索引 默认为false

      uniqueIndex 唯一索引 默认为false

      indexName 为这一领域的索引添加一个名字

      uniqueIndexName 为这一领域的索引添加一个唯一的名字

      foreignAutoRefresh 当查询到一个外键对象时,是否自动刷新 如 Order表中有Account外键对象,当返回Order的记录时是否也返回Account的记录, 默认为false

      maxForeignAutoRefreshLevel 为了防止无限递归或者无限循环时 需要用到该属性设置自动刷新的最高级别

      allowGeneratedIdInsert 插入一个ID字段是否覆盖它生成的ID的对象 默认为false

      columnDefinition 定义列,默认情况下,数据库类型是用于自动生成所需的SQL来创建列,所以该属性并不常用

      foreignAutoCreate 在插入一个有外键对象的对象时,是否自动插入这个外键对象

      version 行版本 当一个对象被更新,以防止数据损坏多个实体时更新在同一时间进行的保护

    展开全文
  • 本文主要讲了 Redis 的持久化相关功能持久化一直是影响 Redis 性能的高发地,也是面试中经常被问到的。 包括 RDB 相关的特性和优缺点,AOF 的优缺点,事实上,由于 RDB 的数据实时问题,目前用 AOF 比较多了,...

    JavaSpring高级进阶 2019-06-22 21:53:32

    面试被问哭:Redis 如何做持久化与恢复?

     

    一、前言

    本文主要讲了 Redis 的持久化相关功能,持久化一直是影响 Redis 性能的高发地,也是面试中经常被问到的。

    包括 RDB 相关的特性和优缺点,AOF 的优缺点,事实上,由于 RDB 的数据实时性问题,目前用 AOF 比较多了,而持久化恢复也是优先 AOF。

    RDB 是旧的模式,现在基本上都使用 AOF,当然,今天两个都会一起聊聊。

    二、RDB

    RDB 流程图:

    面试被问哭:Redis 如何做持久化与恢复?

     

    RDB 特点:

    1. RDB 是一种快照模式,即保存的是 key value 数据内容。
    2. RDB 有 2 种持久方式,同步 save 模式和异步 bgsave 模式。由于 save 是同步的,所以可以保证数据一致性,而 bgsave 则不能。
    3. save 可以在客户端显式触发,也可以在 shutdown 时自动触发;bgsave 可以在客户端显式触发,也可以通过配置由定时任务触发,也可以在 slave 节点触发。
    4. save 导致 redis 同步阻塞,基本已经废弃。bgsave 则不会导致阻塞,但也有缺点:在 fork 时,需要增加内存服务器开销,因为当内存不够时,将使用虚拟内存,导致阻塞 Redis 运行。所以,需要保证空闲内存足够。
    5. 默认执行 shutdown 时,如果没有开启 AOF,则自动执行 bgsave。
    6. 每次的 RDB 文件都是替换的。

    关于优化:

    Redis 会压缩 RDB 文件,使用 LZF 算法,让最终的 RDB 文件远小于内存大小,默认开启。但会消耗 CPU。

    RDB 缺点:

    1. 无法秒级持久化。
    2. 老版本 Redis 无法兼容新版本 RDB。

    RDB 优点:

    1. 文件紧凑,适合备份,全量复制场景。例如每 6 小时执行 bgsave,保存到文件系统之类的。
    2. Redis 加载 RDB 恢复数据远远快于 AOF。

    三、AOF

    由于 RDB 的数据实时性问题,AOF(append only file) 是目前 Redis 持久化的主流方式。

    AOF 特点:

    1. 默认文件名是 appendonly.aof。和 RDB 一样,保存在配置中 dir 目录下。
    2. AOF 相比较于 RDB,每次都会保存写命令,数据实时性更高。
    3. AOF 由于每次都会记录写命令,文件会很大,因此需要进行优化,称之为“重写机制”(下面详细说)。
    4. AOF 每次保存的写命令都放在一个缓冲区,根据不同的策略(下面详细说)同步到磁盘。

    “重写机制” 细节:

    1. fork 子进程(类似 bgsave)
    2. 主进程会写到2个缓冲区,一个是原有的 “AOF 缓存区”,一个是专门为子进程准备的 “AOF 重写缓冲区”;
    3. 子进程写到到新的 AOF 文件中,批量的,默认 32m;写完后通知主进程。
    4. 主进程把“AOF 重写缓冲区”的数据写到新 AOF 文件中。
    5. 将新的 AOF 文件替换老文件。

    重写流程图:

    面试被问哭:Redis 如何做持久化与恢复?

     

    缓冲区同步策略,由参数 appendfsync 控制,一共3种:

    1. always:调用系统 fsync 函数,直到同步到硬盘返回;严重影响redis性能。
    2. everysec:先调用 OS write 函数, 写到缓冲区,然后 redis 每秒执行一次 OS fsync 函数。推荐使用这种方式。
    3. no: 只执行 write OS 函数,具体同步硬盘策略由 OS 决定;不推荐,数据不安全,容易丢失数据。

    四、持久化恢复

    AOF 和 RDB 文件都可以用于服务器重启时的数据恢复,具体流程如下图:

    面试被问哭:Redis 如何做持久化与恢复?

     

    从图中可以看出优先加载 AOF,当没有 AOF 时才加载 RDB。当 AOF 或者 RDB 存在错误,则加载失败。

    五、问题排查和性能优化

    Redis 持久化是影响 Redis 性能的高发地,也是面试中常问的问题。

    1、fork 操作

    当 Redis 做 RDB 或者 AOF 重写时,必然要进行 fork 操作,对于 OS 来说,fork 都是一个重量级操作。而且,fork 还会拷贝一些数据,虽然不会拷贝主进程所有的物理空间,但会复制主进程的空间内存页表。对于 10GB 的 Redis 进程,需要复制大约 20MB 的内存页表,因此 fork 操作耗时跟进程总内存量息息相关,再加上,如果使用虚拟化技术,例如 Xen 虚拟机,fork 会更加耗时。

    一个正常的 fork 耗时大概在 20毫秒左右。为什么呢,假设一个 Redis 实例的 OPS 在 5 万以上,如果 fork 操作耗时在秒级,那么僵拖慢几万条命令的执行,对生产环境影响明显。

    我们可以在 Info stats 统计中查询 latestforkusec 指标获取最近一次 fork 操作耗时,单位微秒。

    如何优化:

    1. 优先使用物理机或者高效支持 fork 的虚拟化技术,避免使用 Xen。
    2. 控制 redis 实例最大内存,尽量控制在 10GB 以内。
    3. 合理配置 Linux 内存分配策略,避免内存不足导致 fork 失败。
    4. 降低 fork 的频率,如适度放宽 AOF 自动触发时机,避免不必要的全量复制。

    2、子进程开销

    fork 完毕之后,会创建子进程,子进程负责 RDB 或者 AOF 重写,这部分过程主要涉及到 CPU,内存,硬盘三个地方的优化。

    1. CPU 写入文件的过程是 CPU 密集的过程,通常子进程对单核 CPU 利用率接近 90%。如何优化呢?既然是 CPU 密集型操作,就不要绑定单核 CPU,因为这样会和父 CPU 进行竞争。同时,不要和其他 CPU 密集型服务不是在一个机器上。如果部署了多个 Redis 实例,尽力保证统一时刻只有一个子进程执行重写工作。
    2. 内存子进程通过 fork 操作产生,占用内存大小等同于父进程,理论上需要两倍的内存完成持久化操作,但 Linux 有 copy on write 机制,父子进程会共享相同的物理内存页,当父进程处理写操作时,会把要修改的页创建对应的副本,而子进程在 fork 操作过程中,共享整个父进程内存快照。即——如果重写过程中存在内存修改操作,父进程负责创建所修改内存页的副本。这里就是内存消耗的地方。如何优化呢?尽量保证同一时刻只有一个子进程在工作;避免大量写入时做重写操作。
    3. 硬盘 硬盘开销分析:子进程主要职责是将 RDB 或者 AOF 文件写入硬盘进行持久化,势必对硬盘造成压力,可通过工具例如 iostat,iotop 等,分析硬盘负载情况。

    如何优化:

    1. 不要和其他高硬盘负载的服务放在一台机器上,例如 MQ,存储。
    2. AOF 重写时会消耗大量硬盘 IO,可以开启配置 no-appendfsync-on-rewrite,默认关闭。表示在 AOF 重写期间不做 fsync 操作。
    3. 当开启 AOF 的 Redis 在高并发场景下,如果使用普通机械硬盘,每秒的写速率是 100MB左右,这时,Redis 的性能瓶颈在硬盘上,建议使用 SSD。
    4. 对于单机配置多个 Redis 实例的情况,可以配置不同实例分盘存储 AOF 文件,分摊硬盘压力。

    3、AOF 追加阻塞

    当开启 AOF 持久化时,常用的同步硬盘的策略是“每秒同步” everysec,用于平衡性能和数据安全性,对于这种方式,redis 使用另一条线程每秒执行 fsync 同步硬盘,当系统资源繁忙时,将造成 Redis 主线程阻塞。

    流程图如下:

    面试被问哭:Redis 如何做持久化与恢复?

     

     

    通过上图可以发现:everysec 配置最多可能丢失 2 秒数据,不是 1 秒;如果系统 fsync 缓慢,将会导致 Redis 主线程阻塞影响效率。

    问题定位:

    1. 发生 AOF 阻塞时,会输入日志。用于记录 AOF fsync 阻塞导致拖慢 Redis 服务的行为。
    2. 每当 AOF 追加阻塞事件发生时,在 info Persistence 统计中,aofdelayedfsync 指标会累加,查看这个指标方便定位 AOF 阻塞问题。
    3. AOF 同步最多运行 2 秒的延迟,当延迟发生时说明硬盘存在性能问题,可通过监控工具 iotop 查看,定位消耗 IO 的进程。

    4、单机多实例部署

    Redis 单线程架构无法充分利用多核CPU,通常的做法是一台机器上部署多个实例,当多个实例开启 AOF 后,彼此之间就会产生CPU 和 IO 的竞争。

    如何解决这个问题呢?

    让所有实例的 AOF 串行执行。

    我们通过 info Persistence 中关于 AOF 的信息写出 Shell 脚本,然后串行执行实例的 AOF 持久化。

    整个过程如图:

    面试被问哭:Redis 如何做持久化与恢复?

     

    通过不断判断 AOF 的状态,手动执行 AOF 重写,保证 AOF 不会存在竞争。具体的 Shell 编写以及 info 信息判断,可以查看下图:

    六、总结

    本文主要讲了 Redis 的持久化相关功能,持久化一直是影响 Redis 性能的高发地,也是面试中经常被问到的。包括 RDB 相关的t特性和优缺点,AOF 的优缺点,事实上,由于 RDB 的数据实时性问题,目前用 AOF 比较多了。而持久化恢复也是优先 AOF。

    关于持久化的问题排查,就很麻烦了,但无非几个方面,fork 耗时,子进程的 CPU,内存,硬盘开销,AOF 的同步阻塞,单机多实例部署。

    这些优化,可以通过前面写的分析进行排查。

    点关注不迷路,后续更新跟多干货。

    面试被问哭:Redis 如何做持久化与恢复?

     

    展开全文
  • java持久化api Java Persistence API(JPA)是供应用程序开发人员理解的重要Java功能。 它准确地将Java开发人员如何将对对象的方法调用转换为访问,持久化和管理NoSQL和关系数据库中存储的数据。 本文通过构建...

    java持久化api

    Java Persistence API(JPA)是供应用程序开发人员理解的重要Java功能。 它准确地将Java开发人员如何将对对象的方法调用转换为访问,持久化和管理NoSQL和关系数据库中存储的数据。

    本文通过构建自行车借贷服务的教程示例详细研究了JPA。 本示例将使用Spring Boot框架,MongoDB数据库( 不再开源的 )和Maven包管理器为较大的应用程序创建一个创建,读取,更新和删除(CRUD)层。 我还将NetBeans 11用作选择的IDE。

    本教程重点介绍Java Persistence API的开源角度,而不是工具,以展示其工作原理。 这全是关于学习编程应用程序的模式的,但是理解软件仍然很聪明。 您可以在我的GitHub存储库中访问完整的代码。

    Java:不仅仅是“ beans”

    主要版本每六个月发布一次; 由于功能通常存在重大差异,因此在选择版本之前,您可能需要做一些研究。

    总而言之,Java拥有悠久的历史。 本教程重点介绍JDK 11 ,它是Java 11的开源实现,因为它是仍处于活动状态的长期支持版本之一。

    • Spring Boot: Spring Boot是来自Pivotal开发的较大Spring框架的模块。 Spring是使用Java的非常流行的框架。 它允许各种架构和配置。 Spring还提供对Web应用程序和安全性的支持。 Spring Boot提供了用于快速引导各种Java项目的基本配置。 本教程使用Spring Boot快速编写控制台应用程序并针对数据库测试功能。
    • Maven: Maven是由Apache开发的项目/包管理器。 Maven允许在其POM.xml文件中管理软件包和各种依赖项。 如果您使用过NPM,则可能熟悉软件包管理器的功能。 Maven还管理构建和报告功能。
    • Lombok: Lombok是一个库,它允许通过对象文件中的注释来创建对象获取器/设置器。 C#等语言中已经存在该功能,Lombok将此功能引入了Java。
    • NetBeans: NetBeans是一种流行的开源IDE,专门用于Java开发。 它的许多工具都为最新的Java SE和EE更新提供了一个实现。

    这组工具将用于为虚构的自行车商店创建一个简单的应用程序。 它将实现插入“客户”和“自行车”对象集合的功能。

    酿造完美

    导航到Spring Initializr 该网站使您能够生成Spring Boot的基本项目需求以及该项目所需的依赖项。 选择以下选项:

    1. 项目: Maven项目
    2. 语言: Java
    3. Spring Boot: 2.1.8(或最稳定的版本)
    4. 项目元数据:无论您的命名约定是什么(例如com.stephb
      • 您可以将神器保留为“演示”
    5. 依赖项:添加:
      • Spring Data MongoDB
      • Lombok

    单击下载,然后在所选的IDE(例如NetBeans)中打开新项目。

    型号概要

    这些模型表示收集的有关程序中特定对象的信息,这些信息将保留在数据库中。 关注两个对象: CustomerBike 首先,在src文件夹中创建一个dto文件夹。 然后,创建两个名为Customer.javaBike.java的 Java类对象。 它们在程序中的结构如下:

    顾客。 Java

     1 package com.stephb.JavaMongo.dto ;
     2 
     3 import lombok.Getter ;
     4 import lombok.Setter ;
     5 import org.springframework.data.annotation.Id ;
     6 
     7 /**
     8  *
     9  * @author stephon
    10  */

    11 @Getter @Setter
    12 public class Customer {
    13 
    14         private @Id String id ;
    15         private String emailAddress ;
    16         private String firstName ;
    17         private String lastName ;
    18         private String address ;
    19         
    20 }

    Bike.java

     1 package com.stephb.JavaMongo.dto ;
     2 
     3 import lombok.Getter ;
     4 import lombok.Setter ;
     5 import org.springframework.data.annotation.Id ;
     6 
     7 /**
     8  *
     9  * @author stephon
    10  */

    11 @Getter @Setter
    12 public class Bike {
    13         private @Id String id ;
    14         private String modelNumber ;
    15         private String color ;
    16         private String description ;
    17 
    18         @Override
    19         public String toString ( ) {
    20                 return "This bike model is " + this . modelNumber + " is the color " + this . color + " and is " + description ;
    21         }
    22 }

    如您所见,对象中使用了Lombok批注来生成属性/属性的获取器/设置器。 如果您不希望所有属性都包含该类中的getter / setter,则属性可以专门接收注释。 这两个类将构成将您的数据携带到想要显示信息的任何地方的容器。

    建立一个数据库

    我使用了Mongo Docker容器进行测试。 如果您的系统上安装了MongoDB,则不必在Docker中运行实例。 您可以通过选择系统信息并按照安装说明从其网站上安装MongoDB。

    安装后,您可以通过命令行,GUI(例如MongoDB Compass)或用于连接数据源的IDE驱动程序与新的MongoDB服务器进行交互。 现在,您可以定义数据层以提取,转换和保留数据。 要设置数据库访问属性,请导航至应用程序中的applications.properties文件并提供以下内容:

     1 spring. data . mongodb . host = localhost
     2 spring. data . mongodb . port = 27017
     3 spring. data . mongodb . database = BikeStore

    定义数据访问对象/数据访问层

    数据访问层(DAL)中的数据访问对象(DAO)将定义您如何与数据库中的数据进行交互。 关于使用spring-boot-starter的很棒的事情是,查询数据库的大部分工作已经完成。

    客户 DAO开始。 src文件夹中的新dao文件夹中创建一个接口,然后创建另一个名为CustomerRepository.java的 Java类名称。 该类应如下所示:

     1 package com.stephb.JavaMongo.dao ;
     2 
     3 import com.stephb.JavaMongo.dto.Customer ;
     4 import java.util.List ;
     5 import org.springframework.data.mongodb.repository.MongoRepository ;
     6 
     7 /**
     8  *
     9  * @author stephon
    10  */

    11 public interface CustomerRepository extends MongoRepository < Customer, String > {
    12         @Override
    13         public List < Customer > findAll ( ) ;
    14         public List < Customer > findByFirstName ( String firstName ) ;
    15         public List < Customer > findByLastName ( String lastName ) ;
    16 }

    此类是使用DTO( Customer.java )和字符串从MongoRepository类扩展或继承的接口,因为它们将用于通过自定义函数进行查询。 因为您从此类继承而来,所以您可以访问许多函数,这些函数允许持久化和查询对象,而无需实现或引用自己的函数。 例如,实例化CustomerRepository对象后,可以立即使用Save函数。 如果需要更多扩展功能,也可以覆盖这些功能。 给定对象的特定元素,我创建了一些自定义查询来搜索我的集合。

    Bike对象还具有用于与数据库进行交互的存储库。 实施它与CustomerRepository非常相似。 它应该看起来像:

     1 package com.stephb.JavaMongo.dao ;
     2 
     3 import com.stephb.JavaMongo.dto.Bike ;
     4 import java.util.List ;
     5 import org.springframework.data.mongodb.repository.MongoRepository ;
     6 
     7 /**
     8  *
     9  * @author stephon
    10  */

    11 public interface BikeRepository extends MongoRepository < Bike,String > {
    12         public Bike findByModelNumber ( String modelNumber ) ;
    13         @Override
    14         public List < Bike > findAll ( ) ;
    15         public List < Bike > findByColor ( String color ) ;
    16 }

    运行程序

    现在,您已经有了一种结构化数据的方式,并且可以对数据进行提取,转换和持久化,然后运行程序!

    导航到您的Application.java文件(根据您为应用程序命名的名称,它可能具有不同的名称,但应包含“ application”)。 定义类的位置,然后包括一个实现CommandLineRunner 这将允许您实现运行方法来创建命令行应用程序。 覆盖CommandLineRunner界面提供的run方法,并包括以下内容以测试BikeRepository

     1 package com.stephb.JavaMongo ;
     2 
     3 import com.stephb.JavaMongo.dao.BikeRepository ;
     4 import com.stephb.JavaMongo.dao.CustomerRepository ;
     5 import com.stephb.JavaMongo.dto.Bike ;
     6 import java.util.Scanner ;
     7 import org.springframework.beans.factory.annotation.Autowired ;
     8 import org.springframework.boot.CommandLineRunner ;
     9 import org.springframework.boot.SpringApplication ;
    10 import org.springframework.boot.autoconfigure.SpringBootApplication ;
    11 
    12 
    13 @SpringBootApplication
    14 public class JavaMongoApplication implements CommandLineRunner {
    15                 @Autowired
    16                 private BikeRepository bikeRepo ;
    17                 private CustomerRepository custRepo ;
    18                 
    19     public static void main ( String [ ] args ) {
    20                         SpringApplication. run ( JavaMongoApplication. class , args ) ;
    21     }
    22         @Override
    23         public void run ( String ... args ) throws Exception {
    24                 Scanner scan = new Scanner ( System . in ) ;
    25                 String response = "" ;
    26                 boolean running = true ;
    27                 while ( running ) {
    28                         System . out . println ( "What would you like to create? \n C: The Customer \n B: Bike? \n X:Close" ) ;
    29                         response = scan. nextLine ( ) ;
    30                         if ( "B" . equals ( response. toUpperCase ( ) ) ) {
    31                                 String [ ] bikeInformation = new String [ 3 ] ;
    32                                 System . out . println ( "Enter the information for the Bike" ) ;
    33                                 System . out . println ( "Model Number" ) ;
    34                                 bikeInformation [ 0 ] = scan. nextLine ( ) ;
    35                                 System . out . println ( "Color" ) ;
    36                                 bikeInformation [ 1 ] = scan. nextLine ( ) ;
    37                                 System . out . println ( "Description" ) ;
    38                                 bikeInformation [ 2 ] = scan. nextLine ( ) ;
    39 
    40                                 Bike bike = new Bike ( ) ;
    41                                 bike. setModelNumber ( bikeInformation [ 0 ] ) ;
    42                                 bike. setColor ( bikeInformation [ 1 ] ) ;
    43                                 bike. setDescription ( bikeInformation [ 2 ] ) ;
    44 
    45                                 bike = bikeRepo. save ( bike ) ;
    46                                 System . out . println ( bike. toString ( ) ) ;
    47 
    48 
    49                         } else if ( "X" . equals ( response. toUpperCase ( ) ) ) {
    50                                 System . out . println ( "Bye" ) ;
    51                                 running = false ;
    52                         } else {
    53                                 System . out . println ( "Sorry nothing else works right now!" ) ;
    54                         }
    55                 }
    56                 
    57         }
    58 }

    @Autowired批注允许自动依赖项注入BikeRepositoryCustomerRepository Bean。 您将使用这些类来持久化并从数据库中收集数据。

    你有它! 您已经创建了一个命令行应用程序,该应用程序连接到数据库并能够以最少的代码执行CRUD操作。

    结论

    从对象和类之类的编程语言概念转换为在数据库中存储,检索或更改数据的调用对于构建应用程序至关重要。 Java Persistence API(JPA)是Java开发人员工具包中解决该挑战的重要工具。 您正在使用Java探索哪些数据库? 请分享评论。

    翻译自: https://opensource.com/article/19/10/using-java-persistence-api

    java持久化api

    展开全文
  • MongoDB是面向文档的开源数据库,...然后演示了如何持久保存、加载、删除和查询映射到 MongoDB的Java域模型。MongoDB是面向文档的数据库,用于存储并检索类似JavaScript 对象符号(JavaScriptObjectNotation,JSON
  • EOS数据持久性(上)

    2018-10-10 11:15:16
    虽然这个用例由于各种原因而不太适合作为生产智能合约,但开始学习数据持久性如何在EOSIO上运行而不被与eosio的multi_index功能无关的业务逻辑分心,这也算的上一个很好的合约。 第1步:创建一个新目录 之前,你创建...

    本教程假定你已经完成了EOS开发从智能合约开始

    要了解数据持久性,请编写一个简单的智能合约,作为地址记录。虽然这个用例由于各种原因而不太适合作为生产智能合约,但开始学习数据持久性如何在EOSIO上运行而不被与eosio的multi_index功能无关的业务逻辑分心,这也算的上一个很好的合约。

    第1步:创建一个新目录

    之前,你创建了一个合约目录,现在就在那里开始。

    //shell
    cd CONTRACTS_DIR

    为我们的合约创建一个新目录并进入目录:

    //c++
    mkdir addressbook
    cd addressbook

    第2步:创建并打开一个新文件

    //c++
    touch addressbook.cpp

    在你喜欢的编辑器中打开文件。

    第3步:编写扩展标准类并包含EOSIO

    在之前的教程中,你创建了一个hello world合约,并学习了基础知识。你将熟悉下面的结构,该类已分别命名为addressbook

    //c++
    
    #include <eosiolib/eosio.hpp>
    #include <eosiolib/print.hpp>
    using namespace eosio;
    
    class addressbook : public eosio::contract {
      public:
    
      private: 
    
    };

    第4步:为表创建数据结构

    在配置和实例化表之前,需要编写表示地址簿数据结构的结构。 将此视为“schema”。 由于它是一个地址簿,该表将包含人,因此创建一个名为“person”的struct

    //c++
    struct person {};

    定义multi_index表的模式时,需要使用唯一值作为主键。

    对于此合约,请使用类型为account_name的名为“key”的字段。此合约将为每个用户提供一个唯一条目,因此该密钥将是基于用户的account_name保证一致性且有唯一值。

    //c++
    struct person {
        account_name key; 
    };

    由于该合约是地址簿,因此可能应该为每个条目或人员存储一些相关的详细信息。

    //c++
    struct person {
     account_name key;
     string first_name;
     string last_name;
     string street;
     string city;
     string state;
    };

    ok。基本schema架构现已完成。接下来,定义一个primary_key方法,该方法将由multi_index迭代器使用。每个multi_index架构都需要一个主键。要实现此目的,只需创建一个名为primary_key()的方法,并返回一个值,在本例中为结构中定义的成员key

    //c++
    struct person {
     account_name key;
     string first_name;
     string last_name;
     string street;
     string city;
     string state;
    
     uint64_t primary_key() const { return key; }
    };

    步骤5:配置多索引表

    现在已经使用结构定义了表的模式,我们需要配置表。需要对eosio::multi_index构造函数进行命名和配置,以使用我们之前定义的结构。

    //c++
    typedef eosio::multi_index<N(people), person> address_index;
    • 我们把N(N(base32 X),用于从X的base32编码的字符串解释生成编译时uint64_t)命名为表。该表包含许多不同的个体“persons”,因此将表命名为“people”。
    • 传入上一步中定义的单person结构
    • 声明此表的类型。此类型将用于稍后实例化此表。
    //c++
    //configure the table
    typedef eosio::multi_index<N(people), person> address_index;

    使用上述multi_index配置,有一个名为peoplemulti_index表,该表基于使用struct person的该表的单个行的模式或数据结构。

    到目前为止,我们的文件应该是这样的。

    //c++
    
    #include <eosiolib/eosio.hpp>
    #include <eosiolib/print.hpp>
    
    using namespace eosio;
    
    class addressbook : public eosio::contract {
    
      public:
    
      private:
        struct [[eosio::table]] person {
          account_name key;
          std::string first_name;
          std::string last_name;
          std::string street;
          std::string city;
          std::string state;
    
          uint64_t primary_key() const { return key; }
        };
    
        typedef eosio::multi_index<N(people), person> address_index;
    
    };

    第6步:构造函数

    使用C++类时,你应该创建的第一个公共方法是构造函数。

    我们的构造函数将负责最初设置合约。

    EOSIO合约扩展了合约类。使用合约范围初始化我们的父合约类。我们的构造函数传递的范围参数是正在部署合约的区块链上的帐户。

    //c++
    addressbook(account_name self): contract(self){}

    第7步:向表中添加记录

    以前,多索引表的主键被定义为强制执行此合约将仅为每个用户存储一条记录。为了使其全部工作,需要建立一些关于设计的假设。

    • 授权修改通讯簿的唯一帐户是用户。
    • 我们表的primary_key是唯一的,基于用户名。
    • 对于可用性,合约应该能够通过单个操作创建和修改表行。

    在eosio中,区块链具有唯一的帐户,因此在此特定用例中,account_name是作为primary_key的理想候选者。account_name类型是uint64_t

    接下来,为用户定义添加或更新记录的操作。此操作需要接受此操作需要能够放置(创建)或修改的任何值。

    格式化定义以使其更容易阅读。为了简化用户体验和界面,有一个方法负责创建和修改行。因此,将其命名为“upsert”,即“update”和“insert”的组合。

    //c++
    
    void upsert(
      account_name user, 
      std::string first_name, 
      std::string last_name, 
      std::string street, 
      std::string city, 
      std::string state
    ) {}

    早些时候,有人提到只有用户才能控制自己的记录,因为这个合约是选择加入的。为此,请使用eosio.cdt提供的require_auth方法。此方法接受一个参数,即account_name类型,并断言执行交易的帐户等于提供的值。

    //c++
    void upsert(account_name user, std::string first_name, std::string last_name, std::string street, std::string city, std::string state) {
      require_auth( user );
    }

    实例化表。之前,配置了multi_index表,并将其声明为address_index。要实例化一个表,请考虑这两个必需参数:

    • “code”,代表合约的帐户。可以通过作用域_self变量访问此值。
    • 定义合约付款人的范围“scope”,该用例中的合约负责支付ram费用。
    //c++
    void upsert(account_name user, std::string first_name, std::string last_name, std::string street, std::string city, std::string state) {
      require_auth( user );
      address_index addresses(_self, _self );
    }

    接下来,查询迭代器,将其设置为变量,因为此迭代器将被多次使用。

    //c++
    void upsert(account_name user, std::string first_name, std::string last_name, std::string street, std::string city, std::string state) {
      require_auth( user );
      address_index addresses(_self, _self );
      auto iterator = addresses.find(user);
    }

    安全性已经建立并且表格实例化了,太棒了!

    接下来,编写用于创建或修改表的逻辑。检测特定用户是否已存在。

    为此,请通过传递user参数来使用表的find方法。find方法将返回一个迭代器。使用该迭代器对end方法进行测试。end方法是“null”的别名。

    //c++
    void upsert(account_name user, std::string first_name, std::string last_name, std::string street, std::string city, std::string state) {
      require_auth( user );
      auto iterator = addresses.find( user );
      address_index addresses(_self, _self );
      if( addresses.find( user ) == addresses.end() )
      {
        //The user isn't in the table
      }
      else {
        //The user is in the table
      }
    }

    使用multi_index方法emplace在表中创建记录。此方法接受两个参数,即此记录的范围“scope”和回调函数。

    emplace方法的回调函数必须使用lamba来创建接口。在body中分配行的值和提供给upsert的值。

    //c++
    void upsert(account_name user, std::string first_name, std::string last_name, std::string street, std::string city, std::string state) {
      require_auth( user );
      address_index addresses(_self, _self );
      auto iterator = addresses.find( user );
      if( iterator == addresses.end() )
      {
            addresses.emplace(user, [&]( auto& row ) {
          row.key = user;
          row.first_name = first_name;
          row.last_name = last_name;
          row.street = street;
          row.city = city;
          row.state = state;
        });
      }
      else {
        //The user is in the table
      }
    }

    接下来,处理“upsert”函数的修改或更新。使用modify方法,传递一些参数

    • 前面定义的迭代器,在调用此操作时设置为声明的用户。
    • 范围“scope”或“ram payer”ram消费者,在这种情况下是用户,如先前在提出该合约的设计时所决定的那样。
    • 回调函数用于处理表的修改。
    //c++
    void upsert(account_name user, std::string first_name, std::string last_name, std::string street, std::string city, std::string state) {
      require_auth( user );
      address_index addresses(_self, _self );
      auto iterator = addresses.find( user );
      if( iterator == addresses.end() )
      {
       addresses.emplace(user, [&]( auto& row ) {
         row.key = user;
         row.first_name = first_name;
         row.last_name = last_name;
         row.street = street;
         row.city = city;
         row.state = state;
       });
      }
      else {
       addresses.modify(iterator, user, [&]( auto& row ) {
         row.first_name = first_name;
         row.last_name = last_name;
         row.street = street;
         row.city = city;
         row.state = state;
       });
      }
    }

    地址簿合约现在具有一个功能操作,如果该记录尚不存在,将允许用户在表中创建一行,如果已存在则修改它。

    但是如果用户想要完全删除记录呢?请看EOS的数据持久性(下)

    对了,文中调用的各种eos方法可以参考EOS.IO C语言API手册

    ======================================================================

    分享一个交互式的在线编程实战,EOS智能合约与DApp开发入门

    EOS教程

    本课程帮助你快速入门EOS区块链去中心化应用的开发,内容涵盖EOS工具链、账户与钱包、发行代币、智能合约开发与部署、使用代码与智能合约交互等核心知识点,最后综合运用各知识点完成一个便签DApp的开发。

    这里是原文

    转载于:https://blog.51cto.com/13697184/2298099

    展开全文
  • 本文主要讲了 Redis 的持久化相关功能持久化一直是影响 Redis 性能的高发地,也是面试中经常被问到的。 包括 RDB 相关的特定和优缺点,AOF 的优缺点,事实上,由于 RDB 的数据实时问题,目前用 AOF 比较多了,而...
  •  原子是指事务包含的所有操作要么全部成功,要么全部失败回滚,这和前面两篇博客介绍事务的功能是一样的概念,因此事务的操作如果成功就必须要完全应用到数据库,如果操作失败则不能对数据库有任何影响。...
  • 一、前言 本文主要讲了 Redis 的持久化相关功能持久化一直是影响 Redis 性能的高发地,也是面试中经常被问到的。 包括 RDB 相关的特定和优缺点,AOF 的优缺点,事实上,由于 RDB 的数据实时问题,目前用 AOF ...
  • 原文链接:...包括 RDB 相关的特定和优缺点,AOF 的优缺点,事实上,由于 RDB 的数据实时问题,目前用 AOF 比较多了,而持久化恢复也是优先 AOF。RDB 是旧的模式,现...
  • 专注于Java领域优质技术,欢迎关注一、前言本文主要讲了 Redis 的持久化相关功能持久化一直是影响 Redis 性能的高发地,也是面试中经常被问到的。包括 RDB 相关的特定和优缺点,AOF 的优缺点,事实上,由于 RDB 的...
  • 持久功能将内存中的数据同步到磁盘来避免Redis发生异常导致数据丢失的情况。当Redis实例重启时,即可利用之前持久化的文件实现数据恢复。接下来,本文介绍两种持久化的运行机制和优缺点。一 RDBRDB是默认的持久化...
  • 欢迎关注公众号:慕容千语的架构笔记一、前言本文主要讲了 Redis 的持久化相关功能持久化一直是影响 Redis 性能的高发地,也是面试中经常被问到的。包括 RDB 相关的特定和优缺点,AOF 的优缺点,事实上,由于 RDB ...
  • 虽然这个用例由于各种原因而不太适合作为生产智能合约,但开始学习数据持久性如何在EOSIO上运行而不被与eosio的multi_index功能无关的业务逻辑分心,这也算的上一个很好的合约。 第1步:创建一个新目录 之前,你...
  • 虽然这个用例由于各种原因而不太适合作为生产智能合约,但开始学习数据持久性如何在EOSIO上运行而不被与eosio的multi_index功能无关的业务逻辑分心,这也算的上一个很好的合约。 第1步:创建一个新目录 之前,你创建...
  • 本文主要讲了 Redis 的持久化相关功能持久化一直是影响 Redis 性能的高发地,也是面试中经常被问到的。包括 RDB 相关的特定和优缺点,AOF 的优缺点,事实上,由于 RDB 的数据实时问题,目前用 AOF 比较多了。而...
  • 本文主要讲了 Redis 的持久化相关功能持久化一直是影响 Redis 性能的高发地,也是面试中经常被问到的。 包括 RDB 相关的特定和优缺点,AOF 的优缺点,事实上,由于 RDB 的数据实时问题,目前用 AOF 比较多了,...
  • 使用 Morphia 持久保存、加载、删除和查询映射到 MongoDB 的 Java 域模型 ...简介: MongoDB 是面向文档的开源数据库,Morphia 是面向 ...然后演示了如何持久保存、加载、删除和查询映射到 MongoDB 的 Java™...
  • 一、前言本文主要讲了 Redis 的持久化相关功能持久化一直是影响 Redis 性能的高发地,也是面试中经常被问到的。包括 RDB 相关的特定和优缺点,AOF 的优缺点,事实上,由于 RDB 的数据实时问题,目前用 AOF 比较...
  • 演示尖端技术的使用,例如在集群上运行的持久性存储,基于自定义指标的自动扩展和聚合的API服务器 而且,此存储库中包含的Kubernetes yaml清单是多体系结构,可在32位和64位ARM上运行! 我自己在家中的设置包含以下...
  • Redis是一个基于键值(K-V)的高速缓存软件,和他具有相同功能的软件有memcached,但其支持更为复杂的数据结构,例如:List,set,sorted set,同时redis具有持久性功能。redis究竟是什么?对于不同的应用场合,对redis...
  • 一、前言本文主要讲了 Redis 的持久化相关功能持久化一直是影响 Redis 性能的高发地,也是面试中经常被问到的。包括 RDB 相关的特定和优缺点,AOF 的优缺点,事实上,由于 RDB 的数据实时问题,目前用 AOF 比较...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 408
精华内容 163
关键字:

性功能如何持久