jpa和hibernate_JPA和Hibernate级联类型的初学者指南

jpa和hibernate

介绍

JPA将实体状态转换转换为数据库DML语句。 由于对实体图进行操作很常见,因此JPA允许我们将实体状态更改从父级传播到子级

通过CascadeType映射配置此行为。

JPA与Hibernate级联类型

Hibernate支持所有JPA级联类型和一些其他旧式级联样式。 下表绘制了JPA级联类型与其等效的Hibernate本机API之间的关联:

JPA EntityManager操作 JPA CascadeType Hibernate本机会话操作 Hibernate原生CascadeType 事件监听器
分离(实体) 分离 逐出(实体) 分离或

EVICT
默认驱逐事件侦听器
合并(实体) 合并 合并(实体) 合并 默认合并事件监听器
坚持(实体) 坚持 坚持(实体) 坚持 默认的持久事件监听器
刷新(实体) 刷新 刷新(实体) 刷新 默认刷新事件监听器
删除(实体) 去掉 删除(实体) 删除或删除 默认删除事件监听器
saveOrUpdate(实体) SAVE_UPDATE 默认的保存或更新事件监听器
复制(实体,复制模式) 复制 默认复制事件监听器
锁(实体,lockModeType) buildLockRequest(实体,lockOptions) 默认锁定事件监听器
以上所有EntityManager方法 所有 以上所有的Hibernate Session方法 所有

从该表可以得出以下结论:

  • 在JPA EntityManager或Hibernate Session上调用persistmergerefresh没有什么区别。
  • JPA的removedetach调用被委托给Hibernate Delete逐出本机操作。
  • 只有Hibernate支持复制saveOrUpdate 。 尽管复制对于某些非常特定的情况很有用(当确切的实体状态需要在两个不同的数据源之间进行镜像时),但持久 合并合并始终是比本机saveOrUpdate操作更好的替代方法。将持久对象用于TRANSIENT实体,并为已分离实体进行合并。saveOrUpdate的缺点(将分离的实体快照传递给已经管理该实体的会话时 )导致了合并操作的前身:现已不存在的saveOrUpdateCopy操作。
  • JPA锁定方法与Hibernate锁定请求方法具有相同的行为。
  • JPA CascadeType.ALL不仅适用于EntityManager状态更改操作,而且还适用于所有Hibernate CascadeTypes 。因此,如果将关联与CascadeType.ALL映射,您仍然可以级联Hibernate特定事件。 例如,即使JPA没有定义LOCK CascadeType ,您也可以级联JPA锁定操作(尽管它的行为就像是重新附加,而不是实际的锁定请求传播)。

级联最佳做法

级联仅对父级 - 子级关联有意义( 父级实体状态转换级联到其子级实体)。 从孩子级联到父级不是很有用,通常,这是映射代码的味道。

接下来,我将采取分析所有JPA 家长的级联行为- 关联。

一对一

最常见的一对一双向关联如下所示:

@Entity
public class Post {@Id@GeneratedValue(strategy = GenerationType.AUTO)private Long id;private String name;@OneToOne(mappedBy = "post",cascade = CascadeType.ALL, orphanRemoval = true)private PostDetails details;public Long getId() {return id;}public PostDetails getDetails() {return details;}public String getName() {return name;}public void setName(String name) {this.name = name;}public void addDetails(PostDetails details) {this.details = details;details.setPost(this);}public void removeDetails() {if (details != null) {details.setPost(null);}this.details = null;}
}@Entity
public class PostDetails {@Id@GeneratedValue(strategy = GenerationType.AUTO)private Long id;@Column(name = "created_on")@Temporal(TemporalType.TIMESTAMP)private Date createdOn = new Date();private boolean visible;@OneToOne@PrimaryKeyJoinColumnprivate Post post;public Long getId() {return id;}public void setVisible(boolean visible) {this.visible = visible;}public void setPost(Post post) {this.post = post;}
}

