GVKun编程网logo

在具有循环引用的SQL中插入TABLES(存在循环引用)

17

如果您对在具有循环引用的SQL中插入TABLES和存在循环引用感兴趣,那么这篇文章一定是您不可错过的。我们将详细讲解在具有循环引用的SQL中插入TABLES的各种细节,并对存在循环引用进行深入的分析,

如果您对在具有循环引用的SQL中插入TABLES存在循环引用感兴趣,那么这篇文章一定是您不可错过的。我们将详细讲解在具有循环引用的SQL中插入TABLES的各种细节,并对存在循环引用进行深入的分析,此外还有关于android – 使用带有循环引用的Parcelable、ARC下使用MJRefresh时需要注意tableView循环引用、block循环引用的问题:、bootstrap table处理含有子集json的数据以及fastjson禁止循环引用的问题的实用技巧。

本文目录一览:

在具有循环引用的SQL中插入TABLES(存在循环引用)

在具有循环引用的SQL中插入TABLES(存在循环引用)

我有2张表:

Empleados(**numEmpl**, nombre, apellido, sexo, telefono, salario, numDept)Departamentos(**numDept**, nombreDept, numDirect)

在部门中:

  1. numEmpl是主键
  2. numDept是对Departamentos(numDept)的外键引用。在部门中:
  3. numDept是主键
  4. numDirect是对Empleados(numEmpl)的外键引用

因此,有一个循环参考。

首先,我创建了表格:

CREATE TABLE EMPLEADOS(numEmpl primary key, nombre,      apellido, sexo, telefono, salario, numDept)CREATE TABLE DEPARTAMENTOS(numDept primary key, nombreDept, numDirect)(i didn''t write here each of type is each colum)

现在,我在它们之间创建引用:

ALTER TABLE DEPARTAMENTOS     ADD CONSTRAINT FK_DEPT_EMP FOREIGN KEY (numDirect)     REFERENCES EMPLEADOS(numEmpl)ALTER TABLE EMPLEADOS     ADD CONSTRAINT FK_EMP_DEPT FOREIGN KEY (numDept)     REFERENCES DEPARTAMENTOS(numDept).

它起作用了,所以现在我尝试插入一些数据:

INSERT INTO Empleados(numEmpl, nombre, apellidos, sexo, telefono, salario, numDept)VALUES (1, ''Pepito'', ''P茅rez'', ''H'', ''111111111'', 20000, 1);INSERT INTO Departamentos(numDept, nombreDept, numDirect)VALUES (1, ''Direccion'', 1);

但是现在它引发了一个错误,告诉我不能在循环引用中引入数据,我试图禁用循环引用并插入数据,然后再次启用它,它起作用了,但是有人告诉我这不是正确的方法,在创建表以这种方式插入数据时我必须做一些特殊的事情,它会起作用,但是我不知道该怎么做。我正在使用oracle
sql developer。

编辑:感谢您的答案,但他们没有用。首先,我只能拥有该表,当我执行插入操作时,它必须以这种方式工作,而无需将参数设置为null并随后对其进行更新,很抱歉,我之前没有说过。因此,我要做的唯一方法就是允许圆参考,但是当我尝试以某人在这里所说的方式来做时,它告诉我一些有关回滚的信息,有人可以提供帮助吗?

答案1

小编典典

要允许循环引用,您需要可延迟的约束:

ALTER TABLE DEPARTAMENTOS     ADD CONSTRAINT FK_DEPT_EMP FOREIGN KEY (numDirect)     REFERENCES EMPLEADOS(numEmpl)    DEFERRABLE INITIALLY DEFERRED    ;ALTER TABLE EMPLEADOS     ADD CONSTRAINT FK_EMP_DEPT FOREIGN KEY (numDept)     REFERENCES DEPARTAMENTOS(numDept)    DEFERRABLE INITIALLY DEFERRED    ;

