当前位置: 首页 > 编程日记 > 正文

Hibernate复习之Hibernate基本介绍

众所周知。眼下流行的面向对象的对象关系映射的Java持久层框架有MyBatis和Hibernate。他们都是对象关系映射ORM。 解决的主要问题就是对象-关系的映射。域模型和关系模型都分别建立在概念模型的基础上。域模型是面向对象的,关系模型是面向关系的,普通情况下。一个持久化类和一个表相应,类的每一个实例相应表中的一条记录。 (可能存在类中多个属性相应一列的情况,映射组成关系), ORM中间件採用元数据来描写叙述对象-关系映射细节,元数据通常採用XML格式。而且存放在专门的对象-关系映射文件里,假设希望把ORM软件集成到自己的Java应用中。用户首先要配置对象-关系映射文件。Hibernate中也就是entity.hbm.xml,而MyBatis中就是entityMapper.xml
以下主要介绍一下Hibernate的运行过程:

session.save(customer)

运行过程:
1)运用反射机制,获得customer对象的类型Customer.class
2)參考对象-关系映射元数据。了解Customer类相应的表,以及属性相应的列,Customer类和其它类关系。
3)依据以上映射信息。生成SQL语句

insert into tab_customer values(id,name,password,telphone);

4)调用JDBC API。运行以上的SQL语句。


JDBC与Hibernate比較:
1,JDBC: Java中嵌入SQL。不便于维护
Hibernate: 无须编写SQL语句;由Hibernate通过读取映射文件在运行时自己主动生成SQL

save(student)-> insert into customer values(?,?,?);

2。JDBC:查询数据。须要手动封装成对象;保存对象,须要手动插入值
Hibernate: 可自己主动实现对象和表中记录的转换
3,JDBC:查询内存中已存在的对象。改动属性值,均须要和数据库进行交互
Hibernate:通过Dirty checking(脏检查)避免交互;


Hibernate的工作原理:
1。Hibernate框架依据hibernate.cfg.xml的配置的信息来和数据库进行通信,当然和Spring结合后也能够通过注解来实现。
2,Hibernate框架依据详细的映射文件**.hbm.xml 来保存。更新。删除,查询对象。


Hibernate API。Hibernate中几个比較重要的类:
Configuration接口:
Configuration对象用于配置而且启动Hibernate,Hibernate应用通过Configuration实例还指定对象-关系映射文件的位置或者动态配置Hibernate的属性。然后创建SessionFactory实例

Configuration config = new Configuration();
Config.configure();
SessionFactory factory = config.buildSessionFactory();

SessionFactory :
用来构造Session的实例对象,它的特点:
1)线程安全: 该实例对象何以被多个线程共享
2)重量级:该实例对象的构造和销毁消耗系统资源,所以一般在应用程序启动的时候就构造实例对象,一般一个数据库相应一个SessionFactory的实例对象。假设要訪问多个数据库,就须要创建多个该实例对象。


3)SessionFactory实例对象中维护了一个非常大的缓存,存放了一些提前定义的SQL语句和XML配置文件的信息,另外还维持了一个Hibernate的第二级缓存(缓存了全部Session对象所载入的POJO对象),用来保存在该生命周期中的一些业务对象,可是这个第二级缓存默认是关闭的,必须在xml中手动配置才干够开放

Session session = factory.openSession();

Session(别名:持久化管理器),用来对对象的保存,更新,删除和查询
特点:
1)线程不安全。要避免同一个Session对象被多个线程共享,一般一个线程相应一个Session
2)轻量级:能够随意的构造和销毁该实例对象。


3)Session对象中维护了一个缓存,称为Hibernate的第二级缓存(缓存了当前Session对象所载入的那些POJO对象),每一个Session对象都有自己的缓存。
Query:
利用HQL语句(Hibernate Query Language)用来查询单个或者多个对象,面向对象的

Query query = session.createQuery("from Student where studentId=1");
Student s = (Student)query.uniqueResult();