Post实体扮演Parent角色,而PostDetailsChild

双向关联应始终在两侧进行更新,因此父级侧应包含addChildremoveChild组合。 这些方法确保我们始终同步关联的双方,以避免对象或关系数据损坏问题。

在这种特殊情况下, CascadeType.ALL和孤立删除是有意义的,因为PostDetails生命周期绑定到其Post Parent实体的生命周期。

进行一对一的持久化操作

CascadeType.PERSISTCascadeType.ALL配置一起提供,因此我们仅需持久化Post实体,并且关联的PostDetails实体也将持久化:

Post post = new Post();
post.setName("Hibernate Master Class");PostDetails details = new PostDetails();post.addDetails(details);session.persist(post);

生成以下输出:

INSERT INTO post(id, NAME) 
VALUES (DEFAULT, Hibernate Master Class'')insert into PostDetails (id, created_on, visible) 
values (default, '2015-03-03 10:17:19.14', false)

级联一对一合并操作

CascadeType.MERGE继承自CascadeType.ALL设置,因此我们只需要合并Post实体,并且关联的PostDetails也将合并:

Post post = newPost();
post.setName("Hibernate Master Class Training Material");
post.getDetails().setVisible(true);doInTransaction(session -> {session.merge(post);
});

合并操作生成以下输出:

SELECT onetooneca0_.id     AS id1_3_1_,onetooneca0_.NAME       AS name2_3_1_,onetooneca1_.id         AS id1_4_0_,onetooneca1_.created_on AS created_2_4_0_,onetooneca1_.visible    AS visible3_4_0_
FROM   post onetooneca0_
LEFT OUTER JOIN postdetails onetooneca1_ ON onetooneca0_.id = onetooneca1_.id
WHERE  onetooneca0_.id = 1UPDATE postdetails SET created_on = '2015-03-03 10:20:53.874', visible = true 
WHERE  id = 1UPDATE post SET NAME = 'Hibernate Master Class Training Material' 
WHERE  id = 1

级联一对一删除操作

CascadeType.REMOVE也继承自CascadeType.ALL配置,因此Post实体的删除也会触发PostDetails实体的删除:

Post post = newPost();doInTransaction(session -> {session.delete(post);
});

生成以下输出:

delete from PostDetails where id = 1
delete from Post where id = 1

一对一删除孤立级联操作

如果一个孩子实体从母公司分离,儿童外键设置为NULL。 如果我们也要删除“ 行”,则必须使用孤立删除支持。

doInTransaction(session -> {Post post = (Post) session.get(Post.class, 1L);post.removeDetails();
});

除去孤儿将生成以下输出:

SELECT onetooneca0_.id         AS id1_3_0_,onetooneca0_.NAME       AS name2_3_0_,onetooneca1_.id         AS id1_4_1_,onetooneca1_.created_on AS created_2_4_1_,onetooneca1_.visible    AS visible3_4_1_
FROM   post onetooneca0_
LEFT OUTER JOIN postdetails onetooneca1_ON onetooneca0_.id = onetooneca1_.id
WHERE  onetooneca0_.id = 1delete from PostDetails where id = 1

单向一对一关联

大多数情况下, 实体是反方(如的mappedBy), 儿童 controling通过它的外键关联。 但是级联不限于双向关联,我们还可以将其用于单向关系:

@Entity
public class Commit {@Id@GeneratedValue(strategy = GenerationType.AUTO)private Long id;private String comment;@OneToOne(cascade = CascadeType.ALL)@JoinTable(name = "Branch_Merge_Commit",joinColumns = @JoinColumn(name = "commit_id", referencedColumnName = "id"),inverseJoinColumns = @JoinColumn(name = "branch_merge_id", referencedColumnName = "id"))private BranchMerge branchMerge;public Commit() {}public Commit(String comment) {this.comment = comment;}public Long getId() {return id;}public void addBranchMerge(String fromBranch, String toBranch) {this.branchMerge = new BranchMerge(fromBranch, toBranch);}public void removeBranchMerge() {this.branchMerge = null;}
}@Entity
public class BranchMerge {@Id@GeneratedValue(strategy = GenerationType.AUTO)private Long id;private String fromBranch;private String toBranch;public BranchMerge() {}public BranchMerge(String fromBranch, String toBranch) {this.fromBranch = fromBranch;this.toBranch = toBranch;}public Long getId() {return id;}
}