事务结束时 检查可延展性约束;在提交时间之前,允许存在虚假的 无效数据库状态
(在原始问题中:两个插入语句之间)。但是语句必须在事务内部,因此语句应包含在BEGIN [WORK];和中COMMIT [WORK];

android – 使用带有循环引用的Parcelable

android – 使用带有循环引用的Parcelable

Parcelable似乎没有优雅地处理像Serializable那样的循环引用.在下面的示例中,Bar的序列化工作正常,但将其写入Parcel会导致堆栈溢出:
I/TestRunner( 1571): java.lang.StackOverflowError
I/TestRunner( 1571):    at android.os.Parcel.writeParcelable(Parcel.java:1106)
I/TestRunner( 1571):    at android.os.Parcel.writeValue(Parcel.java:1029)
I/TestRunner( 1571):    at com.XXX.util.ParcelableTest$Bar.writetoParcel(ParcelableTest.java:209)
I/TestRunner( 1571):    at android.os.Parcel.writeParcelable(Parcel.java:1106)
I/TestRunner( 1571):    at android.os.Parcel.writeValue(Parcel.java:1029)
I/TestRunner( 1571):    at com.XXX.util.ParcelableTest$Baz.writetoParcel(ParcelableTest.java:246)
I/TestRunner( 1571):    at android.os.Parcel.writeParcelable(Parcel.java:1106)
I/TestRunner( 1571):    at android.os.Parcel.writeValue(Parcel.java:1029)
I/TestRunner( 1571):    at com.XXX.util.ParcelableTest$Bar.writetoParcel(ParcelableTest.java:209)
I/TestRunner( 1571):    at android.os.Parcel.writeParcelable(Parcel.java:1106)
I/TestRunner( 1571):    at android.os.Parcel.writeValue(Parcel.java:1029)


public void testCircular() throws Exception {

    final Bar bar = new Bar();
    final Baz baz = new Baz(bar);
    bar.baz = baz;

    // First,serialize
    final ByteArrayOutputStream bytes = new ByteArrayOutputStream();
    new ObjectOutputStream(bytes).writeObject(bar);
    final ByteArrayInputStream bytesIn = new ByteArrayInputStream(bytes.toByteArray());
    final Bar bar2 = (Bar) new ObjectInputStream(bytesIn).readobject();

    assertNotNull(bar2);
    assertNotNull(bar2.baz);
    assertEquals( bar2,bar2.baz.bar );


    // Now try same thing using parcelable
    final Parcel p = Parcel.obtain();
    p.writeValue(bar); // FAIL!  StackOverflowError
    p.setDataPosition(0);
    final Bar bar3 = (Bar) p.readValue(Bar.class.getClassLoader());

    assertNotNull(bar3);
    assertNotNull(bar3.baz);
    assertEquals( bar3,bar3.baz.bar );

}


protected static class Bar implements Parcelable,Serializable {
    private static final long serialVersionUID = 1L;
    public static final Parcelable.Creator<Bar> CREATOR = new Parcelable.Creator<Bar>() {
        public Bar createFromParcel(Parcel source) {
            final Bar f = new Bar();
            f.baz = (Baz) source.readValue(Bar.class.getClassLoader());
            return f;
        }

        public Bar[] newArray(int size) {
            throw new UnsupportedOperationException();
        }

    };


    public Baz baz;

    public Bar() {
    }

    public Bar( Baz baz ) {
        this.baz = baz;
    }

    public int describeContents() {
        return 0;
    }

    public void writetoParcel(Parcel dest,int ignored) {
        dest.writeValue(baz);
    }


}


protected static class Baz implements Parcelable,Serializable {
    private static final long serialVersionUID = 1L;
    public static final Parcelable.Creator<Baz> CREATOR = new Parcelable.Creator<Baz>() {
        public Baz createFromParcel(Parcel source) {
            final Baz f = new Baz();
            f.bar = (Bar) source.readValue(Baz.class.getClassLoader());
            return f;
        }

        public Baz[] newArray(int size) {
            throw new UnsupportedOperationException();
        }

    };


    public Bar bar;

    public Baz() {
    }

