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

介绍

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

通过CascadeType映射配置此行为。

JPA与Hibernate级联类型

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

JPA EntityManager操作 JPA CascadeType 休眠本机会话操作 休眠原生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的缺点(将分离的实体快照传递给已经管理该实体的Session时 )导致了合并操作的前身:现已不存在的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生命周期与其 实体的生命周期绑定在一起。

进行一对一的持久化操作

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

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

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

相关文章

EE JSP:使用JSTL标记库生成动态内容

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

Sublime text 2下alignment插件无效的解决办法

在sublime text 2中安装了alignment插件&#xff0c;但使用快捷键‘ctrlalta无效&#xff0c;经过各种方法依然无效&#xff0c;最后找到了这个“Doesnt work at all for me (full steps)”&#xff0c;方法就是用sb打开%sb 路径%\Data\Packages\Alignment目录下的alignment.py…

php入口函数,php 常用的系统函数

字符串函数strlen&#xff1a;获取字符串长度&#xff0c;字节长度substr&#xff1a;字符串截取&#xff0c;获取字符串(按照字节进行截取)strchr&#xff1a;与substr相似&#xff0c;从指定位置截取一直到最后strrchr(获取文件后缀名)&#xff1a;与strchr一样&#xff0c;只…

startActivityForResult的使用和用法

startActivityForResult的使用和用法 startActivityForResult 和 onActivityResult在activity间传递数据AndroidManifest.xml<applicationandroid:icon"drawable/ic_launcher"android:label"string/app_name" ><activityandroid:name".KakuL…

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

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

php用正则去掉一些固定字符,用PHP正则表达式清除字符串的空白

我们经常会处理来自用户输入或从数据库中读取的数据&#xff0c;可能在你的字符串中有多余的空白或制表符&#xff0c;回车等。存储这些额外的字符是有点浪费空间的。如果您想要去掉字符串开始和结束的空白可以使用PHP内部函数trim() 。但是, 我们经常想完全清除空白。需要把开…

Windows上编译libpng

Windows上编译libpng 下载libpng 1.5.10并解压到[工作目录]/png/libpng-1.5.10 用CMake选择png/libpng-1.5.10目录并Configure&#xff1a; CMAKE_C_FLAGS_DEBUG/D_DEBUG /MTd /Zi /Ob0 /Od /RTC1 CMAKE_C_FLAGS_RELEASE/MT /O2 /Ob2 /D NDEBUG CMAKE_INSTALL_PREFIX[工作目录…

在Graphite中存储Hystrix的几个月历史指标

Hystrix的杀手级功能之一是低延迟&#xff0c;数据密集型且美观的仪表板 &#xff1a; 即使这只是Hystrix实际操作的副作用&#xff08;断路器&#xff0c;线程池&#xff0c;超时等&#xff09;&#xff0c;它也往往是最令人印象深刻的功能。 为了使其工作&#xff0c;您必须…

html和php文件怎么连接,html页面跟php文件连接的方法

html页面跟php文件连接的方法发布时间&#xff1a;2020-09-25 11:11:05来源&#xff1a;亿速云阅读&#xff1a;115作者&#xff1a;小新小编给大家分享一下html页面跟php文件连接的方法&#xff0c;相信大部分人都还不怎么了解&#xff0c;因此分享这篇文章给大家参考一下&…

java定义一个course类,求指教定义一个学生类 ,大学生小学生,定义一个选课接口...

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼interface XC{abstract String CourseName();abstract String CourseID();}abstract class Student{protected String Name;protected String Ban;protected String Sex;public Student(){}public Student(String Name,String Ban,…

NYOJ-----最少乘法次数

最少乘法次数 时间限制&#xff1a;1000 ms | 内存限制&#xff1a;65535 KB难度&#xff1a;3描述给你一个非零整数&#xff0c;让你求这个数的n次方&#xff0c;每次相乘的结果可以在后面使用&#xff0c;求至少需要多少次乘。如24&#xff1a;2*222&#xff08;第一次乘&a…

在Java 7或更早版本中使用Java 8 Lambda表达式

我认为没有人会拒绝Java 8引入的Lambda表达式的有用性。但是&#xff0c;许多项目都停留在Java 7甚至旧版本上。 升级可能既耗时又昂贵。 如果第三方组件与Java 8不兼容&#xff0c;则可能根本无法升级。 除此之外&#xff0c;整个Android平台都停留在Java 6和7上。 尽管如此…

php获得昨天零时的时间戳,php 获取时间今天明天昨天时间戳

echo "今天:".date("Y-m-d")."";echo "昨天:".date("Y-m-d",strtotime("-1 day")), "";echo "明天:".date("Y-m-d",strtotime("1 day")). "";echo "一周…

Zend Debugger 配置

到官网 http://www.zend.com/en/products/studio/downloads 下载 windows 版 Studio Web Debugger打开下载得到的压缩包&#xff0c;里面有一些文件夹列表&#xff08;4_3_x_comp &#xff0c; 4_4_x_comp &#xff0c; 5_0_x_comp &#xff0c; 5_2_x_comp &#xff0c; 5_2_x…

JavaFX技巧17:带有AnchorPane的动画工作台布局

最近&#xff0c;我不得不为应用程序实现一个布局&#xff0c;其中可以根据用户是否登录来隐藏或通过滑入/滑出动画显示或显示菜单区域和状态区域。 以下视频显示了实际的布局&#xff1a; 在过去&#xff0c;我可能会使用自定义控件和自定义布局代码来实现这种行为&#xff0…

php投票系统中各个文件的作用说明,PHP开发简单投票系统之投票页面功能模块(二)...

当完成前面的投票后&#xff0c;可以选择点击查看结果查看每个项目的总票数和所有项目的投票百分比。点击“查看结果”后程序会自动计算每个项目的票数和所占百分比。使用了隐藏表单属性隐藏域在页面中对于用户是不可见的&#xff0c;在表单中插入隐藏域的目的在于收集或发送信…

使用Spring Boot对REST URL进行集成测试

我们正在构建一个具有REST接口的Spring Boot应用程序&#xff0c;并且在某个时候我们想测试我们的REST接口&#xff0c;并在可能的情况下将此测试与常规单元测试集成。 一种方法是Autowire我们的REST控制器&#xff0c;并使用它来调用我们的端点。 但是&#xff0c;这不会完全融…

php最常用方法,php 常用方法

/*** 返回token参数* 参数 result 需要先urldecode*/function getToken($result) {$result urldecode ( $result ); // URL转码$Arr explode ( &, $result ); // 根据 & 符号拆分$temp array (); // 临时存放拆分的数组$myArray array (); // 待签名的数组// 循环构…

使用Google Guice消除实例之间的歧义

如果接口有多个实现&#xff0c;则Google guice提供了一种精巧的方法来选择目标实现。 我的示例基于Josh Long &#xff08; starbuxman &#xff09;的出色文章&#xff0c;内容涉及Spring提供的类似机制。 因此&#xff0c;请考虑一个名为MarketPlace的接口&#xff0c;该接…

ref 和out 关键字

ref 和out 关键字 通过对CLR的学习&#xff0c;我们可以知道&#xff0c;CLR默认所有方法参数都是传值的。对于引用类型的对象&#xff0c;传递的是对象的引用&#xff08;指向对象的指针&#xff09;&#xff0c;被调用者拥有该对象的引用的拷贝&#xff0c;能够修改对象&…