层叠在于传播实体状态过渡到一个或多个儿童的实体,它可用于单向和双向关联。

一对多

最常见的 - 关联由一到多和多到一的关系,其中级联是只对一个一对多侧有用:

@Entity
public class Post {@Id@GeneratedValue(strategy = GenerationType.AUTO)private Long id;private String name;@OneToMany(cascade = CascadeType.ALL, mappedBy = "post", orphanRemoval = true)private List<Comment> comments = new ArrayList<>();public void setName(String name) {this.name = name;}public List<Comment> getComments() {return comments;}public void addComment(Comment comment) {comments.add(comment);comment.setPost(this);}public void removeComment(Comment comment) {comment.setPost(null);this.comments.remove(comment);}
}@Entity
public class Comment {@Id@GeneratedValue(strategy = GenerationType.AUTO)private Long id;@ManyToOneprivate Post post;private String review;public void setPost(Post post) {this.post = post;}public String getReview() {return review;}public void setReview(String review) {this.review = review;}
}

像一对一示例一样, CascadeType.ALL和孤立删除是合适的,因为Comment生命周期绑定到其Post Parent实体的生命周期。

级联一对多持久化操作

我们只需保留Post实体,所有相关的Comment实体也将保留:

Post post = new Post();
post.setName("Hibernate Master Class");Comment comment1 = new Comment();
comment1.setReview("Good post!");
Comment comment2 = new Comment();
comment2.setReview("Nice post!");post.addComment(comment1);
post.addComment(comment2);session.persist(post);

持久操作将生成以下输出:

insert into Post (id, name) 
values (default, 'Hibernate Master Class')insert into Comment (id, post_id, review) 
values (default, 1, 'Good post!')insert into Comment (id, post_id, review) 
values (default, 1, 'Nice post!')

级联一对多合并操作

合并Post实体也将合并所有Comment实体:

Post post = newPost();
post.setName("Hibernate Master Class Training Material");post.getComments().stream().filter(comment -> comment.getReview().toLowerCase().contains("nice")).findAny().ifPresent(comment -> comment.setReview("Keep up the good work!")
);doInTransaction(session -> {session.merge(post);
});

生成以下输出:

SELECT onetomanyc0_.id    AS id1_1_1_,onetomanyc0_.NAME  AS name2_1_1_,comments1_.post_id AS post_id3_1_3_,comments1_.id      AS id1_0_3_,comments1_.id      AS id1_0_0_,comments1_.post_id AS post_id3_0_0_,comments1_.review  AS review2_0_0_
FROM   post onetomanyc0_
LEFT OUTER JOIN comment comments1_ON onetomanyc0_.id = comments1_.post_id
WHERE  onetomanyc0_.id = 1update Post set name = 'Hibernate Master Class Training Material' 
where id = 1update Comment set post_id = 1, review='Keep up the good work!' 
where id = 2

级联一对多删除操作

删除Post实体后,关联的Comment实体也将被删除:

Post post = newPost();doInTransaction(session -> {session.delete(post);
});

生成以下输出:

delete from Comment where id = 1
delete from Comment where id = 2
delete from Post where id = 1

一对多删除孤立级联操作

移除孤儿使我们可以在其父级不再引用子级实体时将其删除:

newPost();doInTransaction(session -> {Post post = (Post) session.createQuery("select p " +"from Post p " +"join fetch p.comments " +"where p.id = :id").setParameter("id", 1L).uniqueResult();post.removeComment(post.getComments().get(0));
});

