hibernate复习第(一)天
首先导入jar。
这个版本是3.2.5
开发流程:
1、由Domain object ->mapping ->db (官方推荐)
2、由DB开始,使用工具生成mapping和Domain object。(常用)
3、由映射文件开始
hibernate的bean的要求:
1、有一个缺省的构造,也就是无参构造
2、有一个id属性,对应数据库的主键。(可选)
3、非final的类。对懒加载影响(可选)
mapping映射文件。模板可以从hibernate下载文件的eq文件夹下的子文件夹中找到:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping
package="cn.itcast.hibernate.domain"> <class name="User">
<id name="id" >
<generator class="native"/>
</id> <property name="name"/>
<property name="birthday"/>
</class> </hibernate-mapping>
class,对应java类,name对应类名,和package的属性组合得到类的地址
<class name="User" table="user">可以有一个table属性,对应数据库表名,不写表示默认与类名相同
<id name="id" column="id">可以有一个column属性,对应数据表中的列名,不写默认与类名相同
<generator >表示以何种方式生成主键
<property name="name" column="">属性,name对应java类的字段,column对应数据表的列名,也是可省略。如果对应的列名是唯一的的话,可以在<property 中加上unique="true"/>
注意:这里的hibernate映射文件就是用于说明java对象与哪个表中的记录相对应,以及java对象中的各个属性分别对应表中的哪一项,不同性质的属性(例如,主键和普通属性)用不同的标签来映射,如果java对象中的某个属性不需要存储在数据库中,那么在hibernate映射文件中就不需要配置这个属性。
两个问题:
关于使用表名和字段与关键字冲突的问题。
如果表名和字段与关键字啊发生冲突,解决方案有两种:
使用column和table,改表名或字段名;
如果表名或者字段名不允许更改,可以在table或者column中字段前面加上符号"`",例如:<class name="User" column="`user`">.这个符号是键盘中~对应的那个键在英文状态下的符号
hibernate.cfg.xml配置文件记不住怎么办?
这个我们一般不记,在hibernate文件夹下的etc文件夹下有一个hibernate.properties文件夹,这里所有的配置信息都可以在这里查找得到
hibernate.cfg.xml文件:模板在 etc文件夹下面可以找到:
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/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://localhost:3306/demo</property>
<property name="hibernate.connection.username">guodaxia</property>
<property name="hibernate.connection.password">961012gz</property> <property name="hibernate.hbm2ddl.auto">create</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="show_sql">true</property> <mapping resource="cn/itcast/hibernate/domain/User.hbm.xml"/>
</session-factory>
</hibernate-configuration>
注意:
url中直接写jdbc:mysql:///demo表示地址是本机,端口是默认端口3306
5个必填属性:
url、驱动、用户名、密码、方言(方言主要是各个数据库分页语句不一样)
hibernate.hbm2ddl.auto属性:
4个可选值:
create-drop(创建和删除,启动时创建,使用后删除,一般在测试使用)
create(创建,启动时创建,使用后不删除,再次启动前删除后再创建,一般测试使用)
update(更新)
validate(检验映射文件与表是否对应,如果不对应报错不执行更新操作)
show_sql属性:是否显示执行的sql语句
<mapping resource=""/>映射文件的路径 hibernate如何操作数据库。
/*
* hibernate初始化的过程,这个过程一般只做一次
* 所以我们一般做一个工具类
*/
Configuration cfg=new Configuration();
cfg.configure();
SessionFactory sf=cfg.buildSessionFactory();
Session s=sf.openSession();
首先得到Configuration对象,使用该构造hibernate会自动加载classpath下面的hibernate.properties文件;
cfg.configuration();如果存在的话,hibernate自动加载classpath下的hibernate.cfg.xml配置文件。当然也可以加参数表示映射文件的文件路径和文件名,所以如果即写了hibernate.properties又写了hibernate.cfg.xml如果有相同属性配置,后者会覆盖前者。
创建sessionFactory工厂,这个类似于JDBC的DriverManager;
通过工厂创建session,session相当于JDBC中的Connection。
说明:
既然取读的是classpath下面的内容,为什么我们的配置文件都是放在src下面呢?这是因为myeclipes编译的时候会自动将src目录下的文件编译到classpath中去。
操作数据表:使用Session接口。
因为hibernate文件初始化比较耗费资源,我们一般书写一个工具类帮助处理:
package cn.itcast.hibernate; import java.io.Serializable; import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration; public final class HibernateUtil {
/*
* 设计成为单例,或者将所有的放射设计成为静态的
*/ private static SessionFactory sessionFactory;
private static ThreadLocal<Session> sessionThread;/* 使用threadLocal优化连接 */
private HibernateUtil(){
} static{
Configuration cfg=new Configuration();
cfg.configure();//从classPath里面读取配置文件。如果名字不是hibernate.cfg.xml的话需要特定指出,src下的文件会自动编译到classPath中
sessionFactory=cfg.buildSessionFactory();
sessionThread=new ThreadLocal<Session>();
} public static SessionFactory getSessionFactory(){
return sessionFactory;
} public static Session getSession(){
Session s=sessionThread.get();
if(s==null){
s=sessionFactory.openSession();
}else{
sessionThread.set(s);
}
return s;
}
}
java对象的几种状态:
对象状态
瞬时(transient):数据库中没有数据与之对应,超过作用域会被JVM垃圾回收器回收,一般是new出来的与session没有关联的对象
持久(persistent):数据库中有数据与之对应,当前与session有关联,并且相关联的session没有关闭,事务没有提交,持久对象状态发生改变,在事务提交时会影响到数据库(hibernate能检测到);
持久化状态的时候如果你修改了该对象会自动调用update方法。
脱管:数据库中有数据与之对应,当前session与之无关联。save等操作后的java类或者查询得到的java类都是这种状态。托管状态的对象修改后只能是自己调用update方法才能对数据库进行修改。
Session对象的一些常见方法:
Transaction beginTransaction();开启事务
get(Class,Serializable)根据主键获取一条数据
load(Class,Serializable)根据主键获取一条数据.具有懒加载特性。懒加载类似new一封User子类
save(Object).保存一条数据
persist(Object).保存一条数据。
save和persist的区别是:在没有开启事务的情况下,save方法会先插入数据再回滚,而persist方法不会插入记录也就不需要回滚
update(Object):将对象更新到数据库
saveOrUpdate(Object):hibernate自动检测对象是瞬时状态还是脱管状态,然后执行insert或者update语句
merge(Object):和saveOrUpdate类似,区别在saveOrUpdate方法操作之后会改变对象的状态,变成持久状态,而merge之后还是脱管状态
Session s=HibernateUtil.getSession();
User user=new User();
user.setName("zhangSan");
user.setBirthday(new Date());
s.save(user);
s.close();
上面的代码执行完之后,sql语句正常但是数据库中却没有任何记录。这是因为:
JDBC是自动提交的,但是hibernate的缺省将这个功能关闭,必须自己开启使用事务才会生效。事务的创建方式:
Transaction tx=session.beginTransaction();
如果不需要开启提交事务提交事务就可以操作数据库数据的话,注意一下你的表结构,看你的引擎
标准的操作数据库的结构:
static void addUser(User user){//比较规范的hibernate的一个写法
Session s=null;
Transaction tx=null;
try{
s=HibernateUtil.getSession();;
tx=s.beginTransaction();
s.save(user);
user.setName("new name");//这个user是持久状态
user.setBirthday(new Date());
tx.commit();
}catch(HibernateException e){
if(tx!=null) tx.rollback();
throw e;
}finally{
if(s!=null) s.close();
}
}
操作数据库的结构也可以写成这个样子:
static void addUser1(User user){//可以简写成为这个样子,因为hibernate接到异常会自动向外抛,如果数据库没有得到事务提交信号请求会自动回滚
Session s=null;
Transaction tx=null;
try{
s=HibernateUtil.getSession();;
tx=s.beginTransaction();
s.save(user);
tx.commit();
}finally{
if(s!=null) s.close();
}
}
基本操作的一些代码:
package cn.itcast.hibernate; import java.util.Date; import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test; import cn.itcast.hibernate.domain.User; public class Base { public static void main(String[] args) {
/*
* hibernate初始化的过程,这个过程一般只做一次
* 所以我们一般做一个工具类
*/
// Configuration cfg=new Configuration();
// cfg.configure();
// SessionFactory sf=cfg.buildSessionFactory();
// Session s=sf.openSession(); Session s=HibernateUtil.getSession();
//JDBC是自动提交的,但是hibernate的缺省将这个功能关闭,必须自己开启使用事务才会生效
//如果必须要开启提交事务就可以操作数据库数据的话,注意一下你的表结构,看你的引擎
User user=new User();
user.setName("zhangSan");
user.setBirthday(new Date()); // Transaction tx=s.beginTransaction();
// s.save(user);
// tx.commit();
// s.close();
// System.out.println("end");
addUser(user);
System.out.println("id:"+user.getId()); // User u=getUser(user.getId());
User u=(User) s.load(User.class, user.getId()); System.out.println("name:"+u.getName()); } static void addUser(User user){//比较规范的hibernate的一个写法
Session s=null;
Transaction tx=null;
try{
s=HibernateUtil.getSession();;
tx=s.beginTransaction();
s.save(user);
// s.persist(user);
user.setName("new name");//这个user是持久状态
user.setBirthday(new Date());
tx.commit();
}catch(HibernateException e){
if(tx!=null) tx.rollback();
throw e;
}finally{
if(s!=null) s.close();
}
} static void addUser1(User user){//可以简写成为这个样子,接到异常自动向外抛,如果数据库没有得到提交请求会自动回滚
Session s=null;
Transaction tx=null;
try{
s=HibernateUtil.getSession();;
tx=s.beginTransaction();
s.save(user);
tx.commit();
}finally{
if(s!=null) s.close();
}
} @Test
public void fun1(){
System.out.println(getUser(1));
}
public static User getUser(int id){
Session s=null;
User user=null;
try{
s=HibernateUtil.getSession();
user=(User) s.get(User.class, 1);
// user=(User) s.load(User.class,1);//这里会报错
}finally{
if(s!=null) s.close();
}
return user;
} }
public static void add(Object entity){
Session s=null;
Transaction tx=null;
try{
s=getSession();
tx=s.beginTransaction();
s.save(entity);
tx.commit();
}catch(HibernateException e){
tx.rollback();
throw e;
}finally{
if(s!=null) s.close();
}
} public static void delete(Object entity){
Session s=null;
Transaction tx=null;
try{
s=getSession();
tx=s.beginTransaction();
s.delete(entity);
tx.commit();
}catch(HibernateException e){
tx.rollback();
throw e;
}finally{
if(s!=null) s.close();
}
} public static void update(Object entity){
Session s=null;
Transaction tx=null;
try{
s=getSession();
tx=s.beginTransaction();
s.update(entity);
tx.commit();
}catch(HibernateException e){
tx.rollback();
throw e;
}finally{
if(s!=null) s.close();
}
} public static Object get(Class clazz,Serializable id){
Session s=null;
try{
s=getSession();
return s.get(clazz, id);
}catch(HibernateException e){
throw e;
}finally{
if(s!=null) s.close();
}
} public static Object load(Class clazz,Serializable id){
Session s=null;
try{
s=getSession();
return s.load(clazz, id);
}catch(HibernateException e){
throw e;
}finally{
if(s!=null) s.close();
}
}
关于load()和get()的区别:
两者都是根据类的字节码文件和ID得到一条数据。区别在于:
第一点是:没有记录的情况下,load会抛出异常,get会返回空,一般采用的load方法。
第二点是:get只返回实体对象实例。而load返回的是代理类实体对象实例。
第三点是:get方法只能使用一级缓存。而load可以使用一级和二级缓存。
第四点是:都是通过id得到单个对象的方法。
第五点:load方法具有懒加载的特性,不是立即操作数据库,而是返回一个代理对象,在操作该对象的属性的时候才操作数据库将信息填入。
关于save()和persist()的区别:
在不开启事务的情况下,save方法会先插入数据再回滚,而persist方法不会插入记录
update、saveOrUpdate、merge的区别见我的其他博客:
http://www.cnblogs.com/aigeileshei/p/5796788.html
前面学习了增删改和根据id进行查询。但是查询语句往往比较复杂,hibernate提供了两种方式进行数据库表的查询操作:HQL和Criteria
HQL:
面向对象的查询语言,与SQL不同,HQL中的对象名是区分大小写的(除了JAVA类和属性其他部分不区分大小写);HQL中查的是对象而不是表,而且支持多态;
HQL主要通过Query来操作,Query的创建方式:
Query q=session.createQuery(hql);
Query的主要方法:
list():将query对象中的结果集变成list集合
uniqueResult():将query对象中的结果集变成一个Object对象,当结果集中对象数>1的时候会报异常
setXxx()和getXxx()方法,类似于pstmt的getXxx和setXxx
setFirstResult(number);//设置query查询的结果从第多少条记录开始
setMaxResults(number);//查询的结果多少条。使用上面的和这个方法可以进行分页,而且不限制数据库。这个分页应该是根据方言hibernate封装的
HQL语句中占位符与命名参数的使用:
hql语句中占位符的使用:
String hql="from User as user where user.name=?";
Query query=s.createQuery(hql);
query.setString(0,name);
这里注意,下标是从0开始的。
命名参数的使用:
单纯的占位符使用不是很方便,因为每一个?与数据都需要一一对应。hibernate提供了命名参数。
String hql="from User as user where user.name=:n";
Query query=s.createQuery(hql);
query.setString("n"name);
同一个命名参数可以多次使用
命名参数在hql中=:命名参数名。格式注意正确。
将命名参数设置进Query中们可以使用后Map结合如果参数过多的话,这样比较简便一些:
static void qr(){
Session s=HibernateUtil.getSession();
String hql="from User where name=:name and age>:bj and (age-:bj)>0";
Query query=s.createQuery(hql);
Map <String,Object> params=new HashMap<String,Object>();
params.put("name", "guodaxia");
params.put("bj",);
query.setProperties(params); List<User> users=query.list();
}
hql查询的简单例子:
package cn.itcast.hibernate; import java.util.Date;
import java.util.Iterator;
import java.util.List; import org.hibernate.Query;
import org.hibernate.Session; import cn.itcast.hibernate.domain.User; public class QueryTest {
public static void main(String[] args) {
User user=new User();
user.setBirthday(new Date());
user.setName("name");
HibernateUtil.add(user); System.out.println(query("name"));
} static User query(String name){
Session s=null;
try{
s=HibernateUtil.getSession();
// String hql="from User as user where user.name=?";
String hql="from User as user where user.name=:n";
Query query=s.createQuery(hql);
// query.setString(0, name);//下标从0开始
query.setString("n", name); //设置结果集的范围,可用来分页
query.setFirstResult(200);
query.setMaxResults(10); List<User> list=query.list();//executeQuery()
User user=(User) query.uniqueResult();
// for(Iterator<User> it=list.iterator();it.hasNext();){
// User user=it.next();
// list.add(user);
//// System.out.println(user);
// }
// return list.get(0);
return user;
}finally{
if(s!=null) s.close();
}
}
}
Criteria(条件查询):
是一种比hql更加面向对象的一种方式。
创建方式:
Criteria crit=session.createCriteria(User.class);
条件查询关于条件的添加与query不一样,在处理结果集方面与query基本一致。
简单属性条件如:
criteria.add(Restrictions.eq(propertyName,value)),
criteria.add(Restrictions.eqProperty(propertyName,otherPropertyName))
Restrictions对象中封装了许多条件查询的增加条件的方法。可以配合API使用
Criteria查询的小例子:
package cn.itcast.hibernate; import java.util.Date;
import java.util.List; import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions; import cn.itcast.hibernate.domain.User; public class Cri {
public static void main(String[] args) {
cri("name");
} static void cri(String name){
Session s=null;
try{
s=HibernateUtil.getSession();
Criteria c=s.createCriteria(User.class);//条件查询,很面向对象的方式。这个接口相当于一个容器
c.add(Restrictions.eq("name", name));//添加约束条件
c.add(Restrictions.lt("birthday", new Date())); c.setFirstResult(0);
c.setMaxResults(10);
List<User> list=c.list(); User u=(User)c.uniqueResult();
System.out.println(u); for(User user:list){
System.out.println(user.getName());
}
}finally{
if(s!=null) s.close();
}
}
}
hibernate复习第(一)天的更多相关文章
- Hibernate复习之Hibernate基本介绍
众所周知.眼下流行的面向对象的对象关系映射的Java持久层框架有MyBatis和Hibernate.他们都是对象关系映射ORM. 解决的主要问题就是对象-关系的映射.域模型和关系模型都分别建立在概念模 ...
- Hibernate复习
第一天 Hibernate是一个持久层的ORM框架.两个配置文件, 类名.hbm.xml类的属性和表的列对应 hibernate.cfg.xml核心配置文件 Hibernate相关API: Confi ...
- hibernate复习第(4)天
1.hibernate的映射类型.hbm.xml中property中的type属性.这个type属性是表示持久化类中的属性对应数据库中的什么数据类型,用来构建一种映射type的可选值:hibernat ...
- hibernate复习第(三)天
今日要点: 1.继承关系映射 一个表对应一个映射树(subclass) 一个子类一个表,子类只有父类没有的字段(joined-subclass) 鉴别器和内连接结合使用(subclass join) ...
- hibernate复习第(二)天
今日要点: 关联映射 多对一(Employee - Department) 一对多(Department - Employee) 一对一(Person - IdCard) 多对多(teachet - ...
- HIBERNATE知识复习记录4-HQL和QBC
Hibernate中共提供了三种检索方式:HQL(Hibernate Query Language).QBC.QBE(Query By Example). HQL 是Hibernate Query L ...
- HIBERNATE知识复习记录3-关联关系
先上一张图,关于几种关系映射: 抄一段解释: 基本映射是对一个实体进行映射,关联映射就是处理多个实体之间的关系,将关联关系映射到数据库中,所谓的关联关系在对象模型中有一个或多个引用.关联关系分为上述七 ...
- HIBERNATE知识复习记录1-连接及常用方法
要去面试了,复习一下HIBERNATE的相关知识吧,原来边看视频边写的代码如下,已经分不清先后次序了,大致看一看吧. 先看下总的配置文件hibernate.cfg.xml: <?xml vers ...
- Hibernate 知识点复习
核心接口 1 Configuration接口负责配置并启动Hibernate,创建SessionFactory对象 2 SessionFactory接口负责初始化Hibernate.它充当数据存储 ...
随机推荐
- staitic_cast原理与使用
本文以下述结构为例: 总结如下: 1) static_cast用于有直接或间接关系的指针或引用之间 转换.没有继承关系的指针不能用此转换,即使二者位于同一类体系中.比如,Left,Right之间不能用 ...
- ubuntu 1204 安装mysql
检測本机是否有安装mysql sudo netstat -tap | grep mysql 运行上面的命令之后.看到 mysq 的socket 处于监听状态,说明有成功安装. 安装mysql sudo ...
- WPF编程学习——样式(好文)
http://www.cnblogs.com/libaoheng/archive/2011/11/20/2255963.html
- win10中如何成功安装lxml
lxml官网地址:http://lxml.de/index.html 问题: 在学习lxm的时候,发现在win10下总是安装失败,如下: 在网上搜索了半天也没找到具体的解决方案,就FQgoogle下, ...
- spring 事务传播行为类型
事务传播行为种类 Spring在TransactionDefinition接口中规定了7种类型的事务传播行为, 它们规定了事务方法和事务方法发生嵌套调用时事务如何进行传播: 事务传播行为类型 说明 P ...
- poj3708(公式化简+大数进制装换+线性同余方程组)
刚看到这个题目,有点被吓到,毕竟自己这么弱. 分析了很久,然后发现m,k都可以唯一的用d进制表示.也就是用一个ai,和很多个bi唯一构成. 这点就是解题的关键了. 之后可以发现每次调用函数f(x),相 ...
- 2820: YY的GCD
2820: YY的GCD Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 1693 Solved: 901[Submit][Status][Discu ...
- Java中List.remove报UnsupportedOperationException异常
今天项目中有个需求场景: A和B都是List,而B是A的子集,现在想求A和B的差集. 想到了List中提供的removeAll()方法可以求得差集,但是结果确报了UnsupportedOperatio ...
- python解释器安装教程
1. 首先,打开python的官网:python.org 2. 首页downloads下打开, 3. 最上边是两个最新的版本,长期计划,推荐使用python3,如果长期打算用p3,默认使用最新版本.如 ...
- hibernate 多对多 懒加载问题
报错:org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: net. ...