Criteria:
功能同上。以面向对象的形式和数据库进行复杂的CRUD操作,还适用于动态查询。
Transaction:
用来处理事务,事务的启动,提交,回滚


OID:主键
在Java语言中。依照内存地址来识别或区分同一个类的不同对象。关系型数据库按主键值来识别或区分同一个表的不同记录,Hibernate使用OID来统一两者之间的矛盾,OID是关系数据库中的主键(通常为代理主键)在Java对象模型中的等价物。

在运行时,Hibernate依据OID来维持Java对象和数据库表中记录的相应关系。

为了保证持久化对象的OID的唯一性和不可变性。通常由Hibernate或底层数据库来为OID赋值,能够将OID的setId()方法设置为private类型,以禁止Java应用程序随便改动OID。
:子元素用来设定标识符生成器
Hibernate提供了标识符生成器口:net.sf.hibernate.id.IdentifierGenerator,而且提供了非常多内置实现。

net.sf.hibernate.id.IdentityGenerator –缩写名– identity
net.sf.hibernate.id.IncrementGenerator –缩写名– increment

主键生成方式:
1,increment:
其生成方式与底层数据库无关。大部分数据库都支持,该方式的实现机制是在当前应用实例中维持一个变量,以保存着当前的最大值。之后每次须要生成主键的时候将此值加1作为主键。其不足之处是当多个线程并发对数据库表进行写操作时。可能出现同样的主键值,发生主键反复的冲突。所以在多线程并发操作的时候不应该使用该方法。

<id name="id" column="ID"><!-- 主键生成机制 --><generator class="increment"/>
</id>

2,identity:
与底层数据库有关,要求数据库支持Identity。如MySQL中auto_increment,SQL Server中的identity。支持的数据库有MySQL,SQL Server,DB2,Sybase,可是不支持oracle,它同一时候支持并发操作。

<id name="id" column="ID"><!-- 主键生成机制 --><generator class="identity" />
</id>

3,assigned:
主键由外部程序负责生成。无需Hibernate參与。假设要由程序代码来指定主键,就採有这样的方式。

<id name="id" column="ID"><!-- 主键生成机制 --><generator class="assigned" />
</id>

4,sequence
使用序列生成主键,须要底层数据库支持在数据库中建一个序列

create sequence seq_name increment by 1 start with 1;

然后在映射文件里指定使用序列的名字

<id name="id" column="ID"><!-- 主键生成机制 --><generator class="sequence"><param name="sequence">seq_name</param></generator>
</id>

5,hilo
通过hi/lo算法生成主键,须要一个表来保存主键的信息,在数据库中建一张表:

create table hi_value(next_hi number not null);
insert into hi_value(next_hi) values(1);
commit;

映射文件里须要指明表的这些信息

<id name="id" column="ID"><!-- 主键生成机制 --><generator class="hilo"><param name="table">hi_value</param><param name="column">next_hi</param><param name="max_lo">100</param></generator>
</id>

6,seqhilo
与hilo 相似,通过hi/lo 算法实现的主键生成机制,仅仅是主键历史状态保存在Sequence中。适用于支持Sequence的数据库,
在数据库中建一个序列

create sequence seq_name increment by 1 start with 1; 
<id name="id" column="ID"><!-- 主键生成机制 --><generator class="seqhilo"><param name="sequence">seq_name</param><param name="max_lo">100</param></generator>
</id>

7。 native:
由Hibernate依据不同的数据库方言自行推断採用identity、hilo、sequence当中一种作为Hibernate主键生成方式,native的长处是与底层无关。便于不同数据库之间的移植,由Hibernate依据不同数据库选择主键的生成方式。在oracle中须要创建叫 Hibernate_sequence名字的sequence。假设设置了Hibernate.hbm2ddl.auto属性,不须要手动建立序列,前提是数据库帐号必须有Create Sequence这样的高级权限。mysql等数据库则不用建立sequence。

<id name="id" column="ID"><!-- 主键生成机制 --><generator class="native" />
</id>

8,foreign
外键生成方式,依赖其它表的主键。在主键一对一映射中须要使用到

<id name="id" column="ID"><!-- 主键生成机制 --><generator class="foreign><param name="property">id</param></generator>
</id>

9,uuid.hex:
採用基于128位的算法生成唯一值,并编制成32位长度的唯一字符串作为主键值,uuid.hex的长处是支持大部分数据库,缺点就是要占用较大的存储空间。

对于并发Insert要求较高的系统。推荐採用uuid.hex 作为主键生成机制。

<id name="id" column="ID"><!-- 主键生成机制 --><generator class="uuid.hex" />
</id>

10。uuid.string:
使用UUID算法。UUID被编码为一个16个字符长的随意ASCII字符组成的字符串。

不能在PostgreSQL数据库中使用。

uuid.string同uuid.hex相似,须要占非常大的存储空间。
11,select
使用触发器生成主键(主要用于早期的数据库主键生成机制,少用)


介绍完以上这些内容之后,以下就简单的体验一下搭建Hibernate的开发环境:
1.导入Hibernate的jar包,我这里新建的是Maven项目,因此首先须要加入关于Hibernate的依赖,由于我们还须要与数据库打交道。因此还须要加入数据库以及数据源的依赖jar包,以下是我的pom.xml文件的内容:

<properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><hibernate.version>4.1.7.Final</hibernate.version><druid.version>1.0.12</druid.version><mysql.version>5.1.18</mysql.version>
</properties><dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency><!-- hibernate4 --><dependency><groupId>org.hibernate</groupId><artifactId>hibernate-core</artifactId><version>${hibernate.version}</version></dependency><!--Druid连接池包 --><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>${druid.version}</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>${mysql.version}</version></dependency>
</dependencies>

2.在src/main/resources文件夹下新建一个hibernate.cfg.xml的文件。里面我们主要配置数据源:

<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/hibernate</property><property name="connection.username">root</property><property name="connection.password">admin</property><!-- SQL方言 --><property name="dialect">org.hibernate.dialect.MySQLDialect</property><!-- 在控制台打印出运行的SQL语句 --><!-- Echo all executed SQL to stdout --><property name="show_sql">true</property><!-- 是否格式化打印出来的SQL --><property name="format_sql">true</property><!-- 将映射文件转换为数据库定义语言 --><!-- Drop and re-create the database schema on startup --><!-- web项目启动时怎么操作表结构:更新、删除重建 --><property name="hbm2ddl.auto">update</property><!-- 映射文件 --><mapping resource="student.hbm.xml" /></session-factory>
</hibernate-configuration>

3.我们这里新建一个Student的实体类。而且也在src/main/resources文件夹下创建一个映射文件:student.hbm.xml
Student.java

package com.ecjtu.hibernate.entity;import java.io.Serializable;
import java.util.Date;public class Student implements Serializable {private static final long serialVersionUID = 1L;private String major;private Long id;private String name;private String sex;private Integer age;private Date birthday;public Student() {}public Student(String major, Long id, String name, String sex, int age,Date birthday) {super();this.major = major;this.id = id;this.name = name;this.sex = sex;this.age = age;this.birthday = birthday;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}public Date getBirthday() {return birthday;}public void setBirthday(Date birthday) {this.birthday = birthday;}public String getMajor() {return major;}public void setMajor(String major) {this.major = major;}public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}@Overridepublic String toString() {return "Student[Major:" + getMajor() + " Id:" + getId() + " Name:"+ getName() + " sex:" + getSex() + " Age:" + getAge()+ " birthday:" + getBirthday() + "]";}
}

student.hbm.xml

<?

xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="com.ecjtu.hibernate.entity"> <class name="Student" table="TAB_STUDENT"> <id name="id" column="id"> <!-- 主键生成机制:自增长 --> <generator class="increment"/> </id> <!-- 属性字段 --> <property name="major"/> <property name="name"/> <property name="sex"/> <property name="age"/> <property name="birthday"/> </class> </hibernate-mapping>

4.建好这些之后基本上也就大功告成了,接下来就能够測试了。在src/test/java以下新建一个測试类HibernateTest.java

package com.ecjtu.hibernate.Test;import java.util.Date;import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.junit.Before;
import org.junit.Test;import com.ecjtu.hibernate.entity.Student;/*** @ClassName: HibernateTest* @Description: Hibernate測试* @author Zhouxh* @date 2017年2月19日*/
public class HibernateTest {private SessionFactory sessionFactory;@SuppressWarnings({ "deprecation"})@Beforepublic void init(){//1.创建配置对象Configuration configuration=new Configuration();//2.读取配置文件,參数可为空。Document。File,配置文件的路径或者URL//HibernateTest/src/main/resources/hibernate.cfg.xmlconfiguration.configure();//3.依据配置文件,创建一级缓存(sessionFactory)sessionFactory=configuration.buildSessionFactory();}@Testpublic void test(){/*** 建立与数据库的连接* 映射文件,映射对象* session  代码与数据库之间的会话*///4.创建Session。打开会话Session session=sessionFactory.openSession();//5.开启事物Transaction transaction=session.beginTransaction();Student student=new Student("软件工程", 1000L, "李四", "男", 34, new Date(System.currentTimeMillis()));session.save(student);//6.事物的提交transaction.commit();//7.session的关闭session.close();}
}

5.运行完Junit单元測试成功了就可以。这时控制台也会打出insert into语句,这就说明我们的配置没有问题了。


6.封装HibernateSessionFactory工具类,由于Session是线程不安全的。为了保证当前线程仅仅有一个session对象,而且当前线程中的Session不能让其它线程来訪问,须要将获取Session的方法进行封装。为了保证Session的线程安全性。须要将Session放到ThreadLocal中,ThreadLocal为线程本地变量
HibernateSessionFactory.java,主要是为了维护Session的创建和关闭。

package com.ecjtu.hibernate.util;import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;/*** @ClassName: HibernateSessionFactory* @Description: 封装一个创建Session的工厂而且得到Session的方法* @author Zhouxh* @date 2017年2月20日*/
@SuppressWarnings("deprecation")
public class HibernateSessionFactory {//hibernate.cfg.xml文件的位置//private static String configFile = "hibernate.cfg.xml";private static SessionFactory factory;// 用于存放Session,该对象是线程安全的。仅仅有当前线程才干訪问private static ThreadLocal<Session> threadLocal;static {Configuration config = new Configuration( );// 无參默认系统去找src以下的hibernate.cfg.xml"config.configure();// 重量级:该实例对象的构造和销毁消耗系统资源,所以一般在应用程序启动的时候就构造实例对象,// 一般一个数据库相应一个SessionFactory的实例对象,// 假设要訪问多个数据库,就须要创建多个该实例对象。

factory = config.buildSessionFactory(); threadLocal = new ThreadLocal<Session>(); } /** * @Title: getSession * @Description: 获取Session * @return * @throws */ public static Session getSession() { // 该方法底层是一个map实现的Key为当前线程的对象,value为Session // 假设当前线程没有打开过Session,那么就返回空,意味着我们须要去创建一个Session, // 保证了一个线程里面相应一个Session Session session = threadLocal.get(); // 第一个为空的话,第二个表达式不会运行,避免了空指针 // session为空而且或者他没有被打开过就去创建 if (session == null || !session.isOpen()) { session = factory.openSession(); // 该方法底层通过Map来保存的,调用该方法会自己主动帮你创建一个map出来。 // 并通过key-value保存Session到map中,获取session的时候通过key去取的话 // 不同的key就会返回不同的session threadLocal.set(session); } return session; } /** * @Title: closeSession * @Description: 关闭Session * @throws */ public static void closeSession() { Session session = threadLocal.get(); threadLocal.set(null); if (session != null) { session.close(); } } }

到这里。Hibernate复习的第一部分也就结束了。主要就是简介一下Hibernate的使用和主要的一些信息。

最后附上一张Hibernate的内置映射类型,也就是Hibernate的类型—Java类型—标准SQL类型三者之间的相应关系:
这里写图片描写叙述

相关文章:

Linux常用命令手册

核心&#xff1a; cat定位&#xff0c;sed时间搜索&#xff0c;grep关键字查询&#xff0c;tail行数&#xff0c;|管道结合 最前N行 这个主要看文件最开始是什么时候记录了什么 #head -1 XXX.log 最后N行 #cat XXX.log | tail -n 10 时间区间搜索 #sed -n /2010-05-20…

程序员敲诈老板,或面临 37 年监禁

‍‍作者 | 祝涛 出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09;12月1日&#xff0c;网络设备制造商优比快&#xff08;Ubiquiti&#xff09;的前雇员尼古拉斯夏普&#xff08;nicholas Sharp&#xff09;被捕&#xff0c;他被控窃取数据&#xff0c;并试图…

使用modernizr.js检测浏览器对html5以及css3的支持情况

使用modernizr.js检测浏览器对html5和css3的支持情况 详情请看主页&#xff1a;modernizr主页 1. modernizr 是什么&#xff1f; modernize 是一个js库————一个用于检测当前浏览器对html5&css3 的支持情况&#xff0c;其中包括对 css3 的 font-face、border-radius、…

SharePoint运行状况分析器有关磁盘空间不足的警告

对于负责管理SharePoint内部部署安装的SharePoint管理员&#xff0c;SharePoint Health Analyzer是一款出色的工具。此功能不仅有助于解决服务器故障和服务失败的问题&#xff0c;还提供了有关如何解决问题的提示。总的来说&#xff0c;我觉得这个功能非常有帮助。但是&#xf…

百度PHP高级顾问惠新宸:PHP在百度的发展历程

惠新宸&#xff0c;百度PHP高级顾问,年二十有八&#xff0c;好追根究底&#xff0c;有不良嗜好, 幸性本善。乙酉年识互联网&#xff0c;丁亥年入雅虎&#xff0c;翌年入百度。虽性好安稳&#xff0c;然经变无数&#xff0c;唯常叹"人生&#xff0c;菠菜汤尔"。大家好…

Python 远程连接服务器用它就够了

作者 | 费弗里来源 | Python大数据分析❝本文示例代码及文件已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes❞1 简介日常工作中经常需要通过SSH连接到多台远程服务器来完成各种任务&#xff0c;当需要操作的服务器众多&#xff0c;且要执行的任务涉…

如何在centos安装python-mysql

在python中使用mysql&#xff0c;需要安装mysql-python依赖包&#xff0c;可以通过pip来安装&#xff1a;pip install MySQL-python如果发生错误&#xff0c;需要先安装一个开发包&#xff1a;yum install python-devel如果还是报错&#xff0c;运行&#xff1a;yum install my…

DNS 到底怎么工作的? (How does dns work?)

其实这个问题每次看的时候都觉得很明白&#xff0c;但是很久之后就忘记了&#xff0c;所以这次准备记录下来。深入到这个过程的各个细节之中&#xff0c;以后多看看。 Step 1 请求缓存信息&#xff1a; 当你在开始访问一个 www.baidu.com 开始&#xff0c;第一件事情就是去访问…

#pragma pack(n) 的作用

在C语言中&#xff0c;结构是一种复合数据类型&#xff0c;其构成元素既可以是基本数据类型&#xff08;如int、long、float等&#xff09;的变量&#xff0c;也可以是一些复合数据类型&#xff08;如数组、结构、联合等&#xff09;的数据单元。在结构中&#xff0c;编译器为结…

LoadRunner设置检查点的几种方法介绍

LoadRunner设置检查点的几种方法介绍 发布时间: 2011-5-03 11:53 作者: 一米阳光做测试 来源: 51Testing软件测试网采编 字体: 小 中 大 | 上一篇 下一篇 | 打印 | 我要投稿 3、将脚本切换回代码界面&#xff0c; 在光标闪烁的上行&#xff0c;添加如下的代码&…

Python 爬虫利器 Selenium 从入门到进阶

作者 | 俊欣来源 | 关于数据分析与可视化今天小编就来讲讲selenium&#xff0c;我们大致会讲这些内容selenium简介与安装页面元素的定位浏览器的控制鼠标的控制键盘的控制设置元素的等待获取cookies调用JavaScriptselenium进阶selenium的简介与安装selenium是最广泛使用的开源W…

获取下个月的今天

/* 获取下个月的今天如果 $date 2018-1-31 二月没有31号 则获取二月份的最后一天 返回值为2018-2-28如果 $date 2018-1-15 返回值为2018-2-15 -- psw-- */function getNextMonthDays($date){$firstday date(Y-m-01, strtotime($date));$lastday strtotime("$firstday …

C语言的sizeof和strlen

strlen是函数&#xff0c;而sizeof是算符。strlen需要进行一次函数调用&#xff0c;而对于sizeof而言&#xff0c;因为缓冲区已经用已知字符串进行了初始化&#xff0c;起长度是固定的&#xff0c;所以sizeof在编译时计算缓冲区的长度。因为sizeof()测试的是数组的长度。而strl…

机器人 Ameca「苏醒」瞬间逼真到令人恐惧,网友纷纷惊叹……

整理 | 禾木木 出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09; 近日&#xff0c;国内外网友都被一段机器人「苏醒」的视频惊讶到。 视频开始时&#xff0c;机器人似乎已经睡着&#xff0c;眼睛闭着&#xff0c;头部略微向下倾斜。随着肩膀的伸展&#xff0c;机器…

linux源码包卸载方式

linux源码包软件的安装与卸载3人收藏此文章,我要收藏 发表于1年前 , 已有593次阅读 共0个评论Linux软件安装与卸载&#xff08;源码包形式&#xff09;&#xff1a;一般情况下linux程序的发布不能像windows那样&#xff0c;直接打包成一个setup.exe文件&#xff0c;然用户安装 …

在实践中我遇到stompjs, websocket和nginx的问题与总结

阅读原文&#xff1a;https://wdd.js.org/stomp-over... 1. AWS EC2 不支持WebSocket 直达解决方案 英文版 简单说一下思路&#xff1a;WebSocket底层基于TCP协议的&#xff0c;如果你的服务器基于HTTP协议暴露80端口&#xff0c;那WebSocket肯定无法连接。你只要将HTTP协议修改…

C语言memset函数详解(Linux下和windows下的差异)

memest原型 (please type "man memset" in your shell) void *memset(void *s, int c, size_t n); memset:作用是在一段内存块中填充某个给定的值&#xff0c;它对较大的结构体或数组进行清零操作的一种最快方法。 #include <stdio.h>#include <string.…

Oracle 工程师离职并回踩:MySQL 糟糕透顶,强烈推荐 PostgreSQL

整理 | 祝涛 出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09;如果你即将离职&#xff0c;你会做什么&#xff1f;抨击自己付出了五年心血的技术——这是Oracle公司前首席软件工程师、MySQL优化器团队成员Steinar Gunderson的选择。这位工程师现已在Chrome团队…

ORA-01109:数据库未打开(解决)

SQL> startup mountORA-01081: 无法启动已在运行的 ORACLE - 请首先关闭它SQL> shutdown immediateORA-01109: 数据库未打开 已经卸载数据库。ORACLE 例程已经关闭。SQL> startup mountORACLE 例程已经启动。 Total System Global Area 612368384 bytesFixed Size 125…

[洛谷P1317]低洼地

题目大意&#xff1a;一组数&#xff0c;分别表示地平线的高度变化。高度值为整数&#xff0c;相邻高度用直线连接。找出并统计有多少个可能积水的低洼地&#xff1f;&#xff08;首尾都为0&#xff09; 题解&#xff1a;求出其中都多少个不严格下降子段和不严格上升子段所夹的…

Linux环境编程--多线程

本文作者: 姚继锋 (2001-08-11 09:05:00) 时隔多年 原文地址已经无从查。。。 居然是2001年就写了 今天看来对初学者还是很有参考意义 所以特转给大家 本人在原文基础上适当修改 1 引言 线程&#xff08;thread&#xff09;技术早在60年代就被提出&#xff0c;但真正应…

Python 到底该怎么学才好?你关心的答案来了

相对于Android、IOS等技术&#xff0c;Python有着更为广阔的应用领域&#xff0c;例如前后端、AI、数据分析、爬虫、自动化、游戏开发等几乎所有领域都有它的应用。但也正因为如此&#xff0c;很多新人在学完Python基础后&#xff0c;根本不知道该选择什么方向深造&#xff0c;…

9513 防空洞

时间限制:1000MS 内存限制:65535K提交次数:104 通过次数:24 题型: 编程题 语言: G;GCC Description 有一天&#xff0c;dragon123偷偷地拿锄头在学校里挖开了一个尘封已久的防空洞。他在这个防空洞里面找到许多贵重的东西&#xff1a;一些石头和一些液体。dragon123知道&…

学习Mybatis与mysql数据库的示例笔记

目录结构&#xff1a; pom.xml文件 1 <?xml version"1.0" encoding"UTF-8"?>2 <project xmlns"http://maven.apache.org/POM/4.0.0"3 xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"4 xsi:schem…

Linux环境编程--进程通信

实验内容 编写程序实现进程的管道通信。用系统调用pipe( )建立一管道&#xff0c;二个子进程P1和P2分别向管道各写一句话&#xff1a;Child 1 is sending a message!Child 2 is sending a message! 父进程从管道中读出二个来自子进程的信息并显示&#xff08;要求先接收P1&…

你的编程能力从什么时候开始突飞猛进的?

如果提到程序员&#xff0c;很多人的印象是&#xff1a;呆板、木讷、不懂浪漫。如果提到代码&#xff0c;很多人的印象是&#xff1a;枯燥、繁琐、很难理解。但其实程序员的浪漫是普通人想象不到的&#xff0c;有一个网友为了追女生&#xff0c;以自己和女生为主角写了一个战棋…

超级 App 手机百度云端架构设计与个性化推荐

2015 年 6 月 28 日下午&#xff0c;百度与 InfoQ 携手举办了手机百度“云和端技术实践”沙龙活动。这是手机百度首次公开超级 App 背后的技术知识。活动分云端和客户端技术两个会场同时举办&#xff0c;吸引了众多技术爱好者前来学习交流。现场人数爆满&#xff0c;气氛热烈。…

Scala和范畴论 -- 对Monad的一点认识

背景 所有一切的开始都是因为这句话&#xff1a;一个单子&#xff08;Monad&#xff09;说白了不过就是自函子范畴上的一个幺半群而已&#xff0c;有什么难以理解的。第一次看到这句话是在这篇文章&#xff1a;程序语言简史(伪)。这句话出自Haskell大神Philip Wadler&#xff0…

Linux环境编程--linux中的perror、exit、_exit、wait 和 waitpid

perror&#xff1a;#include<stdio.h> #include<stdlib.h>定义函数 void perror(const char *s); perror ("open_port");函数说明 perror ( )用 来 将 上 一 个 函 数 发 生 错 误 的 原 因 输 出 到标 准 错误 (stderr) 。参数 s 所指的字符…

DeepMind 打造 AI 游戏系统,可以玩扑克、国际象棋、围棋等,战斗力爆表

编译 | 禾木木 出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09; 谷歌母公司 Alphabet 的人工智能实验室 DeepMind 长期以来一直投资于游戏人工智能系统。实验室的理念是&#xff0c;游戏虽然缺乏明显的商业应用&#xff0c;但却是认知和推理能力的独特相关挑战。这使…