    public Baz( Bar bar ) {
        this.bar = bar;
    }

    public int describeContents() {
        return 0;
    }

    public void writetoParcel(Parcel dest,int ignored) {
        dest.writeValue(bar);
    }


}

我正在尝试将一些代码从使用Serializable转换为使用循环引用的Parcelable.使用Parcelable处理此问题是否有一个好的策略?

解决方法

也许答案在于一组更智能的writetoParcel和createFromParcel方法?

在我的脑海中,您可以保留已经完全写入给定Parcel的对象列表,并仅通过标记(可能是其本地identityHashCode())来标识它们. (请注意,这不是一个全局列表,它是明确的per-Parcel;也许它本身是通过半全局Map< Parcel,Set< Integer>>存储的?你需要确保一旦包裹遗忘了这个集合完全写了.)

writetoParcel()的相关位看起来像这样:

HashSet<Integer> set = getWrittenSetFor(dest);
final int tag = identityHashCode();
if (set.contains(tag)) {
    // Already sent
    dest.writeInt(tag);
} else {
    set.put(tag);
    dest.writeInt(tag);
    dest.writeValue(this);
}

相应的createFromParcel()会稍微复杂一些.

我希望这种方法存在潜在的问题,但这是我开始的地方.正如我在这里所说的,它依赖于identityHashCode()保证对于不同的对象是不同的 – 它通常在32位JVM上(作为底层C指针的值).普通的hashCode()可能是值得的(可能添加了输入信息?),或者某种序列号.

另一个选择可能是将对象简单地序列化为byte []并将其写入Parcel,但它让我觉得有点低效……

ARC下使用MJRefresh时需要注意tableView循环引用

ARC下使用MJRefresh时需要注意tableView循环引用

直接上代码,这是一个懒加载,相信大多数朋友已经发现在使用MJRefresh时出现了内存管理的错误

#pragma mark======创建主界面
- (UITableView  *)tableView
{
    if (!_tableView) {
        
        _tableView = [[UITableView alloc]initWithFrame:CGRectMake(0, 108, WIDTH, HEIGHT-108-44) style:UITableViewStylePlain];
        _tableView.backgroundColor = [UIColor colorWithRed:220/255.0 green:222/255.0 blue:222/255.0 alpha:1];
        _tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
        _tableView.dataSource = self;
        _tableView.delegate = self;
        [_tableView registerNib:[UINib nibWithNibName:@"OldGoodsCell" bundle:nil] forCellReuseIdentifier:@"cell"];
        _tableView.mj_header = [MJRefreshNormalHeader headerWithRefreshingTarget:self refreshingAction:@selector(refersh)];
        _tableView.mj_footer = [MJRefreshAutoNormalFooter footerWithRefreshingBlock:^{
#pragma mark======加载更多数据
            NSLog(@"加载更多数据");
            
            [_tableView.mj_footer endRefreshing];
        }];

    }
    return _tableView;
}

上述代码中,造成循环引用的地方依然是最基本的block,即

_tableView.mj_footer = [MJRefreshAutoNormalFooter footerWithRefreshingBlock:^{
#pragma mark======加载更多数据
            NSLog(@"加载更多数据");
            
            [_tableView.mj_footer endRefreshing];
        }];

_tableView的mj_footer内部是这样的,self就是_tableView;

- (void)setMj_footer:(MJRefreshFooter *)mj_footer
{
    if (mj_footer != self.mj_footer) {
        // 删除旧的,添加新的
        [self.mj_footer removeFromSuperview];
        [self addSubview:mj_footer];
        
        // 存储新的
        [self willChangeValueForKey:@"mj_footer"]; // KVO
        objc_setAssociatedObject(self, &MJRefreshFooterKey,
                                 mj_footer, OBJC_ASSOCIATION_ASSIGN);
        [self didChangeValueForKey:@"mj_footer"]; // KVO
    }
}

但是,我们在block里是这样写的

[MJRefreshAutoNormalFooter footerWithRefreshingBlock:^{
            [_tableView.mj_footer endRefreshing];
        }]