正如我们在以下输出中看到的,评论已删除:

SELECT onetomanyc0_.id    AS id1_1_0_,comments1_.id      AS id1_0_1_,onetomanyc0_.NAME  AS name2_1_0_,comments1_.post_id AS post_id3_0_1_,comments1_.review  AS review2_0_1_,comments1_.post_id AS post_id3_1_0__,comments1_.id      AS id1_0_0__
FROM   post onetomanyc0_
INNER JOIN comment comments1_ON onetomanyc0_.id = comments1_.post_id
WHERE  onetomanyc0_.id = 1delete from Comment where id = 1

多对多

多对多关系非常棘手,因为此关联的每一方都扮演“ 父母”和“ 孩子”角色。 尽管如此,我们仍可以从一侧传播我们想要传播实体状态变化的位置。

我们不应该默认使用CascadeType.ALL ,因为CascadeTpe.REMOVE最终可能会删除比我们期望的更多的东西(您很快就会发现):

@Entity
public class Author {@Id@GeneratedValue(strategy=GenerationType.AUTO)private Long id;@Column(name = "full_name", nullable = false)private String fullName;@ManyToMany(mappedBy = "authors", cascade = {CascadeType.PERSIST, CascadeType.MERGE})private List<Book> books = new ArrayList<>();private Author() {}public Author(String fullName) {this.fullName = fullName;}public Long getId() {return id;}public void addBook(Book book) {books.add(book);book.authors.add(this);}public void removeBook(Book book) {books.remove(book);book.authors.remove(this);}public void remove() {for(Book book : new ArrayList<>(books)) {removeBook(book);}}
}@Entity
public class Book {@Id@GeneratedValue(strategy=GenerationType.AUTO)private Long id;@Column(name = "title", nullable = false)private String title;@ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})@JoinTable(name = "Book_Author",joinColumns = {@JoinColumn(name = "book_id", referencedColumnName = "id")},inverseJoinColumns = {@JoinColumn(name = "author_id", referencedColumnName = "id")})private List<Author> authors = new ArrayList<>();private Book() {}public Book(String title) {this.title = title;}
}

级联多对多持久操作

坚持作者实体也将保留书籍

Author _John_Smith = new Author("John Smith");
Author _Michelle_Diangello = new Author("Michelle Diangello");
Author _Mark_Armstrong = new Author("Mark Armstrong");Book _Day_Dreaming = new Book("Day Dreaming");
Book _Day_Dreaming_2nd = new Book("Day Dreaming, Second Edition");_John_Smith.addBook(_Day_Dreaming);
_Michelle_Diangello.addBook(_Day_Dreaming);_John_Smith.addBook(_Day_Dreaming_2nd);
_Michelle_Diangello.addBook(_Day_Dreaming_2nd);
_Mark_Armstrong.addBook(_Day_Dreaming_2nd);session.persist(_John_Smith);
session.persist(_Michelle_Diangello);
session.persist(_Mark_Armstrong);

BookBook_Author行与Authors一起插入:

insert into Author (id, full_name) 
values (default, 'John Smith')insert into Book (id, title) 
values (default, 'Day Dreaming')insert into Author (id, full_name) 
values (default, 'Michelle Diangello')insert into Book (id, title) 
values (default, 'Day Dreaming, Second Edition')insert into Author (id, full_name) 
values (default, 'Mark Armstrong')insert into Book_Author (book_id, author_id) values (1, 1)
insert into Book_Author (book_id, author_id) values (1, 2)
insert into Book_Author (book_id, author_id) values (2, 1)
insert into Book_Author (book_id, author_id) values (2, 2)
insert into Book_Author (book_id, author_id) values (3, 1)

解除多对多关联的一侧

要删除Author ,我们需要取消关联属于可移动实体的所有Book_Author关系:

doInTransaction(session -> {Author _Mark_Armstrong =getByName(session, "Mark Armstrong");_Mark_Armstrong.remove();session.delete(_Mark_Armstrong);
});

该用例生成以下输出:

SELECT manytomany0_.id        AS id1_0_0_,manytomany2_.id        AS id1_1_1_,manytomany0_.full_name AS full_nam2_0_0_,manytomany2_.title     AS title2_1_1_,books1_.author_id      AS author_i2_0_0__,books1_.book_id        AS book_id1_2_0__
FROM   author manytomany0_
INNER JOIN book_author books1_ON manytomany0_.id = books1_.author_id
INNER JOIN book manytomany2_ON books1_.book_id = manytomany2_.id
WHERE  manytomany0_.full_name = 'Mark Armstrong'SELECT books0_.author_id  AS author_i2_0_0_,books0_.book_id    AS book_id1_2_0_,manytomany1_.id    AS id1_1_1_,manytomany1_.title AS title2_1_1_
FROM   book_author books0_
INNER JOIN book manytomany1_ON books0_.book_id = manytomany1_.id
WHERE  books0_.author_id = 2delete from Book_Author where book_id = 2insert into Book_Author (book_id, author_id) values (2, 1)
insert into Book_Author (book_id, author_id) values (2, 2)delete from Author where id = 3

多对多关联会生成太多冗余SQL语句,并且经常很难调整它们。 接下来,我将演示多对多CascadeType.REMOVE隐藏的危险。

多对多CascadeType.REMOVE陷阱

多对多CascadeType.ALL是另一个代码异味,我在查看代码时经常碰到。 所述CascadeType.REMOVE使用CascadeType.ALL时自动继承,但实体去除不仅应用到链接表,但对关联的另一侧为好。

让我们将Author实体书籍多对多关联更改为使用CascadeType.ALL代替:

@ManyToMany(mappedBy = "authors", cascade = CascadeType.ALL)
private List<Book> books = new ArrayList<>();

删除一位作者时

doInTransaction(session -> {Author _Mark_Armstrong = getByName(session, "Mark Armstrong");session.delete(_Mark_Armstrong);Author _John_Smith = getByName(session, "John Smith");assertEquals(1, _John_Smith.books.size());
});

属于已删除作者的所有图书都将被删除,即使我们仍与已删除图书相关联的其他作者也是如此:

SELECT manytomany0_.id        AS id1_0_,manytomany0_.full_name AS full_nam2_0_
FROM   author manytomany0_
WHERE  manytomany0_.full_name = 'Mark Armstrong'  SELECT books0_.author_id  AS author_i2_0_0_,books0_.book_id    AS book_id1_2_0_,manytomany1_.id    AS id1_1_1_,manytomany1_.title AS title2_1_1_
FROM   book_author books0_
INNER JOIN book manytomany1_ ON books0_.book_id = manytomany1_.id
WHERE  books0_.author_id = 3  delete from Book_Author where book_id=2
delete from Book where id=2
delete from Author where id=3

通常,此行为与业务逻辑期望不符,仅在首次删除实体时才发现。

如果我们也将CascadeType.ALL设置为Book实体,则可以进一步推动该问题:

@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "Book_Author",joinColumns = {@JoinColumn(name = "book_id", referencedColumnName = "id")},inverseJoinColumns = {@JoinColumn(name = "author_id", referencedColumnName = "id")}
)

这次,不仅书籍被删除,而且作者也被删除:

doInTransaction(session -> {Author _Mark_Armstrong = getByName(session, "Mark Armstrong");session.delete(_Mark_Armstrong);Author _John_Smith = getByName(session, "John Smith");assertNull(_John_Smith);
});

作者的删除触发所有相关书籍的删除,这进一步触发所有相关的作者的删除。 这是一个非常危险的操作,会导致大规模实体删除,这很少是预期的行为。

