[原]Pro*C介绍-内嵌SQL

2023-11-19

[ Translate by Z.Jingwei. Document address:http://www-db.stanford.edu/~ullman/fcdb/oracle/or-proc.html ]

Pro*C介绍
内嵌SQL



概要

内嵌SQL是结合高级语言如C/C++的计算能力和SQL数据库处理能力的一种方法。它允许你在程序中执行任意的SQL语句。Oracle的嵌入SQL环境称为Pro*C。

Pro*C程序分两步编译。首先,Pro*C的预编译器识别出嵌入在程序中的SQL语句,并将这些语句转换为对SQL运行时库(SQL runtime library)中功能(functions)的适当调用。输出是纯C/C++代码和未被处理的纯C/C++代码。然后,用常规C/C++编译器编译代码并生成可执行程序。更详细的内容请参考。

Demo程序

Pro*C语法

SQL

所有SQL语句都要以EXEC SQL开始,并用分号";"结束。SQL语句可以放置在C/C++块中的任何地方,但可执行的(SQL)语句应该在声明语句后面。例:

{
    int a;
    /* ... */
    EXEC SQL SELECT salary INTO :a
             FROM Employee
             WHERE SSN=876543210;
    /* ... */
    printf("The salary is %d/n", a);
    /* ... */
}

预处理指令

能够在Pro*C中正常工作的C/C++预处理指令是#include#if。Pro*C不能识别#define。下面的代码是错误的:

#define THE_SSN 876543210
/* ... */
EXEC SQL SELECT salary INTO :a
         FROM Employee
         WHERE SSN = THE_SSN;/* INVALID */

语句标号

可以在SQL中跳转到C/C++标记

    EXEC SQL WHENEVER SQLERROR GOTO error_in_SQL;
    /* ... */
error_in_SQL:
    /* do error handling */

我们会在后面的一节中讲到有关WHENEVER的含意。

错误处理一节中讲到有关 WHENEVER的含意。

宿主变量

基础

宿主变量是连接宿主程序与数据库的关键。宿主变量表达式必须视为(resolve to)左值(能被赋值)。你可以像声明普通C变量一样,按着C的语法规则声明宿主变量。宿主变量的声明可以放置在任何C变量声明可以放置的地方。(C++用户需要使用"DECLARE SECTION";参考) Oracle可以使用的C数据类型包括:

C++ Users) Oracle可以使用的C数据类型包括:
  • char
  • char[n]
  • int
  • short
  • long
  • float
  • double
  • VARCHAR[n] - 它是能被Pro*C的预编译器识别的预处理类型(psuedo-type)。它用来 表示由空白填充(blank-padded,译注:'/0')的变长字符串。Pro*C预编译器会把它转换为有一个2字节(byte)长的域和一个n字(byte)长的字符数组的结构体。

你不能指定寄存器存储类型(译注:指针)为宿主变量。

可以在SQL表达式中使用冒号":"做前缀来引用一个宿主变量,但不能在C表达式中用分号做前缀。当使用字符串作为宿主变量时,必须省略引用;Pro*C明白你正指定一个基于宿主变量声明类型的字符串(译注:这句的意思是,当定义一个字符串做为宿主变量时char *str="string",在嵌入SQL中使用时,要省略"*"而不是*str)。不能将C函数调用和多数的指针计算表达式作为宿主变量使用,即使它们确实被解释为左值。下面的代码同时说明了合法和不合法的宿主变量的引用:

int deptnos[3] = { 000, 111, 222 };
int get_deptno() { return deptnos[2]; }
int *get_deptnoptr() { return &(deptnos[2]); }
int main() 
{
    int x; char *y; int z;
    /* ... */
    EXEC SQL INSERT INTO emp(empno, ename, deptno)
        VALUES(:x, :y, :z); /* LEGAL */
    EXEC SQL INSERT INTO emp(empno, ename, deptno)
        VALUES(:x + 1,  /* LEGAL: the reference is to x */
               'Big Shot',  /* LEGAL: but not really a host var */
               :deptnos[2]);/* LEGAL: array element is fine */
    EXEC SQL INSERT INTO emp(empno, ename, deptno)
        VALUES(:x, :y,
               :(*(deptnos+2)));/* ILLEGAL: although it has anlvalue */
    EXEC SQL INSERT INTO emp(empno, ename, deptno)
        VALUES(:x, :y,
               :get_deptno());  /* ILLEGAL: no function calls */
    EXEC SQL INSERT INTO emp(empno, ename, deptno)
        VALUES(:x, :y,
               :(*get_depnoptr())); /* ILLEGAL: although it has an lvalue */
    /* ... */
}


