Hibernate--初级
来源:互联网 发布:tv是哪里的域名 编辑:程序博客网 时间:2024/05/13 10:52
2017.2.6-2017.2.9
javaee三层结构
- web层:struts2框架
- service层:Spring框架
dao层:hibernate框架
对数据库进行CURD
什么是hibernate框架
- hibernate框架应用于Javaee三层结构中的dao层框架
- 在dao层里面做对数据库crud操作,使用hibernate实现crud操作,hibernate底层代码就是jdbc,hibernate对jdbc进行封装,使用hibernate好处,不需要写复杂jdbc代码了,不需要写sql语句实现
- hibernate是开源的轻量级框架
hibernate版本
- hibernate3.x
- hibernate4.x
- hibernate5.x
什么是orm思想
- hibernate使用orm思想对数据库进行crud操作
- 在web阶段学习javabean,更正确的叫法–实体类
- orm:object relational mapping,对象关系映射
- 让实体类和数据库表进行一一对应
- 不需要直接操作数据库表,而操作表对应的实体类对象
第一个应用
引入jar包
- 引入require文件下的所有jar包
- 引入jpa-metamodel-generator文件夹下的jar包
- 引入MySQL驱动jar包
引入日志jar包
log4j-version.jarlog4j-api-version.jarslf4j-log4j12-version.jar
创建实体类
使用hibernate不许自己手动创建表,hibernate会自动创建
配置实体类和数据库表一一对应关系(映射关系)
创建想xml格式的配置文件
配置文件的路径和名称没有固定要求建议:在实体类所在包里面创建,名称:实体类名称.hbm.xml
配置是xml格式,在配置文件中首先引入xml约束(dtd、schema,hibernate里都为dtd约束)
<?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> <!-- 1。配置类和表对应 class标签 name属性:实体类全路径 table属性:数据表名称 --> <class name="zcw.entity.User" table="user"> <!-- 2.配置实体类id和表id对应 hibernate要求实体类有一个属性唯一值 hibernate要求表有字段作为唯一值 --> <!-- 3.id标签 name属性:实体类里面id属性名称 column属性:生成的表字段名称 --> <id name="id" column="id"> <!-- 4.设置数据表id增长策略 native:生成表id值为主键自动增长 --> <generator class="native"></generator> </id> <!-- 5.配置其他属性和表字段对应 name属性:实体类属性名称 column属性:生成表字段名称 --> <property name="username" column="username"></property> <property name="password" column="password"></property> <property name="address" column="address"></property> </class></hibernate-mapping>
配置hibernate核心配置文件
<?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> <!-- 第一部分:配置数据库信息 --> <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <property name="hibernate.connection.url">jdbc:mysql:///hibernate</property> <property name="hibernate.connection.username">root</property> <property name="hibernate.connection.password">951029</property> <!-- 第二部分:配合hibernate信息 --> <!-- 输出底层SQL语句 --> <property name="hibernate.show_sql">true</property> <!-- 输出低层SQL语句格式 --> <property name="hibernate.format_sql">true</property> <!-- hibernate自动创建表 update:如果已经有表,更新,如果没有,创建 --> <property name="hibernate.hbm2ddl.auto">update</property> <!-- 配置数据库方言 在mysql里面实现分页,关键字limit,只是mysql独有 在oracle数据库,实现分页rownum 让hibernate框架识别不同数据库自己特有的语句 --> <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> <!-- 第三部分:在映射文件放到核心配置文件中 --> <mapping resource="zcw/entity/User.hbm.xml"/> </session-factory></hibernate-configuration>
添加操作
- 加载hibernate核心配置文件
- 创建SessionFactory对象
- 使用SessionFactory创建Session
- 开启事务
- 写具体逻辑crud
- 提交事务
关闭资源
package test;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.hibernate.Transaction;import org.hibernate.cfg.Configuration;import org.junit.Test;import zcw.entity.User;public class addtest { @Test public void add(){ //第一步 加载hibernate核心配置文件 Configuration cfg=new Configuration(); cfg.configure(); //第二步 创建SessionFactory对象 //读取hibernate核心配置文件内容,创建sessionfactory SessionFactory sessionFactory=cfg.buildSessionFactory(); //第三步 使用SessionFactory对象创建session对象 Session session=sessionFactory.openSession(); //第四步 开启事务 Transaction ts=session.beginTransaction(); //第五步 写具体逻辑crud操作 User user=new User(); user.setUsername("张三"); user.setPassword("666"); user.setAddress("福建"); //调用session方法实现添加 session.save(user); //第六步 提交事务 ts.commit(); //第七步 关闭资源 session.close(); sessionFactory.close(); }}
配置文件详解
- 映射配置文件
- 文件名和位置没有固定要求
- class标签name属性值为类全路径
- id标签和property标签name属性值为实体类属性名称
- id标签和property标签,column可以省略
- property标签type属性,设置生成表字段的类型。hibernate会自动设置类型
- 核心配置文件
- 配置位置要求,在
session-factory
标签内 - 配置三部分
- 数据库部分–必须
- hibernate部分–可选
- 映射文件–必须
-核心配置文件名称(hibernate.cfg.xml)和位置(src下)固定
- 配置位置要求,在
hibernate核心API
Configuration
Configuration cfg=new Configuration();cfg.configure();
到src目录下面找到名称为hibernate.cfg.xml配置文件,创建对象,把配置文件放到对象里面(加载核心配置文件)
SessionFactory(重点)
使用configuration对象创建SessionFactory对象,创建SessionFactory过程中做的事:
根据核心配置文件中,有数据库配置,有映射文件部分,到数据库里面根据映射关系把表创建
创建SessionFactory过程非常消耗资源
在hibernate操作中,建一个项目一般只创建一个SessionFactory对象
实现
静态代码块只在类加载是后执行,执行一次。
static Configuration cfg=null;static SessionFactory sessionFactory=null;//静态代码块实现static{ //加载核心配置文件 cfg=new Configuration(); cfg.configure(); sessionFactory=cfg.buildSessionFactory();}//提供返回sessionFactory的方法public static SessionFactory getSessionFactory(){ return sessionFactory;}
Session(重点)
- session类似与jdbc中connection
- 调用session里面不同的方法实现crud操作
- 添加–save()
- 修改–update()
- 删除–delete()
- 根据id查询–get()
session对象是单线程对象
session对象不能共用,只能自己使用
Transaction
事务对象
Transaction ts=session.beginTransaction();
- 事务提交和回滚
- commit()
- rollback()
- 事务的四个特性
- 原子性
- 一致性
- 隔离性
- 持久性
实体类编写规则
- 属性私有
- get、set方法公有
- 要求实体类有属性作为唯一值(id)
实体类属性建议不使用基本数据类型,建议使用基本数据类型对应的包装类
- int-Integer
- char-Character
- 其他的都是首字母大写,比如 double-Double
因为有时候基本数据类型表达的不够准确,如:int score=0,但是它不能表示学生没来考试,而Integer=null则可以表示
hibernate主键生成策略
- native:根据使用的数据库来选择生成策略
uuid:hibernate自动生成UUID值
id的数据类型一定要为字符串类型
根据id获取数据
核心代码
// session的get方法有两个参数// 第一个:实体类的class// 第二个:id值User user=session.get(User.class, 1);System.out.println(user);
修改操作
- 首先获取数据
修改
Transaction ts=session.beginTransaction();// session的get方法有两个参数// 第一个:实体类的class// 第二个:id值User user=session.get(User.class, 1);System.out.println(user);user.setUsername("666");user.setPassword("111");session.update(user);ts.commit();
删除操作
- 先查找出来,再删除
创建实体类对象,再删除
/*//第一种:先查找,后删除User user=session.get(User.class, 1);session.delete(user);*///第二种:先创建,后删除User user=new User();user.setId(2);session.delete(user);
实体类对象状态(概念)
瞬时态:对象里面没有id,对象与session没有关联
User user=new User();user.setUsername("zcw");
持久态:对象有id值,对象与session关联
User user=session.get(User.class,1);
托管态:对象有id值,对象与session没有关联
User user=new User();user.setId(1);
saveOrUpdate
- 执行save操作:当实体类对象为瞬时态时
- 执行update操作:当实体类对象为托管态或持久态时
Hibernate的一级缓存
- 默认是打开状态
- 作用范围:从session创建到session关闭
- 缓存存储的数据为持久态数据
是一种优化技术
Hibernate二级缓存
- 目前已经不使用了,替代技术redis
- 默认不打开
- 作用范围:SessionFactory范围
验证一级缓存
- 首先根据id=1查询
- 再查询id=1
- 看是否有两个sql日志输出
一级缓存执行过程
持久态会自动更新数据库
User user=session(User.class,1);user.setUsername("q");ts.commit();
就算没有提交,也会完成更新
Hibernate事务规范写法
SessionFactory sessionFactory = null; Session session = null; Transaction ts = null; try { sessionFactory = GetSessionFactory.getSessionFactory(); session = sessionFactory.openSession(); ts = session.beginTransaction(); User user = session.get(User.class, 1); System.out.println(user); ts.commit(); } catch (Exception e) { e.printStackTrace(); ts.rollback(); } finally { session.close(); sessionFactory.close(); }
Hibernate绑定Session
为了确保session为单线程
配置hibernate.cfg.xml文件
<property name="hibernate.current_session_context_class">thread</property>
调用SessionFactory得到
return sessionFactory.getCurrentSession();
- 获取与本地线程绑定session的时候,不需要手动关闭
Query对象查询所有记录
使用query对象需要写HQL语句,语法格式:from 实体类名称
- 创建Query对象
调用query对象里面的方法得到结果
Query query=session.createQuery("from User"); List<User> list=query.list(); for(User user:list){ System.out.println(user); }
Criteria对象查询数据
这个方法无需写sql语句
- 创建Criteria对象
调用对象里面的方法得到结果
//createCriteria方法的参数为实体类class Criteria criteria=session.createCriteria(User.class); List<User>list=criteria.list(); for(User user:list){ System.out.println(user); }
SQLQuery对象查询数据
使用sql语句
- 创建SQLQuery对象
调用方法得到结果集
SQLQuery sqlQuery=session.createSQLQuery("select * from user"); List<Object[]> list=sqlQuery.list(); for(Object[] object:list){ System.out.println(Arrays.toString(object)); }
默认的得到的是数组集合,下面的方法将结果集变为封装到User实体中
SQLQuery sqlQuery=session.createSQLQuery("select * from user"); sqlQuery.addEntity(User.class); List<User>list=sqlQuery.list(); for(User user:list){ System.out.println(user); }
hibernate一对多配置
客户–联系人,客户就是公司(一),联系人就是职工(多)。
外键在多的一方
创建实体类
用户
private Integer cid;private String cname;private String clevel;private String csource;private String cphone;private String cmobile;......get、set方法
联系人
private Integer lkm_id;private String lkm_name;private String lkm_gender;private String lkm_phone;
让两个实体类互相表示
在客户实体类里面表示多个联系人
private Set<LinkMan> setLinkMan=new HashSet<LinkMan>();public Set<LinkMan> getSetLinkMan() { return setLinkMan;}public void setSetLinkMan(Set<LinkMan> setLinkMan) { this.setLinkMan = setLinkMan;}
在联系人实体类里面表示所属客户
private Client client;public Client getClient() { return client;}public void setClient(Client client) { this.client = client;}
配置映射关系
- 一个实体类对应一个映射配置文件
配置基本映射文件
Client.hbm.xml映射文件
<class name="zcw.entity.Client" table="client"> <id name="cid" column="id"> <generator class="native"></generator> </id> <property name="cname" column="cname"></property> <property name="clevel" column="clevel"></property> <property name="csource" column="csource"></property> <property name="cphone" column="cphone"></property> <property name="cmobile" column="cmobile"></property></class>
LinkMan.hbm.xml映射文件
<class name="zcw.entity.LinkMan" table="linkMan"> <id name="lkm_id" column="id"> <generator class="native"></generator> </id> <property name="lkm_name" column="lkm_name"></property> <property name="lkm_gender" column="lkm_gender"></property> <property name="lkm_phone" column="lkm_phone"></property></class>
在映射文件中,配置一对多关系
Client.hbm.xml
<!-- 在客户映射文件中,表示所有联系人 使用set标签表示所有联系人 set标签里面有name属性,属性值为联系人set集合名称 --> <set name="setLinkMan"> <!-- 一对多建表,有外键 hibernate机制:双向维护外键,在一和多一方都配置外键 column属性值:外键名称 --> <key column="clid"></key> <!-- 客户所有的联系人,class里面写联系人实体类全路径 --> <one-to-many class="zcw.entity.LinkMan"/> </set>
LinkMan.hbm.xml
<!-- 表示联系人所属客户 name属性:应为联系人实体类中使用client对象表示,所以写client class属性:Client类的全路径 column属性:外键名称 --> <many-to-one name="client" class="zcw.entity.Client" column="clid"></many-to-one>
创建核心配置文件,把映射文件引入到核心配置文件中
<mapping resource="zcw/entity/Client.hbm.xml"/><mapping resource="zcw/entity/LinkMan.hbm.xml"/>
- 测试。成功创建了client和lingkman表
Hibernate一对多级联操作
- 创建客户和联系人对象
- 建立客户对象和联系人对象的关系
- 保存到数据库
复杂写法:
ts = session.beginTransaction(); //添加一个客户,为这个客户添加一个联系人 //1.创建客户和联系人对象 Client client=new Client(); client.setCname("baidu"); client.setClevel("vip"); client.setCsource("internet"); client.setCphone("110"); client.setCmobile("111"); LinkMan linkMan=new LinkMan(); linkMan.setLkm_name("zcw"); linkMan.setLkm_gender("male"); linkMan.setLkm_phone("177"); //2.建立客户对象和联系人对象关系 //2.1将联系人对象放到客户对象的set集合里 client.getSetLinkMan().add(linkMan); //2.2把客户对象放到联系人里 linkMan.setClient(client); //3.保存到数据库 session.save(client); session.save(linkMan); //提交事务 ts.commit();
简单写法
在Client.hbm.xml文件的set标签写上cascade属性
<set name="setLinkMan" cascade="save-update">
java操作代码中
- 不需将客户对象放到联系人中
不需保存LinkMan对象
ts = session.beginTransaction();//添加一个客户,为这个客户添加一个联系人//1.创建客户和联系人对象Client client=new Client();client.setCname("baidu");client.setClevel("vip");client.setCsource("internet");client.setCphone("110");client.setCmobile("111");LinkMan linkMan=new LinkMan();linkMan.setLkm_name("zcw");linkMan.setLkm_gender("male");linkMan.setLkm_phone("177");//2.建立客户对象和联系人对象关系//2.1将联系人对象放到客户对象的set集合里client.getSetLinkMan().add(linkMan);//3.保存到数据库session.save(client);//提交事务ts.commit();
一对多级联删除
将客户和对应的联系人删除
配置Client.hbm.xml文件的set标签
<set name="setLinkMan" cascade="save-update,delete">
删除客户
Client client=session.get(Client.class,2);session.delete(client);
一对多联级修改
//1.根据id查询联系人,根据id查询用户Client client=session.get(Client.class, 1);LinkMan linkman=session.get(LinkMan.class, 3);//把联系人放到客户client.getSetLinkMan().add(linkman) ;//把客户放到联系人里面linkman.setClient(client);
inverse属性
?因为Hibernate双向维护外键,在客户和联系人里面都需要维护外键,修改联系人的时候,首先更新联系人,再更改外键。造成效率问题
解决方法:让client方放弃外键维护。
<set name="setLinkMan" cascade="save-update,delete" inverse="true">
hibernate多对多配置
用户–角色,小张可以是总经理、农民、司机。
另外建一张表,包含两张表的外键
创建两个实体类
User
private Integer id;private String username;private String password;
Rolle
private Integer id;private String name;private String desc;
配置两个实体类的关系
User
private Set<Role> setRole=new HashSet<Role>();public Set<Role> getSetRole() { return setRole;}public void setSetRole(Set<Role> setRole) { this.setRole = setRole;}
Role
private Set<User> setUser=new HashSet<User>();public Set<User> getSetUser() { return setUser;}public void setSetUser(Set<User> setUser) { this.setUser = setUser;}
配置文件
- 基本配置
配置多对多关系
User.hbm.xml
<!-- 用户表里表示所有角色,使用set标签 name属性:角色set集合名称 table:第三表名称 --> <set name="setRole" table="user_role"> <!-- key标签里面配置当前映射文件在第三张表外键名称 --> <key column="userid"></key> <!-- class:角色实体类全路径 column:角色在第三张表外键名称 --> <many-to-many class="zcw.manytomany.Role" column="roleid"></many-to-many> </set>
Role.hbm.xml
<set name="setUser" table="user_role"> <!-- key标签里面配置当前映射文件在第三张表外键名称 --> <key column="roleid"></key> <!-- class:角色实体类全路径 column:角色在第三张表外键名称 --> <many-to-many class="zcw.manytomany.User" column="userid"></many-to-many> </set>
- 在主配置文件中引入映射文件
测试
在User.hbm.xml的set标签写上cascade属性
<set name="setRole" table="user_role" cascade="save-update">
写java代码
//创建user、role实体对象User user1=new User();User user2=new User();user1.setUsername("张三");user1.setPassword("666");user2.setUsername("李四");user2.setPassword("666");Role role1=new Role();Role role2=new Role();Role role3=new Role();role1.setName("项目经理");role1.setDesc("项目经理");role2.setName("餐厅老板");role2.setDesc("餐厅老板");role2.setName("代码高手");role2.setDesc("代码高手");//建立关系user1.getSetRole().add(role1);user1.getSetRole().add(role2);user1.getSetRole().add(role3);user2.getSetRole().add(role1);user2.getSetRole().add(role3);session.save(user1);session.save(user2);
测试
多对多删除(一般不用)
在User.hbm.xml的set标签设置cascade属性
<set name="setRole" table="user_role" cascade="save-update,delete">
删除操作
User user=session.get(User.class, 5);session.delete(user);
第三张表的维护
让用户拥有某个角色
//让用户2拥有角色3//1.获得User和RoleUser user=session.get(User.class, 2);Role role=session.get(Role.class,3)//2.向user中加入roleuser.getSetRole().add(role);
让用户没有某个角色
//让用户2失去角色2//1.获得User和RoleUser user=session.get(User.class, 2);Role role=session.get(Role.class,2);//2.向user中移除roleuser.getSetRole().remove(role);
Hibernate查询方式
对象导航查询
根据id查询某个客户,再查询这个客户里面所有的联系人
OID查询
根据id查询某一条记录,返回对象
hql查询
Query对象,写hql语句实现查询
QBC查询
Criteria对象
本地查询
SQLQuery对象,实现普通sql实现查询
对象导航查询
Client client = session.get(Client.class, 1);Set<LinkMan> list=client.getSetLinkMan();System.out.println(list.size());
OID查询
Client client = session.get(Client.class, 1);
HQL查询
- HQL:Hibernate Query Language,Hibernate提供一种查询语言,hql语言与普通SQL很相似,区别:普通SQL操作数据库表和字段,hql操作实体类和属性。
常用hql语句
- 查询所有:
from 实体类对象
条件查询:
from 实体类名称 where 实体类属性名称=? and 实体类属性名称 like ?
Query query=session.createQuery("from User where id=?");query.setParameter(0, 1);List<User> list=query.list();for(User user:list){ System.out.println(user.getPassword());}
排序查询:from 实体类名称 order by 实体类属性名称 asc/desc
分页查询
//查询记录Query query=session.createQuery("from LinkMan");//设置开始位置query.setFirstResult(0);//设置每页的记录数query.setMaxResults(3);List<LinkMan> list=query.list();
- 投影查询(查询部分字段值):
select 实体类属性名称,实体类属性名称 from 实体类
不支持*号 - 聚集函数使用:
select count(*) from 实体类名称
- count,max,min,sum,avg
- 查询所有:
QBC查询
查询所有
- 创建Criteria对象
得到结果集
Criteria criteria=session.createCriteria(User.class);List<User>list=criteria.list();
条件查询
//创建criteria对象Criteria criteria=session.createCriteria(LinkMan.class);//添加条件criteria.add(Restrictions.eqOrIsNull("lkm_gender", "female"));criteria.add(Restrictions.like("lkm_name", "%h%"));List<LinkMan> list=criteria.list();
排序查询
Criteria criteria=session.createCriteria(LinkMan.class);//设置对那个属性进行排序,设置排序规则criteria.addOrder(Order.desc("id"));//criteria.addOrder(Order.asc("id"));
分页查询
//创建对象Criteria criteria=session.createCriteria(LinkMan.class);//设置开始位置criteria.setFirstResult(0);//设置每页的记录数criteria.setMaxResults(3);
统计查询
//创建对象Criteria criteria=session.createCriteria//设置操作criteria.setProjection(Projections.rowCount());//调用方法得到结果Object obj=criteria.uniqueResult();Long l=(Long)obj;int count=l.intValue();
离线查询(不使用session)
DetachedCriteria detachedCriteria=DetachedCriteria.forClass(LinkMan.class);//最终执行时才需要用到sessionCriteria criteria=detachedCriteria.getExecutableCriteria(sesion);List<LinkMan> list=criteria.list();
HQL多表查询
内连接
select * from user u,role r where u.id=r.id;或select * from user u INNER JOIN role r ON u.id=r.id;
左外连接
select * from user r LEFT OUTER JOIN role r ON u.id=r.id;
右外连接
select * from user r RIGHT OUTER JOIN role r ON u.id=r.id;
HQL内连接
from Client c inner join c.setLinkMan
Query query=session.createQuery("from Client c inner join c.setLinkMan");//返回的list每部分都是数组形式List list=query.list();
- 迫切内连接(返回的是对象):from Client c inner join fetch c.setLinkMan
HQL左外连接
- from Client c left outer join c.setLinkMan
- 迫切左外连接:from Client c left outer join fetch c.setLinkMan
HQL右外连接
from Client c right outer join c.setLinkMan
hibernate检索策略(2种)
立即查询:根据id查询,调用get方法,一调用get方法马上发出语句查询数据库
User user=session.get(User.class,1);
延迟查询:根据id查询,还有load方法,调用load方法不会马上发送语句查询数据,只有得到对象里面的值的时候才会发送语句查询数据库
User user=session.load(User.class,1);
延迟查询(2种)
- 类级别延迟:根据id查询返回实体类对象,调用load方法不会马上发送语句
关联级别延迟:查询某个客户,再查询这个客户的所有联系人,查询客户的所有联系人的过程是否需要延迟,这个过程称为关联级别延迟。
在客户映射文件中进行配置,在set标签上使用属性(1)fetch:select(默认)(2)lazy:TRUE延迟(默认)/false不延迟/extra极其延迟
极其延迟就是你调用什么就发送什么语句
批量抓取
应用场景:查询所有的客户,返回list集合,遍历list集合,得到每个客户,得到每个客户的所有联系人
//创建criteria对象Criteria criteria=session.createCriteria(User.class);List<User> list=criteria.list();for(User u:list){ Set<Role> roles=u.getSetRole(); for(Role role:roles){ System.out.println(role.getName()); }}
上面的代码发送的sql语句太多次,可以配置客户的映射文件,在set标签中写上batch-size属性
<set name="setRole" table="user_role" batch-size="66">
值越大效率越高
- Hibernate--初级
- hibernate 初级
- hibernate 初级应用篇
- Hibernate+EhCache初级应用
- Hibernate初级摘要
- Hibernate初级入门
- hibernate 初级1
- hibernate 初级2
- hibernate 初级04
- Hibernate 初级入门
- Hibernate学习笔记初级
- Hibernate初级知识学习(1)
- Hibernate初级知识学习(2)
- Hibernate初级知识学习(3)
- Hibernate事务的初级知识
- 初学者想学Hibernate,初级基础教程
- Struts+Hibernate编程总结(初级篇)
- spring整合hibernate的初级使用
- poj3469(*最小割模型)
- localeCompare() 方法的使用
- can总线与usb总线比较,那个可靠?
- uvalive7271(A Math Problem) 数位dp
- Ubuntu和windows系统修复GRUB
- Hibernate--初级
- 开始写blog了
- P1200 [USACO1.1]你的飞碟在这儿Your Ride Is Here
- UVA 658 It's not a Bug, it's a Feature!(状压+隐式图+最短路)
- CI Weekly #13 - 用更 Geek 的方式配置你的 CI 工作流
- 写CRUD时jsp页面自动显示填充数据为空的问题(自己的蛋疼问题记录一下)
- C++实现图的广度优先遍历与深度优先遍历
- HDU - 1029----Ignatius and the Princess IV
- 应用打包签名出现Conversion to Dalvik format failed with error 1