SELECT manytomany0_.id        AS id1_0_,manytomany0_.full_name AS full_nam2_0_
FROM   author manytomany0_
WHERE  manytomany0_.full_name = 'Mark Armstrong'  SELECT books0_.author_id  AS author_i2_0_0_,books0_.book_id    AS book_id1_2_0_,manytomany1_.id    AS id1_1_1_,manytomany1_.title AS title2_1_1_
FROM   book_author books0_
INNER JOIN book manytomany1_ON books0_.book_id = manytomany1_.id
WHERE  books0_.author_id = 3  SELECT authors0_.book_id      AS book_id1_1_0_,authors0_.author_id    AS author_i2_2_0_,manytomany1_.id        AS id1_0_1_,manytomany1_.full_name AS full_nam2_0_1_
FROM   book_author authors0_
INNER JOIN author manytomany1_ON authors0_.author_id = manytomany1_.id
WHERE  authors0_.book_id = 2  SELECT books0_.author_id  AS author_i2_0_0_,books0_.book_id    AS book_id1_2_0_,manytomany1_.id    AS id1_1_1_,manytomany1_.title AS title2_1_1_
FROM   book_author books0_
INNER JOIN book manytomany1_ON books0_.book_id = manytomany1_.id
WHERE  books0_.author_id = 1 SELECT authors0_.book_id      AS book_id1_1_0_,authors0_.author_id    AS author_i2_2_0_,manytomany1_.id        AS id1_0_1_,manytomany1_.full_name AS full_nam2_0_1_
FROM   book_author authors0_
INNER JOIN author manytomany1_ON authors0_.author_id = manytomany1_.id
WHERE  authors0_.book_id = 1  SELECT books0_.author_id  AS author_i2_0_0_,books0_.book_id    AS book_id1_2_0_,manytomany1_.id    AS id1_1_1_,manytomany1_.title AS title2_1_1_
FROM   book_author books0_
INNER JOIN book manytomany1_ON books0_.book_id = manytomany1_.id
WHERE  books0_.author_id = 2  delete from Book_Author where book_id=2
delete from Book_Author where book_id=1
delete from Author where id=2
delete from Book where id=1
delete from Author where id=1 
delete from Book where id=2
delete from Author where id=3

这种用例在很多方面都是错误的。 大量不必要的SELECT语句,最终我们最终删除了所有作者及其所有书籍。 这就是为什么当您在多对多关联中发现CascadeType.ALL时,它应该引起您的注意。

当涉及到Hibernate映射时,您应该始终追求简单性。 Hibernate文档也证实了这一假设:

真正的多对多关联的实际测试案例很少见。 大多数时候,您需要存储在“链接表”中的其他信息。 在这种情况下,最好将两个一对多关联用于中间链接类。 实际上,大多数关联是一对多和多对一的。 因此,在使用任何其他关联样式时,您应谨慎进行。

结论

级联是一种方便的ORM功能,但并非没有问题。 您应该仅从父级实体级联到子级,而不是相反。 您应该始终仅使用业务逻辑要求所要求的Casacde操作,而不应将CascadeType.ALL转换为默认的Parent-Child关联实体状态传播配置。

  • 代码可在GitHub上获得 。

翻译自: https://www.javacodegeeks.com/2015/03/a-beginners-guide-to-jpa-and-hibernate-cascade-types.html