指针

可以在SQL表达式中使用普通C语法声明的指针。通常使用一个冒号做前缀:

int*x;
/*...*/
EXEC SQL SELECT xyz INTO :x FROM ...;

这个SELECT语句的结果会写入*x,而不是x

结构

结构同样可以作为宿主变量使用,如下面例子:

typedef struct {
    char name[21];/* one greater than column length; for '/0' */
    int SSN;
} Emp;
/* ... */
Emp bigshot;
/* ... */
EXEC SQL INSERT INTO emp (ename, eSSN)
    VALUES (:bigshot);

数组

像下面这样使用宿主数组:

int emp_number[50];
char name[50][11];
/* ... */
EXEC SQL INSERT INTO emp(emp_number, name)
    VALUES (:emp_number, :emp_name);

这样会一次插入所有的50个元素(tuples)。

数组只能是一维数组。例子中的char name[50][11]可能看起来与这个规则矛盾,然而,Pro*C实际上把name视为一维字符串数组而不是二维字符数组。也可以使用结构数组。

当使用数组存放查询结果时,如果宿主数组的大小(n)小于实际查询后返回的结果数量时,那么只有(查询出来的)前n个结果被填入宿主数组。

指示器变量

指示器实际上是附在宿主变量后的"NULL标记"。每一个宿主变量都可以选择性的关联到一个指示器变量上。指示器变量的类型必须为2字节整形值(short类型),而且必须紧随在宿主变量后且用冒号做为前缀。你也可以使用关键字INDICATOR放在宿主变量和指示器变量之间。例如:

short indicator_var;
EXEC SQL SELECT xyz INTO :host_var:indicator_var
    FROM ...;
/* ... */
EXEC SQL INSERT INTO R
    VALUES(:host_var INDICATOR :indicator_var, ...);

SELECTINTO子句中使用的指示器变量可以用来检查返回给宿主变量的值为空(NULL)或被截断的的情况。Oracle能够赋给指示器变量的值具有下面各项意义:

-1字段(译注:原文为column,意为该字段的列)值为NULL,宿主变量的值不确定。0Oracle把完整的字值赋给了宿主变量。>0Oracle把被截断的字段值赋给了宿主变量。指示器变量返回的整形值是字段的原始长度。-2Oracle把被截断的字段值赋给了宿主变量,但原字段值是不确定的。(译注:这种情况可能是数值型的值被切断后不能确定原始值)

你也可以在INSERTUPDATEVALUESSET子句中使用指示器变量指明用于输入的宿主变量为NULL值。你的程序可以赋给指示器变量的值具有如下各项意义:

-1 Oracle会忽略宿主变量的值并给字段赋一个NULL值。
>=0 Oracle会将宿主变量的值赋给字段。


数据类型同等化

Oracle认识两种数据类型:内部类型和外部类型。内部数据类型指示Oracle在数据库表中如何存储字段。外部数据类型指示如何格式化存储在宿主变量中用于输入或输出的值。在预编译期,每一个宿主变量会被赋予一个默认的Oracle外部数据类型。数据类型同等化允许你重载默认的同等化,并允许你控制Oracle输入数据的解释和输出数据的格式化。

同等化通过使用VAR表达式实现基于从变量到变量的转换。语法是:

EXEC SQL VAR <host_var> IS <type_name> [ (<length>) ];

举例来说, 假设你想从emp表中查询雇员名子,然后传给一个需要C类型(以'/0'结尾的)字符串的程序,你不需要显式的用'/0'来结束这个名子。如下面所示,简单地将宿主变量同等化为外部数据类型STRING

char emp_name[21];
EXEC SQL VAR emp_name IS STRING(21);

emp表中ename字段的长是20字符(character),因此,需要分配21字符(character)以适应'/0'结束符。Oracle的外部数据类型STRING是为C类型字符串特别设计的接口。当把ename字段值传给emp_name时,Oracle会自动用'/n'结尾。

也可以使用TYPE语句将用户自定义数据类型同等化为Oracle外部数据类型。语法是:

EXEC SQL TYPE <user_type> IS <type_name> [ (<length>) ] [REFERENCE];

可以声明一个用户自定义类型的指针,显式的如指向标量或结构的指针,或隐式的如数组,然后在TYPE表达式中使用这个类型。这种情况下,你需要在表达式后使用REFERENCE子句,如下所示:

typedef unsigned char *my_raw;
EXEC SQL TYPE my_raw IS VARRAW(4000) REFERENCE;
my_raw buffer;
/* ... */
buffer = malloc(4004);

这里,我们分配了比源类型长(4000)更多的内存,这是因为预编译器要返回长度,而且可能需要填充适当的长度以满足系统的对齐要求。

动态SQL

嵌入SQL能够满足一个固定的应用,但有时动态产生完整的SQL语句也是很重要的。对于动态SQL,语句存储在字符串变量中,PREPARE把字符串转换为SQL语句,然后用EXECUTE执行这个语句。考虑下面的例子:

char *s = "INSERT INTO emp VALUES(1234, 'jon', 3)";
EXEC SQL PREPARE q FROM :s;
EXEC SQL EXECUTE q;

PREPAREEXECUTE可放到一个语句中,像这样:

char *s = "INSERT INTO emp VALUES(1234, 'jon', 3)";
EXEC SQL EXECUTE IMMEDIATE :s;

事务

Oracle Pro*C支持标准SQL定义的事务。一个事务是一组SQL语句集合,Oracle把它当作单独的单元运行。一个事务从第一个SQL语句开始,遇到"EXEC SQL COMMIT"(执行当前事务对数据库的永久修改)或"EXEC SQL ROLLBACK"(取消从事务开始到当前位置对数据库的任何修改)时结束事务。当前事务由COMMITROLLBACK语句结束后,下一条可执行SQL语句将自动开始一个新事务。

如果程序结束时没有执行EXEC SQL COMMIT,则对数据库的所作的修改都将被忽略。

错误处理

在每个可执行的SQL表达式之后,可以在程序中检查SQLCA显式地或用WHENEVER语句隐式地得到执行状态信息。下面将详细地介绍这两种方法。

SQLCA

SQLCA(SQL Communications Area,SQL通讯区)用于在程序中检查错误和状态变化。每个可执行SQL语句执行后,Oracle 运行时会在这个结构中填入信息。

如果要使用SQLCA,你要用#include包含进sqlca.h头文件。如果在很多地方包含了头文件,你要使用#undef SQLCA来取消SQLCA的宏定义。sqlca.h中的相关程序块如下:

#ifndef SQLCA
#define SQLCA 1

struct sqlca {
    /* ub1 */ char sqlcaid[8];
    /* b4 */ long sqlabc;
    /* b4 */ long sqlcode;
    struct {
        /* ub2 */ unsigned short sqlerrml;
        /* ub1 */ char sqlerrmc[70];
    } sqlerrm;
    /* ub1 */ char sqlerrp[8];
    /* b4 */ long sqlerrd[6];
    /* ub1 */ char sqlwarn[8];
    /* ub1 */ char sqlext[8];
};
/* ... */

sqlca域有下列的意义:

sqlcaid该字符串域初始化为"SQLCA",以指明这是个SQL通讯区。sqlcabc该整数域用byte标识SQLCA结构的长度。sqlcode这个整数域标识最近执行的SQL语句的状态码:
 
0没有错误。>0语句执行但捕获异常。当Oracle根据WHERE条件查找不到任何记录,或SELECT INTOFETCH影响记录数为0时会发生这种情况。<0由于一个错误Oracle不能执行SQL语句。当这个错误发生时,多数情况下当前的事务应该回滚(rollback)。
 sqlerrm这个内嵌结构包含两个域:  sqlerrml - 在sqlerrmc中保存的信息文本的长。 sqlerrmc - 最大到70个字符(character)的信息文本,与sqlcode中存储的错误码相似。
 sqlerrp保留sqlerrd这个二进制整形数组包含6个元素:  sqlerrd[0] - 保留 sqlerrd[1] - 保留 sqlerrd[2] - 最近被执行的SQL语句影响的记录行数。 sqlerrd[3] - 保留 sqlerrd[4] - 分析最近执行语句出现错误,错误的开始字符的偏移。 sqlerrd[5] - 保留
 sqlwarn这个单字符数组包含8个元素,用于警告标志。Oracle使用字符'W'设置一个标记。 
 