很明显,造成了_tableView 的 循环引用,紧接着由于我们的_tableView 是 strong 类型的,它的循环引用带来的结果就是所属的viewController对象无法释放,继而造成dealloc无法执行。我们要打破这种情况,只要打破_tableView的循环引用就成功了。

所以我们要把viewController的self变成弱类型的weakSelf  ,(不会变的请看这个__weak __typeof(&*self)weakSelf = self;会的请忽略) 即整行代码变成 [weakSelf.tableView.mj_footer endRefreshing];

这样一来,即使在给mj_footer的block里出现了 

[weakSelf.tableView.mj_footer endRefreshing]; weakSelf都是弱类型的了,里面的tableView也会随之释放,tableView的循环引用也就解决,循环引用的解决,dealloc方法也就恢复正常

block循环引用的问题:

block循环引用的问题:

在ARC模式下
执行下面语句:

1. - (IBAction)onTest:(id)sender  
2. {  
3.     BlockDemo *demo = [[BlockDemo alloc]init];  
4.     [demo setExecuteFinished:^{  
5.         if (demo.resultCode == 200) {  
6.             NSLog(@"call back ok.");  
7.         }  
8.     }];  
9.       
10.     [demo executeTest];  
11.        
12. }  

执行输出结果:

1. 2015-07-24 19:20:33.997 blockDemo[25215:60b] Object Constructor!  
2. 2015-07-24 19:20:39.000 blockDemo[25215:60b] call back ok.  
同样会被引入循环。

相信看到这里的人,大多都要喷了,这哪个不知道呀,还知道怎么解决呢,非ARC中加了个__block,当然的在ARC中加一个__weak就搞定了。嗯,确实是这样,但别急,接着往下看,绝对有收获。在这里先自己默认想一下,你是如何加这个__weak的。


对于第一个问是点block 的循环引用(retain cycle)到这里暂告结束。下面讲第二点。因为block告警在非ARC 中暂未发现因写法引入(如果你知道,麻烦告诉我怎么弄产生告警,我好研究一下。)
下面讲在ARC模式下去除因写法产生的告警时需要注意的问题。
像上面的写法其实在ARC中会产生(Capturing ''demo'' strongly in this block is likely to lead to a retain cycle)告警。如下图:


在ARC中,编译器智能化了,直接提示这样写会产生循环引用。因此很多爱去除告警的朋友就会想法去掉,好,咱再来看去掉时需注意的问题。
情况一:

1. - (IBAction)onTest:(id)sender  
2. {  
3.     __weak BlockDemo *demo = [[BlockDemo alloc]init];  
4.     [demo setExecuteFinished:^{  
5.         if (demo.resultCode == 200) {  
6.             NSLog(@"call back ok.");  
7.         }  
8.     }];  
9.     [demo executeTest];  
10. }  
直接在前面加一个__weak,但这样真的没有告警了吗?如果有,哪么恭喜欢你,说明编译器还帮你大忙。见下图





这时还会告警,说这是一个WEAK变量,就马上会被release。因此就不会执行block中的内容。大家可以运行一下看
输出结果为:
1. 2014-07-24 19:38:02.453 blockDemo[25305:60b] Object Constructor!  
2. 2014-07-24 19:38:02.454 blockDemo[25305:60b] Object Destoryed!  
很显然,马上被release了,所以block 中的代码根本就不执行。

谢天谢地,幸好编译器提前告诉了我们有这个隐性危险。相信大家为解决告警,又会得到一个比较圆满的解决方案,见下:
1. - (IBAction)onTest:(id)sender  
2. {  
3.     BlockDemo *demo = [[BlockDemo alloc]init];  
4.       
5.     __weak typeof(BlockDemo) *weakDemo = demo;  
6.       
7.     [demo setExecuteFinished:^{  
8.         if (weakDemo.resultCode == 200) {  
9.             NSLog(@"call back ok.");  
10.         }  
11.     }];  
12.     [demo executeTest];  
13. }  