jpa和hibernate

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/338191.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux find 权限不够,超级用户find: `/home/pipi/.gvfs': 权限不够

用sudo su命令切换成的根用户&#xff0c;在找某文件的时候报错&#xff1a;rootubuntu:/home/pipi# find / -perm -2000/sbin/unix_chkpwdfind: /home/pipi/.gvfs: 权限不够就是普通用户pipi的主目录下的一个叫 .gvfs 的目录&#xff0c;dr-x------ 2 pipi pipi 0 …

aws上部署hadoop_在AWS Elastic MapReduce上运行PageRank Hadoop作业

aws上部署hadoop在上一篇文章中&#xff0c;我描述了一个执行PageRank计算的示例&#xff0c;该示例是使用Apache Hadoop进行Mining Massive Dataset课程的一部分。 在那篇文章中&#xff0c;我接受了Java中现有的Hadoop作业&#xff0c;并做了一些修改&#xff08;添加了单元测…

linux编写一个简单的端口扫描程序,小弟我在linux下写了个简单的多线程端口扫描程序,运行时出现有关问题,请问一下(2)...

当前位置:我的异常网 Linux/Unix 小弟我在linux下写了个简单的多线程端口扫描程序&#xff0c;小弟我在linux下写了个简单的多线程端口扫描程序&#xff0c;运行时出现有关问题,请问一下(2)www.myexceptions.net 网友分享于&#xff1a;2013-02-26 浏览&#xff1a;23次usle…

在嵌套使用if语句时,C语言规定else总是什么?

C语言的语法规定&#xff1a;else子句总是与前面最近的不带else的if相结合&#xff0c;与书写格式无关。在C语言中&#xff0c;使用if和else关键字对条件进行判断。请先看下面的代码&#xff1a;#include int main(){ int age; printf("请输入你的年龄&#xff1a;&…

optional空值判断_Java 8 Optional不仅用于替换空值

optional空值判断总览 在Java 8中&#xff0c;您可以返回Optional而不是返回null。 就像您在Java 7中所做的那样。这可能会有所不同&#xff0c;这取决于您是否倾向于忘记检查null还是使用静态代码分析来检查nullalbe引用。 但是&#xff0c;还有一种更引人注目的情况是将Opti…

continue语句的作用是结束整个循环的执行吗?

continue 语句的作用是结束本次循环&#xff0c;跳过循环体中剩余的语句而强制进入下一次循环&#xff08;回到循环体的开头准备再次执行循环体&#xff09;。continue语句只用在 while、for 循环中&#xff0c;常与 if 条件语句一起使用&#xff0c;判断条件是否成立。使用方式…

linux 远程权限不够,Eclipse连接远程Hadoop集群开发时权限不足问题解决方案

eclipse连接远程Hadoop集群开发时报错Exception in thread "main" org.apache.hadoop.security.AccessControlException: Permission denied: userd, accessWRITE, inode"data":zxg:supergroup:rwxr-xr-xat org.apache.hadoop.hdfs.server.namenode.FSPerm…

jsp导入jstl标签库_EE JSP:使用JSTL标记库生成动态内容

jsp导入jstl标签库除了在JSP中编写自己的定制标记之外&#xff0c;您还将发现Java EE实际上提供了一组Java标准标记库&#xff08;JSTL&#xff09;供您使用。 这些内置标签包括重复&#xff08;for-loop&#xff09;标签&#xff0c;条件标签&#xff0c;变量声明和输出标签等…

一文掌握 C 智能指针的使用

RAII 与引用计数了解 objective-C/Swift 的程序员应该知道引用计数的概念。引用计数这种计数是为了防止内存泄露而产生的。基本想法是对于动态分配的对象&#xff0c;进行引用计数&#xff0c;每当增加一次对同一个对象的引用&#xff0c;那么引用对象的引用计数就会增加一次&a…

linux里面启用无线网卡,linux启用无线网卡上网

1、使用cat /proc/version查看linux内核版本号&#xff0c;我的系统是Linux version 2.6.32-220.el6.i6862、使用cat /etc/issue查看linux发行版本号&#xff0c;我的系统是Red Hat Enterprise Linux Server release 6.2 (Santiago)现在 进入正题&#xff0c;如何在redhat linu…

fwrite函数的一般调用形式是什么?

fwrite() 是C 语言标准库中的一个文件处理函数&#xff0c;功能是向指定的文件中写入若干数据块&#xff0c;如成功执行则返回实际写入的数据块数目。该函数以二进制形式对文件进行操作&#xff0c;不局限于文本文件。语法&#xff1a;fwrite(buffer,size,count,fp)参数&#x…

java 不同类型 映射_如何使用Java泛型映射不同的值类型

java 不同类型 映射有时&#xff0c;一般的开发人员会遇到这样的情况&#xff0c;即他必须在特定容器内映射任意类型的值。 但是&#xff0c;Java集合API仅提供与容器相关的参数化。 例如&#xff0c;这将HashMap的类型安全使用限制为单个值类型。 但是&#xff0c;如果您想混合…

linux vim自动换行,VIM 的自动换行及自动折行设置

VIM 的自动换行及自动折行设置以 .vimrc 文件中的设置为例&#xff1a;" 自动换行是每行超过 n 个字的时候 vim 自动加上换行符" 需要注意的是&#xff0c;如果一个段落的首个单词很长&#xff0c;超出了自动换行设置的字符&#xff0c;" 这种情况下不会换行。&…

lambdas 排序_Java8 Lambdas:解释性能缺陷的排序

lambdas 排序与Peter Lawrey合作撰写 。 几天前&#xff0c;我对使用新的Java8声明式的排序性能提出了一个严重的问题。 在这里查看博客文章。 在那篇文章中&#xff0c;我仅指出了问题&#xff0c;但在这篇文章中&#xff0c;我将更深入地了解和解释问题的原因。 这将通过使用…

strncmp函数用法是什么

strncmp函数用法&#xff1a;函数原型int strcmp(char *str1,char * str2&#xff0c;int n)功能比较字符串str1和str2的前n个字符。头文件#include 返回值返回值&#xff1a;返回整数值&#xff1a;当str1<str2时&#xff0c;返回值<0&#xff1b; str1"str2时&…

cepl进程 Linux,Ubuntu下NS2-2.33安装过程

首先安装下列软件包# sudo apt-get install build-essential# sudo apt-get install tcl8.4 tcl8.4-dev tk8.4 tk8.4-dev# sduo apt-get install libxmu-dev libxmu-headers再下载NS2软件&#xff0c;(http://jaist.dl.sourceforge.net/sourceforge/nsnam/ns-allinone-2.33.tar…

分享10个适合初学者学习的C开源项目代码

1.WebbenchWebbench 是一个在 linux 下使用的非常简单的网站压测工具。它使用 fork ()模拟多个客户端同时访问我们设定的 URL&#xff0c;测试网站在压力下工作的性能&#xff0c;最多可以模拟 3 万个并发连接去测试网站的负载能力。Webbench 使用C语言编写&#xff0c; 代码实…

tomcat与tomee_Apache TomEE(和Tomcat)的自签名证书

tomcat与tomee可能在大多数Java EE项目中&#xff0c;您将拥有具有SSL支持&#xff08; https &#xff09;的部分或整个系统&#xff0c;因此浏览器和服务器可以通过安全连接进行通信。 这意味着在处理数据之前&#xff0c;已发送的数据已加密&#xff0c;传输并最终解密。 …

linux环境变量管理器,运维 - linux(ubuntu) 环境变量管理 (持续更新)

运维 - linux(ubuntu) 环境变量管理 (持续更新)注: 本教程以 Ubuntu16.04 操作, 请细看. 如果看完还不明白, 联系我, 我给你发红包.一, 查看环境变量:方法 1: 直接用 $PATH 命令:wafaubuntu:~$ $PATHbash:/home/king/bin:/home/king/.local/bin:/usr/local/sbin:/usr/local/bin…

C 线程的使用~(上)

C 11 之前&#xff0c;C 语言没有对并发编程提供语言级别的支持&#xff0c;这使得我们在编写可移植的并发程序时&#xff0c;存在诸多的不便。现在 C 11 中增加了线程以及线程相关的类&#xff0c;很方便地支持了并发编程&#xff0c;使得编写的多线程程序的可移植性得到了很大…