sqlwarn[0]当其它标记被设置时设置。sqlwarn[1]当输出宿主变量中保存的是被截断的字段值时设置。sqlwarn[2]当计算SQL统计如AVG或SUM时,如果一个NULL字段不能被使用时被设置。sqlwarn[3]SELECT的字段数与INTO句中指定的宿主变量数不等时设置。sqlwarn[4]当没有使用WHERE子句的UPDATEDELETE语句处理了数据表中的每一行时设置。sqlwarn[5]当由于PL/SQL编译错误而导致procedure/function/package/package body创建命令失败时设置。sqlwarn[6]不再使用sqlwarn[7]不再使用
 sqlext保留

SQLCA只能在sqlerrm域中存储最大70字符长的错误信息。要得到更长的(或嵌套的)全部错误信息字符,可以使用sqlglm()函数:

void sqlglm(char *msg_buf, size_t *buf_size, size_t *msg_length);

msg_buf是Oracle存储错误信息的字符缓冲;buf_size指定msg_buf的长(byte); Oracle在*msg_length中存放实际的错误信息长。Oracle错误信息的最大长度是512字节(byte)。

WHENEVER语句

这个表达式进行自动错误检查和处理。语法是:

EXEC SQL WHENEVER <condition> <action>;

Oracle自动检查<condition>的SQLCA,当条件被检测到时,程序会自动执行<action>

<condition>可以是下列各项:

SQLWARNING - 由于Oracle返回一个警告而设置sqlwarn[0] SQLERROR - 由于Oracle返回一个错误, sqlcode的值为负 NOT FOUND - 由于Oracle按WHERE的条件没有找到任何一条记录,或SELECT INTOFETCH返回0条记录,而使sqlcode为正

<action> 可以为下列各项:

CONTINUE - 只要可能,程序会尝试继续运行之后的语句 DO - 程序将控制权交给一个错误处理模块 GOTO <label> - 程序跳转到被标示的语句 STOP - 调用exit()结束程序,回滚未提交的操作

下面是WHENEVER语句的例子:

EXEC SQL WHENEVER SQLWARNING DO print_warning_msg();
EXEC SQL WHENEVER NOT FOUND GOTO handle_empty;

下面是一个更详细的例子:

/* code to find student name given id */
/* ... */
for (;;)
{
    printf("Give student id number : ");
    scanf("%d", &id);
    EXEC SQL WHENEVER NOT FOUND GOTO notfound;
    EXEC SQL SELECT studentname INTO :st_name
             FROM   student
             WHERE  studentid = :id;
    printf("Name of student is %s./n", st_name);
    continue;
notfound:
    printf("No record exists for id %d!/n", id);
}
/* ... */

注意WHENEVER表达式不遵从标准C的作用域规则,整个程序都是它的作用域。举例来说,如果下面的语句在你程序中的什么地方(如在一个循环之前):

EXEC SQL WHENEVER NOT FOUND DO break; 

这个文件在这行之后出现的所有SQL语句都会受其影响。当不再需要WHENEVER 的来影响程序时(比如在你的循环之后),确保使用下面的语句取消它的使用。

EXEC SQL WHENEVER NOT FOUND CONTINUE; 

Demo程序

注意: 例程会创建、使用四个表:DEPTEMPPAY1PAY2。注意你的数据库中可能会存在相同名子的表!

在leland系统的/afs/ir/class/cs145/code/proc下有很多例程。它们被命名为sample*.pc(C用户)和cppdemo*.pc(C++用户)。 ".pc"是Pro*C代码的扩展名。由于有几个固定的步骤复制这些文件,所以不要手工复制它们。下面介绍如何下载和设置例程:

确认你已经运行了source /afs/ir/class/cs145/all.env 在你的目录下,运行load_samples <db_username> <db_passwd> <sample_dir><sample_idr>是你想放置例程的地方(例:load_samples sally etaoinshrdlu cs145_samplescd <sample_dir> 运行make samples(C++用户运行make cppsamples)编译所有的例程。

第2步将会建立样品数据库,创建在<sample_dir>指定的新目录,然后把文件复制到目录下。它会在例程中修改你的用户名和密码,所有你不必每次运行例程时都要输入用户名和密码。sample1cppdemo1也为用户提供了输入用户名和密码的接口,当你想要学习如何使用的时候。如果在第2步输入用户名和密码时产生了任何错误,只要在你的目录下运行clean_sample <db_username> <db_passwd> & lt;sample_dir>,然后重做第2步到第4步。

对于第4步,你可以单独编译每一个例程。比如单独编译sample1.pc。编译过程实际上有两句:

proc iname=sample1.pc
把内嵌SQL代码转换为相应的库调用,输出sample1.c cc <a_number_of_flags_here> sample1.c
主成可执行的sample1

编译你自己的代码,如foo.pc,只要修改Makefile的几个变量:在SAMPLES变量中加入foo程序名,在SAMPLE_SRC变量中加入foo.pc源文件名。然后,写好foo.pcmake foofoo.pc被预编译为foo.c,再编译为可执行的foo。C++用户要把程序名和源文件名加入到CPPSAMPLECPPSAMPLE_SRC而不是SAMPLESSAMPLE_SRC

例程运行于下面的数据库表上:

CREATE TABLE DEPT
    (DEPTNO    NUMBER(2) NOT NULL,
     DNAME     VARCHAR2(14),
     LOC       VARCHAR2(13));

CREATE TABLE EMP
    (EMPNO     NUMBER(4) NOT NULL,
     ENAME     VARCHAR2(10),
     JOB       VARCHAR2(9),
     MGR       NUMBER(4),
     HIREDATE  DATE,
     SAL       NUMBER(7, 2),
     COMM      NUMBER(7, 2),
     DEPTNO    NUMBER(2));

CREATE TABLE PAY1
    (ENAME     VARCHAR2(10),
     SAL       NUMBER(7, 2));

CREATE TABLE PAY2
    (ENAME     VARCHAR2(10),
     SAL       NUMBER(7, 2));

当在第2步运行load_samples的时候这些表就自动创建好了。一些tuples(译注:没找到合适的词,把原词放这了)也插入了。你可以在程序运行前查看这些表也可以任意操作这些表(如:插入、删除或是更新tuples)。当你运行clean_sample时,这些表自动被删除。注意:clean_sample也会清理整个<sample_dir>;

确保在运行这个命令之前将你自己的文件转移到其它的地方!

你应该在运行它之前看一看源代码,头部的注释描述了程序都做些什么。例如,sample1从一个雇员的EMPNO 得到他的名子和工资,从EMP表中得到的那个雇员的佣金。

通过学习源程序你应该可以学到下面的东西:

如何从主机连接到Oracle 如何在C/C++中嵌入SQL 如何使用游标 如何使用宿主变量与数据库通讯 如何使用WHENEVER进行不同的错误处理动作 如何使用指示器变量检测输出中的空值

现在,你可以使用这些技术编写你自己的数据库应用程序了。And have fun!

C++用户

要使用预编译器生成合适的C++代码,你需要注意下面的事项:

代码被预编译器展开。要得到C++代码,你需要在执行proc时设置CODE=CPP选项。 解析能力。procPARSE选项可以是下面的值: PARSE=NONE. C预处理指令只能在声明节中被解析,所以所有的宿主变量需要在声明节中声明。 PARSE=PARTIAL. C预处理指令能被解析;然而,所有的宿主变量需要在声明节中声明。 PARSE=FULL. C预处理指令能被解析,而且宿主变量可以声明在任何地方。当CODE不为 CPP时,这是默认设置;但当CODE=CPP时,指定PARSE=FULL却是个错误。 所以,C++用户必须指定PARSE=NONEPARSE=PARTIAL,因此这也失去了在任意地方声明宿主变量的自由。更有,宿主变量必须被包在一个声明节中,如下:
EXEC SQL BEGIN DECLARE SECTION;
    // declarations...
EXEC SQL END DECLARE SECTION;
你需要使用这种方法去声明所有的宿主和指示器变量。 文件扩展名。你要指定设置CPP_SUFFIX=ccCPP_SUFFIX=C。 头文件定位。默认情况下,proc像标准定位stdio.h文件一样查找头文件。然而C++有自己的头文件,如iostream.h,被放置在别处。所以,你需要使用SYS_INCLUDE选项指定proc查找头文件的路径。

Pro*C支持的嵌入SQL语句列表

声明表达式
EXEC SQL ARRAYLEN 在PL/SQL中使用宿主变量
EXEC SQL BEGIN DECLARE SECTION
EXEC SQL END DECLARE SECTION
声明宿主变量
EXEC SQL DECLARE 给Oracle对像命名
EXEC SQL INCLUDE 从文件中复制
EXEC SQL TYPE 同等化数据类型
EXEC SQL VAR 同等化变量
EXEC SQL WHENEVER 处理运行时错误
执行表达式
EXEC SQL ALLOCATE 声明、控制Oracle数据
EXEC SQL ALTER
EXEC SQL ANALYZE
EXEC SQL AUDIT
EXEC SQL COMMENT
EXEC SQL CONNECT
EXEC SQL CREATE
EXEC SQL DROP
EXEC SQL GRANT
EXEC SQL NOAUDIT
EXEC SQL RENAME
EXEC SQL REVOKE
EXEC SQL TRUNCATE
EXEC SQL CLOSE
EXEC SQL DELETE 排序、修改Oracle数据
EXEC SQL EXPLAIN PLAN
EXEC SQL FETCH
EXEC SQL INSERT
EXEC SQL LOCK TABLE
EXEC SQL OPEN
EXEC SQL SELECT
EXEC SQL UPDATE
EXEC SQL COMMIT 处理事务
EXEC SQL ROLLBACK
EXEC SQL SAVEPOINT
EXEC SQL SET TRANSACTION
EXEC SQL DESCRIBE 使用动态SQL
EXEC SQL EXECUTE
EXEC SQL PREPARE
EXEC SQL ALTER SESSION 控制会话
EXEC SQL SET ROLE
EXEC SQL EXECUTE
END-EXEC
内嵌PL/SQL块


This document was written originally by Ankur Jain and Jeff Ullman for CS145, Autumn 1997; revised by Jun Yang for Prof. Jennifer Widom's CS145 class in Spring, 1998; further revisions by Roy Goldman for Prof. Jeff Ullman's CS145 class in Autumn, 1999; further revisions by Calvin Yang for Prof. Jennifer Widom's CS145 class in Spring, 2002.
作者:zjingwei 发表于2005-3-14 9:31:00 原文链接
阅读:1320 评论:0 查看评论

转载于:https://www.cnblogs.com/basecn/archive/2005/03/14/3264288.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

[原]Pro*C介绍-内嵌SQL 的相关文章

  • 枚举的子类化

    有没有一种简单的方法来子类化Javaenum 我问这个问题是因为我有大约 10 个实现相同接口的对象 但它们对某些方法也有相同的实现 因此我想通过将所有相同的实现放置在扩展的中间对象中来重用代码Enum它也是我需要的所有其他类的超类 或许事
  • “源兼容性”和“目标兼容性”有什么区别?

    之间有什么关系 区别sourceCompatibility and targetCompatibility 当它们设置为不同的值时会发生什么 根据工具链和兼容性 https docs gradle org current userguide
  • java程序有多少种结束方式?

    我知道使用 System exit 0 可以结束一个java程序 例如 如果我有一个JFrame窗口 它会关闭并结束程序 但我想知道还有多少其他方法 可以关闭它并结束程序 包括发生错误时 程序会被关闭 JFrame也会被关闭吗 添加到其他答
  • 在不支持 CAS 操作的处理器上进行 CompareAndSet

    今天 我在一次采访中被问到下一个问题 如果您在具有不支持 CAS 操作的处理器的机器上调用 AtomicLong 的compareAndSet 方法 会发生什么情况 您能否帮我解决这个问题 并在可能的情况下提供一些全面描述的链接 From
  • Java LostFocus 和 InputVerifier,按反向制表符顺序移动

    我有一个 GUI 应用程序 它使用 InputVerifier 在产生焦点之前检查文本字段的内容 这都是很正常的 然而 昨天发现了一个问题 这似乎是一个错误 但我在任何地方都找不到任何提及它的地方 在我将其报告为错误之前 我想我应该问 我在
  • 查看Java Agent修改的Java类的源代码

    我需要了解 Java 代理如何修改我的初始类 以便我能够理解代码的作用 build gradle configurations jar archiveName agent2 jar jar manifest attributes Prema
  • 自定义列表字段点击事件

    我正在编写一个应用程序 其中我创建了用于显示列表视图的自定义列表字段 我的 CustomListField 包含连续的一个图像和文本 我正在通过单击列表字段行获取字段更改侦听器 但我也想将字段更改侦听器放在图像上 谁能告诉我我该怎么做 这是
  • 未装饰窗户的 Windows Snap 功能?

    有谁知道如何允许未装饰的窗户使用此功能 唯一的选择就是重新实施它 有任何想法吗 谢谢 可停靠可能是唯一的JToolBar http docs oracle com javase tutorial uiswing components too
  • 为什么 jar 执行的通配符在 docker CMD 中不起作用?

    我有一个Dockerfile与以下CMD启动我的 Spring Boot 应用程序 FROM java 8 jre CMD java jar app file jar 当我尝试从创建的图像启动容器时 我得到 Error Unable to
  • Java AES 256 加密

    我有下面的 java 代码来加密使用 64 个字符密钥的字符串 我的问题是这会是 AES 256 加密吗 String keyString C0BAE23DF8B51807B3E17D21925FADF273A70181E1D81B8EDE
  • ThreeTen 向后移植与 JSR-310 的比较

    由于某些原因 我们现在无法使用 java 8 我们仍然停留在 java 7 上 不过 我想使用新的JSR 310 date time APIs现在 使用官方向后移植 ThreeTen http www threeten org threet
  • Mockito 和 Hamcrest:如何验证 Collection 参数的调用?

    我遇到了 Mockito 和 Hamcrest 的泛型问题 请假设以下界面 public interface Service void perform Collection
  • 2^31 次方的 Java 指数错误 [重复]

    这个问题在这里已经有答案了 我正在编写一个java程序来输出2的指数幂 顺便说一句 我不能使用Math pow 但是在 2 31 和 2 32 处我得到了其他东西 另外 我不打算接受负整数 My code class PrintPowers
  • 如何更改 Swagger-ui URL 前缀?

    我正在使用 Springfox Swagger2 和 Spring boot 1 5 9 我可以通过此链接访问 swagger UI http localhost 8090 swagger ui html http localhost 80
  • 为什么解析这个 JSON 会抛出错误?

    我正在尝试解析这个 JSONObject query yahoo count 1 results rate Name USD INR id USDINR Time 12 19pm Date 10 31 2015 Bid 65 405 Ask
  • 如何在 IntelliJ IDEA 中运行 akka actor

    来自 Akka 网站文档 然后 这个主要方法将创建所需的基础设施 运行演员 启动给定的主要演员并安排 一旦主要参与者终止 整个应用程序就会关闭 因此 您将能够使用类似于以下的命令运行上面的代码 下列的 java classpath akka
  • 无需递归即可对可观察结果进行分页 - RxJava

    我有一个非常标准的 API 分页问题 您可以通过一些简单的递归来处理 这是一个捏造的例子 public Observable
  • 如何向页面添加 HTML 页眉和页脚?

    如何使用 itext 从 html 源添加标题到 pdf 目前 我们已经扩展了 PdfPageEventHelper 并重写了这些方法 工作正常 但当我到达 2 个以上页面时 它会抛出 RuntimeWorkerException Over
  • Azure Java SDK:ServiceException:ForbiddenError:

    尝试了基本位置检索器代码 如下所示 String uri https management core windows net String subscriptionId XXXXXXXX 5fad XXXXXX 9dfa XXXXXX St
  • 使用 Apache 允许 Glassfish 和 PHP 在同一服务器中协同工作

    是否可以建立从 Java 到 php 文件的桥梁 我有一个用 Java 编写的应用程序 我需要执行http piwik org http piwik org 这是用 PHP 编写的 在服务器中 我正在运行 PHP 但无法从浏览器访问 php

随机推荐

  • REUSE_ALV_FIELDCATALOG_MERGE

    作用 根据程序中的数据内表结构 来自动生成FIELDCAT 内表 不用定义宏或者Form来一个个加入 会根据内表结构所参照的词典类型来自动完成如表标题字段名的生成 得到大概的FIELDCAT 后 可以再根据特殊情况再修改FIELDCAT 内
  • javaSE基础学习总结之开发团队调度软件练习

    java第一阶段学习总结 开发团队调度软件的实现 1 项目需求 2 项目MVC架构 3 创建com mvc team domian模块 4 创建com mvc team service模块 下面展示一些 内联代码片 5 创建com mvc
  • UI图片移动

    local x y 0 149 local run 0 local pi0 20 ui 图片2 右移动3 左移动4 ui 7266427303413860920 7266427303413860920 2 72664273034138609
  • 10个有用的Siebel标准功能

    作为第一篇blog 不想罗列一些Siebel的市场信息或者功能介绍等Overview 以下Siebel非常有用的10个小的tip 1 自定义数据显示格式 用户可以根据自己需要隐藏界面上的某些列 也可以通过拖放的方式控制列显示的顺序 2 自动
  • docker && Tugraph

    拉取tugraph镜像 docker pull tugraph tugraph db centos7 启动docker docker run d p 7070 7070 p 9090 9090 name tugraph demo tugra
  • Oracle Sequence Cache 参数说明

    之前整理的一篇文章 ORACLE SEQUENCE 介绍 http blog csdn net tianlesoftware archive 2009 10 30 4745039 aspx 之前整理的一篇文章 那是还是写blog初期的作品
  • nacos 的 cp 和 ap

    如果只有一个 nacos 节点 可以直接以单机模式启动 naming 功能是完全正常的 也可以以集群模式启动 配置文件中只配一个节点即可 但是 因为此时 nacos 的 raft 实现中 一个节点是选不了主的 所以 cp 模式的 raft
  • matlab绘制贝叶斯曲线,Matlab建立SVM,KNN和朴素贝叶斯模型分类绘制ROC曲线

    原文链接 http tecdat cn p 15508 绘制ROC曲线通过Logistic回归进行分类 加载样本数据 load fisheriris通过使用与versicolor和virginica物种相对应的度量来定义二元分类问题 pre
  • java 布尔类型_Java布尔类型

    Java布尔类型 在Java语言中布尔类型的值只包括true和false 没有其他值 不包括1和0 布尔类型的数据在开发中主要使用在逻辑判断方面 例如 如果外面在下雨 我出门带一把雨伞 如果明天休息 咱们就一起出去玩耍吧 请看一段程序 以下
  • 文件包含漏洞及绕过方法(以php为例)

    一 文件包含漏洞的由来 简单的来说 为了减少 重复造轮子 引入了文件包含函数 可以直接使用文件中的文件和代码 当通过动态获文件时 或者需要引用网络上其他文件时 用户通过对变量值的修改访问规定的文件 但是未对变量值进行校验 导致有了可乘之机
  • 前端vue面试

    用户登陆产品了解生命周期vuex数据平台干嘛vue X怎么持久localstore和cokIE区别路由传惨路由传惨两种方式区别 1 谈一谈你对keep alive的了解P1 2 三 v if v show的区别 3 四 v if和v for
  • 服务器柜机位置摆放电子图,客厅柜机摆放—客厅柜机空调摆放方法介绍

    客厅是一家人在一起活动最多的房间 所以家具及家电等产品的摆放就要有一定的讲究了 其中柜机空调的摆放方法尤其为消费者所关注 下面 小编就详细的向您介绍一下客厅柜机摆放的方法 有兴趣的朋友一起来了解一下吧 客厅柜机摆放 客厅柜机摆放 正确摆放位
  • VectorCAST软件下载安装使用试用培训购买

    商业软件如需下载安装使用试用 可以通过下面添加 提供编译器定制 技术支持 培训 wanglequshuijiao 有需要可以加详细聊 vx 静态测试软件 QAC Klocwork Coverity等 单元测试软件 集成测试软件 Vector
  • 超详细!Jmeter性能测试(二)

    Jmeter 性能测试 二 关联 正则表达式提取器和JSON Extractor提取器 接入上篇博文继续 上篇地址 https blog csdn net weixin 44954642 article details 103054387
  • MySQL几种创建索引的方式

    一 创建表时创建索引 key 索引名 column 二 表创建好后创建索引 1 通过Alter创建索引 PRIMARY KEY 主键索引 mysql gt ALTER TABLE table name ADD PRIMARY KEY col
  • 设计模式七大原则

    1 设计模式的目的 编写软件过程中 程序员面临着来自耦合性 内聚性以及可维护性 可扩展性 重用性 灵活性 等多方面的挑战 设计模式是为了让程序 软件 具有更好 1 代码重用性 即 相同功能的代码 不用多次编写 2 可读性 即 编程规范性 便
  • npm插件安装插件失败问题解决办法

    目录 问题索引列表 错误记录 在线地址pdf转word https www camscanner com pdftopic 问题索引列表 1 配置安装自定义位置nodejs 1 1 使用npm安装模块的位置有默认安装位置和指定安装位置 在W
  • Java自学第15天 面向对象(全)

    面向过程 面向对象 面向过程思想 步骤清晰简单 第一步做什么 第二步做什么 面对过程适合处理一些较为简单的问题 面向对象思想 物以类聚 分类的思维模式 思考问题首先会解决问题需要哪些分类 然后对这些分类进行单独思考 最后 才对某个分类下的细
  • javaSE进阶1之static用法

    JavaSE进阶 静态关键字 static static关键字的作用 成员变量分类 静态成员变量 实例成员变量 static修饰成员变量内存原理 static 修饰成员方法的基本用法 成员方法的分类 static修饰成员方法内存原理 sta
  • [原]Pro*C介绍-内嵌SQL

    Translate by Z Jingwei Document address http www db stanford edu ullman fcdb oracle or proc html Pro C介绍内嵌SQL 概要 Pro C语法