笔记46 Hibernate快速入门(三)
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快速入门(三)的更多相关文章
- 笔记47 Hibernate快速入门(四)
Hibernate注解,完成原来xml文件里的映射信息. 使用注解时,要修改hibernate.cfg.xml中的映射,不再是通过xml文件 <mapping class="hiber ...
- 笔记45 Hibernate快速入门(二)
Hibernate O/R 映射 一.多对一 一个Product对应一个Category,一个Category对应多个Product,所以Product和Category是多对一的关系.使用hiber ...
- 笔记44 Hibernate快速入门(一)
一.Hibernate简介 Hibernate 是传统 Java 对象和数据库服务器之间的桥梁,用来处理基于 O/R 映射机制和模式的那些对象. Hibernate 架构是分层的,作为数据访问层,你不 ...
- (转)Hibernate快速入门
http://blog.csdn.net/yerenyuan_pku/article/details/64209343 Hibernate框架介绍 什么是Hibernate 我们可以从度娘上摘抄这样有 ...
- 【笔记】PyTorch快速入门:基础部分合集
PyTorch快速入门 Tensors Tensors贯穿PyTorch始终 和多维数组很相似,一个特点是可以硬件加速 Tensors的初始化 有很多方式 直接给值 data = [[1,2],[3, ...
- 【Python】【学习笔记】1.快速入门
1.软件安装 从官网下载相应版本的安装包,一般不大. https://www.python.org/ 安装一路默认即可 2. 参考教程:快速入门:十分钟学会Python 本文的内容介于教程(Totur ...
- MyBatis学习笔记(一)——MyBatis快速入门
转自孤傲苍狼的博客:http://www.cnblogs.com/xdp-gacl/p/4261895.html 一.Mybatis介绍 MyBatis是一个支持普通SQL查询,存储过程和高级映射的优 ...
- 笔记52 Mybatis快速入门(三)
一.更多查询 1.模糊查询 修改Category.xml,提供listCategoryByName查询语句select * from category where name like concat(' ...
- 笔记50 Mybatis快速入门(一)
一.Mybatis简介 MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及高级映射.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis ...
随机推荐
- vue做一个上移和下移,删除的li 功能
效果图: 思路就是冒泡原理,把数据放到一个空数组,对其进行排序, 单选框用到的是iview . 具体实现代码: <div v-for="item in singledLists&quo ...
- Asp.net Controller中View 和Action方法认证Authorize 及对AuthorizeAttribute扩展
Asp.net Controller中View和Action方法认证Authorize 在建立Web 站点安全性时 1.登录后才可访问系统文件 ——限制 Forms认证 <authenticat ...
- SQLServer存储过程学习记录
简单来说,存储过程就是一条或者多条sql语句的集合,可视为批处理文件,但是其作用不仅限于批处理. 一.存储过程的概述 SQL Server中的存储过程是使用T_SQL编写的代码段.它的目的在于能够方便 ...
- [机器学习][face recognition] 一个视频人脸识别实现
开发环境和用到的库: Ubuntu jupyter notebook(python3.6) OpenCV Dlib face_recognition 实现效果如下(视频截图): #coding=utf ...
- c# DataTable join 两表连接
转:https://www.cnblogs.com/xuxiaona/p/4000344.html JlrInfodt和dtsource是两个datatable,通过[姓名]和[lqry]进行关联 v ...
- WPF 从服务器下载文件
1.先获取服务器下载地址,给出要下载到的目标地址 public void DownloadFileFromServer() { string serverFilePath = "http:/ ...
- 前端,用js根据一个对象,去除另个对象中重复的元素
这里的应用场景是,两个div盛放待选项目和已选项目,如下图 <div class="col-xs-6 col-sm-6 col-md-6 col-lg-6"> < ...
- QList和QVector等容器的区别:(转)
源地址:https://blog.csdn.net/qq_33266987/article/details/53333373 Qlist.QVector 与 list.vector似乎不太类似: li ...
- python 对redis key的基本操作
首先看一下Python 操作redis.StrictRedis 的初始化方法__init__ def __init__(self, host='localhost', port=6379, db=0, ...
- 简单记录下Jmeter通过CSV保存测试数据,测试用例,及将测试结果导出到Excel里
1.CSV保存测试数据,并上传到CSV Data Set Config,设置相关属性 2.CSV保存测试用例,并上传到CSV Data Set Config,设置相关属性 3.设置一个http请求,设 ...