Hibernate相关概念

一、事物概念

Hibernate的任何对数据有改动的操作,都应该被放在事务里面。

hibernate中的事务由s.beginTransaction();开始由s.getTransaction().commit();结束

本例子,执行了两个操作

第一个,删除id=1的产品,这个是会成功的
第二个,修改id=2的产品,使得其产品名称超过了数据库中设置的长度30,这个是会失败的。
因为这两个操作都是在一个事务中,而且第二个操作失败了,所以最后的结果是两个操作都没有生效

 package hibernate.test;

 import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration; import hibernate.pojo.Product; public class testTransaction { public static void main(String[] args) {
// TODO Auto-generated method stub SessionFactory sFactory = new Configuration().configure().buildSessionFactory();
Session session = sFactory.openSession();
session.beginTransaction(); Product product = (Product) session.get(Product.class, 1);
session.delete(product); Product product2 = (Product) session.get(Product.class, 2);
product2.setName("iphoneiphoneiphoneiphoneiphoneiphoneiphoneiphoneiphone");
session.update(product2); session.getTransaction().commit();
session.close();
sFactory.close();
} }

二、属性延迟加载

属性的延迟加载: 当使用load的方式来获取对象的时候,只有访问了这个对象的属性,hibernate才会到数据库中进行查询,否则不会访问数据库。

 package hibernate.test;

 import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration; import hibernate.pojo.Product; public class testDelayProperty { public static void main(String[] args) {
// TODO Auto-generated method stub SessionFactory sFactory = new Configuration().configure().buildSessionFactory();
Session session = sFactory.openSession();
session.beginTransaction(); Product product = (Product) session.load(Product.class, 1);
System.out.println("log1");
System.out.println(product.getName());
System.out.println("log2"); session.getTransaction().commit();
session.close();
sFactory.close();
} }

三、关系延迟加载

延迟加载又叫lazyload,在one-many many-many的时候都可以使用关系的延迟加载。

<set name="products" lazy="false">改为<set name="products" lazy="true">表示通过Category获取产品是延迟加载的。

 <?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="hibernate.pojo">
<class name="Category" table="category">
<id name="id" column="id">
<generator class="native">
</generator>
</id>
<property name="name" /> <set name="products" lazy="true">
<key column="cid" not-null="false" />
<one-to-many class="Product" />
</set>
</class>
</hibernate-mapping>

测试:

  执行22行的时候,只会查询Category表的信息,不会查询product表。只有在执行24行,通过category取products的时候,才会进行对product表的查询。

 package hibernate.test;

 import java.util.Iterator;
import java.util.Set; import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration; import hibernate.pojo.Category;
import hibernate.pojo.Product; public class testDelayRelation { public static void main(String[] args) {
// TODO Auto-generated method stub SessionFactory sFactory = new Configuration().configure().buildSessionFactory();
Session session = sFactory.openSession();
session.beginTransaction(); Category category = (Category) session.get(Category.class, 4);
System.out.println("log1");
Set<Product> products = category.getProducts();
Iterator<Product> iterator = products.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next().getName()); }
System.out.println("log2"); session.getTransaction().commit();
session.close();
sFactory.close();
} }

四、级联

  什么是级联? 简单的说,就是没有配置级联的时候,删除分类,其对应的产品不会被删除。 但是如果配置了恰当的级联,那么删除分类的时候,其对应的产品都会被删除掉。

  级联有4种类型:

all:所有操作都执行级联操作;

none:所有操作都不执行级联操作;

delete:删除时执行级联操作;

save-update:保存和更新时执行级联操作;

级联通常用在one-many和many-to-many上,几乎不用在many-one上。

1.delete级联

在Category.hbm.xml 加上 <set name="products" cascade="delete" lazy="false">

在删除分类的时候,会把分类下对应的产品都删除掉,否则只会把产品对应的cid设置为空。

2.save-update级联

  运行代码就会发现,这3个瞬时状态的产品对象虽然没有添加到数据库里,但是在事务提交的时候,会把他们3个持久化。 如果没有cascade="save-update",就会报错。

 package hibernate.test;

 import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration; import hibernate.pojo.Category;
import hibernate.pojo.Product; public class testCascadeSaveUpdate {
/*
* 级联有4种类型: all:所有操作都执行级联操作; none:所有操作都不执行级联操作; delete:删除时执行级联操作;
* save-update:保存和更新时执行级联操作;
*/
public static void main(String[] args) {
// TODO Auto-generated method stub SessionFactory sFactory = new Configuration().configure().buildSessionFactory();
Session session = sFactory.openSession();
session.beginTransaction(); Category category = (Category) session.get(Category.class, 5);
Product product = new Product();
product.setName("xiaomi_note");
Product product2 = new Product();
product2.setName("xiaomi_max");
Product product3 = new Product();
product3.setName("xiaomi_8"); category.getProducts().add(product);
category.getProducts().add(product2);
category.getProducts().add(product3); session.getTransaction().commit();
session.close();
sFactory.close();
} }

五、一级缓存

  hibernate默认是开启一级缓存的,一级缓存存放在session上。

例子:

第一次通过id=1获取对象的时候,session中是没有对应缓存对象的,所以会在"log1"后出现sql查询语句。
第二次通过id=1获取对象的时候,session中有对应的缓存对象,所以在"log2"后不会出现sql查询语句。

 package hibernate.test;

 import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration; import hibernate.pojo.Category; public class testCacheL1 { public static void main(String[] args) {
// TODO Auto-generated method stub SessionFactory sFactory = new Configuration().configure().buildSessionFactory();
Session session = sFactory.openSession();
session.beginTransaction(); System.out.println("log1");
Category category = (Category) session.get(Category.class, 1);
System.out.println("log2");
Category category2 = (Category) session.get(Category.class, 1);
System.out.println("log3"); session.getTransaction().commit();
session.close();
sFactory.close();
} }

六、二级缓存

  Hibernate的一级缓存是在Session上,二级缓存是在SessionFactory上。

创建了两个Session:

在第一个Session里

第一次获取id=1的Category 会执行SQL语句

第二次获取id=1的Category,不会执行SQL语句,因为有一级缓存

在第二个Session里

获取id=1的Category,如果没有设置二级缓存时,会执行SQL语句,因为在第二个Session,没有缓存该对象。 所以总共会看到两条SQL语句。

如果设置了二级缓存就使用不同的session,都去获取id=1的category,只会访问一次数据库。因为第二次获取虽然没有从第二个session中拿到缓存,但是从sessionfactory中拿到了Category缓存对象。

1.在hibernate.cfg.xml 中增加对二级缓存的配置

 <?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory>
<!-- Database connection settings -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/tests?characterEncoding=UTF-8</property>
<property name="connection.username">root</property>
<property name="connection.password">123456</property>
<!-- SQL dialect -->
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="current_session_context_class">thread</property>
<property name="show_sql">true</property>
<property name="hbm2ddl.auto">update</property>
<property name="hibernate.cache.use_second_level_cache">true</property>
<property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
<mapping resource="hibernate/pojo/Product.hbm.xml" />
<mapping resource="hibernate/pojo/Category.hbm.xml" />
<mapping resource="hibernate/pojo/User.hbm.xml" />
</session-factory> </hibernate-configuration>

2.在src目录下,创建一个ehcache.xml用于EHCache的缓存配置。

 <ehcache>
<diskStore path="java.io.tmpdir"/>
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
/>
</ehcache>

3.对于要进行二级缓存的实体类,进行配置,增加<cache usage="read-only" />

4.测试

 package hibernate.test;

 import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration; import hibernate.pojo.Category; public class testCacheL2 { public static void main(String[] args) {
// TODO Auto-generated method stub SessionFactory sFactory = new Configuration().configure().buildSessionFactory();
Session session = sFactory.openSession();
session.beginTransaction(); Category category = (Category) session.get(Category.class, 1);
System.out.println("log1");
Category category2 = (Category) session.get(Category.class, 1);
System.out.println("log2");
session.getTransaction().commit();
session.close(); Session session2 = sFactory.openSession();
session2.beginTransaction();
Category category3 = (Category) session2.get(Category.class, 1);
System.out.println("log3"); session2.getTransaction().commit();
session2.close(); sFactory.close();
} }

七、分页

  使用Criteria进行分页查询Hibernate使用Criteria 来进行分页查询c.setFirstResult(2); 表示从第2条数据开始c.setMaxResults(5); 表示一共查询5条数据

 package hibernate.test;

 import java.util.List;

 import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.criterion.Restrictions; import hibernate.pojo.Product; public class testPaging { public static void main(String[] args) {
// TODO Auto-generated method stub SessionFactory sFactory = new Configuration().configure().buildSessionFactory();
Session session = sFactory.openSession();
session.beginTransaction(); String name = "iphone"; Criteria criteria = session.createCriteria(Product.class);
criteria.add(Restrictions.like("name", "%" + name + "%"));
criteria.setFirstResult(2);
criteria.setMaxResults(5); List<Product> products = criteria.list();
for (Product p : products) {
System.out.println(p.getName());
} session.getTransaction().commit();
session.close();
sFactory.close();
} }

八、两种获取方式

Hibernate中根据Id单条查询获取对象的方式有两种,分别是get()和load(),来看一下这两种方式的区别。

1.当get()方法被调用的时候就会立即发出SQL语句。

2.当调用load()方法的时候会返回一个目标对象的代理对象,在这个代理对象中只存储了目标对象的ID值,只有当调用除ID值以外的属性值的时候才会发出SQL查询的。

3.Exception

<1>当使用get获取数据库中不存在的数据时会抛出空指针异常NullPointerException

<2>当使用load获取数据库中不存在的数据时会发生一个ObjectNotFoundException异常。

  这个是因为使用load()的时候返回的是一个代理对象,因为这个时候还没有进行查询,所以我们并没有办法确定要查询的对象到底存在不存在,所以使用load()查询的返回值是永远不会为空的,但是呢,当我们试图访问被代理的真实对象的时候,因为这个对象并不存在,所以就抛出了一个ObjectNotFoundException。

  还有一种说法是get()是用于不确定对象是否真的存在的情况,所以在查询出来后可以先进行一个空指针判断,而load()方法用于对象一定存在的情况下,不然等会儿使用的时候就可能会抛出ObjectNotFoundException了。

4.缓存

  get()和load()都会使用缓存,都是首先从一级缓存Session中查找,当找不到的时候再去二级缓存中查找,当查询不到的时候get()返回的是null,而load()则返回代理对象。

  如果使用这两种方式访问同一个id数据,会发现两个返回的都是真实对象,连load()返回的也是真实对象,并且它们引用的还是同一块对象。这个是因为get()查询出来的对象后会将其放入到缓存中,而load()再去查询的时候它会先去缓存中查找,如果缓存中没有的话才会返回代理对象,但是当缓存中已经存在的话就直接将真实对象返回来了。

5.小结

返回值:

get()返回的是查询出来的实体对象,而load()查询出来的是一个目标实体的代理对象。

查询时机:

get()在调用的时候就立即发出SQL语句查询,而load()在访问非ID属性的时候才会发出查询语句并且将被代理对象target填充上,但是如果这个动作发生在Session被关闭后的话就会抛出LazyInitializationException。

查询结果为空时:

get()抛出NullPointerException

load()抛出ObjectNotFoundException

 package hibernate.test;

 import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration; import hibernate.pojo.Product; public class testLoadAndGet { /*
* load方式是延迟加载,只有属性被访问的时候才会调用sql语句 ;get方式是非延迟加载,无论后面的代码是否会访问到属性,马上执行sql语句
*/
@SuppressWarnings("unused")
public static void main(String[] args) {
// TODO Auto-generated method stub SessionFactory sFactory = new Configuration().configure().buildSessionFactory();
Session session = sFactory.openSession();
session.beginTransaction();
System.out.println("log1");
Product product = (Product) session.get(Product.class, 1);
System.out.println("log2");
Product product2 = (Product) session.load(Product.class, 2);
// Product product2 = (Product) session.load(Product.class, 200);
System.out.println("log3");
// System.out.println(product2.getName());
System.out.println("log4"); // Product p3 = (Product) session.get(Product.class, 500);
// System.out.println("p3=" + p3.getName()); // Product p4 = (Product) session.load(Product.class, 500);
// System.out.println("p4=" + p4.getName()); Product product3 = (Product) session.load(Product.class, 5);
System.out.println(product3.getName());
Product product4 = (Product) session.load(Product.class, 5);
System.out.println(product4.getName());
session.getTransaction().commit();
session.close();
System.out.println(product.getName());
sFactory.close();
} }

九、两种Session方式

Hibernate有两种方式获得session,分别是:openSession和getCurrentSession

区别在于

1. 获取的是否是同一个session对象 
openSession每次都会得到一个新的Session对象 
getCurrentSession在同一个线程中,每次都是获取相同的Session对象,但是在不同的线程中获取的是不同的Session对象 
2. 事务提交的必要性 
openSession只有在增加,删除,修改的时候需要事务,查询时不需要的 
getCurrentSession是所有操作都必须放在事务中进行,并且提交事务后,session就自动关闭,不能够再进行关闭

 package hibernate.test;

 import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration; import hibernate.pojo.Product; public class testSession { static Session session;
static Session session2; public static void main(String[] args) throws InterruptedException {
// TODO Auto-generated method stub SessionFactory sFactory = new Configuration().configure().buildSessionFactory();
// Session session = sFactory.openSession();
// Session session2 = sFactory.openSession(); // Session session = sFactory.getCurrentSession();
// Session session2 = sFactory.getCurrentSession();
//
// System.out.println(session == session2); // session.close();
// session2.close(); Thread thread = new Thread() {
public void run() {
session = sFactory.getCurrentSession();
}
};
thread.start(); Thread thread2 = new Thread() {
public void run() {
session2 = sFactory.getCurrentSession();
}
};
thread2.start(); thread.join();
thread2.join(); System.out.println(session == session2); Session session3 = sFactory.openSession();
System.out.println(((Product) session3.get(Product.class, 2)).getName()); // Session session4 = sFactory.getCurrentSession();
// session4.get(Product.class, 2); session.close();
session2.close(); Session session5 = sFactory.getCurrentSession();
session5.beginTransaction();
session5.get(Product.class, 3);
session5.getTransaction().commit();
// session5.close(); sFactory.close();
} }

十、N+1

  Hibernate有缓存机制,可以通过用id作为key把product对象保存在缓存中 同时hibernate也提供Query的查询方式。假设数据库中有100条记录,其中有30条记录在缓存中,但是使用Query的list方法,就会所有的100条数据都从数据库中查询,而无视这30条缓存中的记录。 N+1是什么意思呢,首先执行一条sql语句,去查询这100条记录,但是,只返回这100条记录的ID 然后再根据id,进行进一步查询。如果id在缓存中,就从缓存中获取product对象了,否则再从数据库中获取。

  Hibernate使用Iterator实现N+1。

  首先通过Query的iterator把所有满足条件的Product的id查出来然后再通过it.next()查询每一个对象如果这个对象在缓存中,就直接从缓存中取了否则就从数据库中获取N+1中的1,就是指只返回id的SQL语句,N指的是如果在缓存中找不到对应的数据,就到数据库中去查。

 package hibernate.test;

 import java.util.Iterator;

 import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration; import hibernate.pojo.Product; public class testN1 { public static void main(String[] args) {
// TODO Auto-generated method stub SessionFactory sFactory = new Configuration().configure().buildSessionFactory();
Session session = sFactory.openSession();
session.beginTransaction(); String name = "iphone";
Query query = session.createQuery("from Product p where p.name like ?");
query.setString(0, "%" + name + "%"); Iterator<Product> iterator = query.iterate();
while (iterator.hasNext()) {
Product product = (Product) iterator.next();
System.out.println(product.getName()); } Query query2 = session.createQuery("select count(*) from Product p where p.name like ?");
query2.setString(0, "%" + name + "%"); long total = (Long) query2.uniqueResult();
System.out.println(total); session.getTransaction().commit();
session.close();
sFactory.close();
} }

十一、乐观锁

  乐观锁(Optimistic Lock), 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据。

1.场景描述:

<1>. 通过session1得到id=1的对象 product1

<2>. 在product1原来价格的基础上增加1000

<3>. 更新product1之前,通过session2得到id=1的对象product2

<4>. 在product2原来价格的基础上增加1000

<5>. 更新product1

<6>. 更新product2

最后结果是product的价格只增加了1000,而不是2000

代码:

 package hibernate.test;

 import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration; import hibernate.pojo.Product; public class testOptimisticLock {
/*
* 场景描述 1. 通过session1得到id=1的对象 product1 2. 在product1原来价格的基础上增加1000
* 3.更新product1之前,通过session2得到id=1的对象product2 4. 在product2原来价格的基础上增加1000
* 5.更新product1 6. 更新product2
*/ public static void main(String[] args) throws InterruptedException {
// TODO Auto-generated method stub SessionFactory sFactory = new Configuration().configure().buildSessionFactory();
Session session = sFactory.openSession();
Session session2 = sFactory.openSession(); session.beginTransaction();
session2.beginTransaction(); Product product = (Product) session.get(Product.class, 1);
System.out.println("产品原价为:" + product.getPrice());
product.setPrice(product.getPrice() + 1000); Product product2 = (Product) session2.get(Product.class, 1);
product2.setPrice(product2.getPrice() + 1000); session.update(product);
session2.update(product2); session.getTransaction().commit();
session2.getTransaction().commit(); Product product3 = (Product) session.get(Product.class, 1);
System.out.println("最终的价格:" + product3.getPrice()); session.close();
session2.close();
sFactory.close();
} }

2.修改配置文件 Product.hbm.xml

<version name="version" column="ver" type="int"></version>增加一个version字段,用于版本信息控制。这就是乐观锁的核心机制。

比如session1获取product1的时候,version=1。 那么session1更新product1的时候,就需要确保version还是1才可以进行更新,并且更新结束后,把version改为2。
注意: version元素必须紧跟着id后面,否则会出错。

 <?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="hibernate.pojo">
<class name="Product" table="product">
<id name="id" column="id">
<generator class="native">
</generator>
</id>
<!--version元素必须紧挨着id后面 -->
<version name="version" column="ver" type="int"></version>
<property name="name" />
<property name="price" />
<many-to-one name="category" class="Category" column="cid"></many-to-one>
<set name="users" table="user_product" lazy="false" >
<key column="pid"></key>
<many-to-many column="uid" class="User"></many-to-many>
</set>
</class> </hibernate-mapping>

3.修改 Product.java

增加version属性

 package hibernate.pojo;

 import java.util.Set;

 public class Product {
int id;
String name;
float price;
Category category;
Set<User> users;
int version;
int cid; public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public float getPrice() {
return price;
} public void setPrice(float price) {
this.price = price;
} public Category getCategory() {
return category;
} public void setCategory(Category category) {
this.category = category;
} public Set<User> getUsers() {
return users;
} public void setUsers(Set<User> users) {
this.users = users;
} public int getCid() {
return cid;
} public void setCid(int cid) {
this.cid = cid;
} public int getVersion() {
return version;
} public void setVersion(int version) {
this.version = version;
} }

4.再次运行代码

5.原理

<1>. 假设数据库中产品的价格是10000,version是10
<2>. session1,session2分别获取了该对象
<3>. 都修改了对象的价格
<4>. session1试图保存到数据库,检测version依旧=10,成功保存,并把version修改为11
<5>. session2试图保存到数据库,检测version=11,说明该数据已经被其他人动过了。 保存失败,抛出异常

相关代码:https://github.com/lyj8330328/hibernate.git

笔记46 Hibernate快速入门(三)的更多相关文章

  1. 笔记47 Hibernate快速入门(四)

    Hibernate注解,完成原来xml文件里的映射信息. 使用注解时,要修改hibernate.cfg.xml中的映射,不再是通过xml文件 <mapping class="hiber ...

  2. 笔记45 Hibernate快速入门(二)

    Hibernate O/R 映射 一.多对一 一个Product对应一个Category,一个Category对应多个Product,所以Product和Category是多对一的关系.使用hiber ...

  3. 笔记44 Hibernate快速入门(一)

    一.Hibernate简介 Hibernate 是传统 Java 对象和数据库服务器之间的桥梁,用来处理基于 O/R 映射机制和模式的那些对象. Hibernate 架构是分层的,作为数据访问层,你不 ...

  4. (转)Hibernate快速入门

    http://blog.csdn.net/yerenyuan_pku/article/details/64209343 Hibernate框架介绍 什么是Hibernate 我们可以从度娘上摘抄这样有 ...

  5. 【笔记】PyTorch快速入门:基础部分合集

    PyTorch快速入门 Tensors Tensors贯穿PyTorch始终 和多维数组很相似,一个特点是可以硬件加速 Tensors的初始化 有很多方式 直接给值 data = [[1,2],[3, ...

  6. 【Python】【学习笔记】1.快速入门

    1.软件安装 从官网下载相应版本的安装包,一般不大. https://www.python.org/ 安装一路默认即可 2. 参考教程:快速入门:十分钟学会Python 本文的内容介于教程(Totur ...

  7. MyBatis学习笔记(一)——MyBatis快速入门

    转自孤傲苍狼的博客:http://www.cnblogs.com/xdp-gacl/p/4261895.html 一.Mybatis介绍 MyBatis是一个支持普通SQL查询,存储过程和高级映射的优 ...

  8. 笔记52 Mybatis快速入门(三)

    一.更多查询 1.模糊查询 修改Category.xml,提供listCategoryByName查询语句select * from category where name like concat(' ...

  9. 笔记50 Mybatis快速入门(一)

    一.Mybatis简介 MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及高级映射.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis ...

随机推荐

  1. LeetCode Array Easy 88. Merge Sorted Array

    Description Given two sorted integer arrays nums1 and nums2, merge nums2 into nums1 as one sorted ar ...

  2. ionic3 emoj表情包插件 emoji-picker

    1.效果演示: 2.安装扩展包依赖 npm i @ionic-tools/emoji-picker --save 3.app.module.ts中导入插件 import { EmojiPickerMo ...

  3. tcpdump - 转储网络上的数据流

    总览 (SYNOPSIS) tcpdump [ -adeflnNOpqStvx ] [ -c count ] [ -F file ] [ -i interface ] [ -r file ] [ -s ...

  4. Codeforces 1156D 带权并查集

    题意:给你一颗树,树边的权值可能是0或1,问先走0边,再走1边,或者只走1边的路径有多少条? 思路:对于一个点,假设通过0边相连的点一共有x个(包括自己),通过1边相连的有y个(包括自己),那么对答案 ...

  5. IO流分类

    IO流在java中从输入和输出角度分类: 1.输入流 2.输出流 IO流在java中从数据的角度来分类: 1.字符流:文本,我们能读懂的都可以认为是字符流,如:文章,java文件等 字符输入流的超类: ...

  6. cmake build

    { //cmake CMakeLists.txt -G "Visual Studio 15 2017" }

  7. 获取min-max之间的随机数

    private static String getRandom(int min, int max){ Integer random =(int)(min+Math.random()*(max-min+ ...

  8. java中设置http响应头控制浏览器禁止缓存当前文档内容

    response.setDateHeader("expries", -1); response.setHeader("Cache-Control", " ...

  9. PHP FILTER_SANITIZE_NUMBER_FLOAT 过滤器

    定义和用法 FILTER_SANITIZE_NUMBER_FLOAT 过滤器删除浮点数中所有非法的字符. 该过滤器默认允许所有数字以及 + - Name: "number_float&quo ...

  10. react react使用css

    在react 中使用css有以下几种方法 第一种全局使用 app.js import React from 'react'; import Router from "./router&quo ...