这样写,即去除了告警又保证了block的运行。这才是我们最终想要的结果。
输出为:

1. 2014-07-24 19:40:33.204 blockDemo[25328:60b] Object Constructor!  
2. 2014-07-24 19:40:38.206 blockDemo[25328:60b] call back ok.  
3. 2014-07-24 19:40:38.207 blockDemo[25328:60b] Object Destoryed!  

但大家别得意。有提示,相信大家都能处理,并得到个好的解决方法。哪么下面大来再来看一下这个写法,让你真心甘拜下风。。。。。

1. - (IBAction)onTest:(id)sender  
2. {  
3.     __weak BlockDemo *demo = [BlockDemo blockdemo]; //这里才是重点,前面是[[BlockDemo alloc]init];会有告警。  
4.       
5.     [demo setExecuteFinished:^{  
6.         if (demo.resultCode == 200) {  
7.             NSLog(@"call back ok.");  
8.         }  
9.     }];  
10.     [demo executeTest];  
11. }  


其实只是把init放到了类方法中进行书写而已,但会有什么不同。

1. + (BlockDemo *)blockdemo  
2. {  
3.     return OBJC_AUTORELEASE([[BlockDemo alloc]init]);  
4. }  
不同点见下图:真心看不到作何告警,是不是。但这存在什么风险,风险就是运行的时候,block根本就没有run。因为对象早就释放了。


直接输出:

1. 2015-07-24 19:47:53.033 blockDemo[25395:60b] Object Constructor!  
2. 2015-07-24 19:47:53.035 blockDemo[25395:60b] Object Destoryed!  

因 此,写这个主要用来告戒一些喜欢用BLOCK但又想当然的朋友,有一些朋友喜欢去除告警,但只是盲目的加上__weak 或__block关键语,往往可能存在一些重大的安全隐患。就像演示中block根本不走。如果到了发布时,为了去告警而这样简单的处理了,并没有进行测 试就打包。哪么将死得很惨。。。。。


好,到了尾声,来说说为什么朋友问我block会不会引行死循环,我说不会的理由。
见码:

1. - (IBAction)onTest:(id)sender  
2. {  
3.     BlockDemo *demo = [BlockDemo blockdemo];//[[BlockDemo alloc]init];  
4.       
5.     [demo setExecuteFinishedParam:^(BlockDemo * ademo) {  
6.         if (ademo.resultCode == 200) {  
7.             NSLog(@"call back ok.");  
8.         }  
9.     }];  
10.       
11.     [demo executeTest];  
12. }  

不管是在外面init,还是在里面,且没有加__block 及__weak。为什么,因为我个人常常在使用自己写的block时,如果是回调,比较喜欢把自身当作参数传到block中。这样期实是编译器给我们做了弱引用。因此不会产生循环引用。

由 于我一直都这样写block,所以朋友一问起,我就说不会循环引用了,因为压根他碰到的就是前面讲述的哪种访问方式,而我回答的是我的这种使用方式。正因 为口头描述,与实际回复真是差之千里。。。哈哈。为了验证我朋友的这个,我特意写了个这篇文章,希望对大家有所帮助。最后,谢谢大家花时间阅读。


bootstrap table处理含有子集json的数据以及fastjson禁止循环引用的问题

bootstrap table处理含有子集json的数据以及fastjson禁止循环引用的问题

总结

以上是小编为你收集整理的bootstrap table处理含有子集json的数据以及fastjson禁止循环引用的问题全部内容。

如果觉得小编网站内容还不错,欢迎将小编网站推荐给好友。

今天关于在具有循环引用的SQL中插入TABLES存在循环引用的分享就到这里,希望大家有所收获,若想了解更多关于android – 使用带有循环引用的Parcelable、ARC下使用MJRefresh时需要注意tableView循环引用、block循环引用的问题:、bootstrap table处理含有子集json的数据以及fastjson禁止循环引用的问题等相关知识,可以在本站进行查询。

本文标签: