您的位置:首页 > 其它

Hibernate(一)

2017-08-07 10:57 274 查看

orm

ORM(object/Relationship Mapping ):对象/关系 映射。

在程序中写大量SQL缺点

不同的数据库使用的SQL语法不同。
同样的功能在拨不通的数据库中有不同的实现方式。
程序过分依赖SQL对程序的移植及拓展,维护等带来很大的麻烦。

Hibernate

Hibernate是Java领域的一款开源ORM框架技术。
Hibernate对JDBC进行非常轻量级的对象封装

如何在eclipse上安装hibernate插件

首先hibernate tools 已经集成到了jboss tools中,所以百度jboss tools,下载相应的配置。需要注意的是选择下载的jboss的版本要和你的eclipse一致。
下载完成之后,打开eclipse,点击菜单help-install new software,然后安装的时候,可以在线或者离线安装。在线的话,在安装的时候填入该网址,如果离线点击artifacts,下载相应的



在完成上述的配置之后,点击next,选择第一个分组下hibernate tools,然后一路next,到结束。
在安装结束后,重启eclipse,点击new-other菜单,出现如下,即安装插件成功。



构建第一hibernate例子

导入工程相应的坐标,整个工程基于maven。
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.2.10.Final</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.41</version>
</dependency>

</dependencies>


配置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="connection.username">root</property>
<property name="connection.password">123456</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql:///hibernatetest?useUnicode=true&characterEncoding=UTF-8</property><!-- hibernatetest这个是你mysql上创建的数据库的名字,必须一致,不能无法连接 -->
<property name="dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property><!-- 数据库方言 -->
<property name="show_sql">true</property>
<property name="format_sql">true</property>
<property name="hbm2ddl.auto">create</property>
<!-- <mapping resource="com/example/test/hibernate/hibernatetest/Student.hbm.xml"/> -->

<mapping resource="Student.hbm.xml" /><!-- 加载关系映射文件 -->
</session-factory>
</hibernate-configuration>


创建持久类
package com.example.test.hibernate.hibernatetest;

import java.util.Date;

public class Student {
/* 1. 公共的类
* 2. 提供一个带参数的构造函数
* 3. 属性私有
* 4. 提供了set、get方法
*
* */
private String name;
private String address;
private String sex;
private int age;
private Date birthday;

public Student(String name, String address, String sex, int age, Date birthday) {
//super();
this.name = name;
this.address = address;
this.sex = sex;
this.age = age;
this.birthday = birthday;
}
public Student() {
//super();
// TODO Auto-generated constructor stub
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}

}


对象关系-对象映射
点击new一个后缀名为hbm.xml的文件,选择要关系映射的实体类class,hibernate为你自动生成。

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2017-8-3 16:29:01 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping>
<class name="com.example.test.hibernate.hibernatetest.Student" table="STUDENT">
<id name="name" type="java.lang.String">
<column name="NAME" />
<generator class="assigned" />
</id>
<property name="address" type="java.lang.String">
<column name="ADDRESS" />
</property>
<property name="sex" type="java.lang.String">
<column name="SEX" />
</property>
<property name="age" type="int">
<column name="AGE" />
</property>
<property name="birthday" type="java.util.Date">
<column name="BIRTHDAY" />
</property>
</class>
</hibernate-mapping>

基于hibernate api开发

package com.example.test.hibernate.hibernatetest;

import java.text.SimpleDateFormat;
import java.util.Date;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

/**
* Unit test for simple App.
*/

public class AppTest  {
private SessionFactory sessionFactory;
private Session session;
private Transaction transaction;

@Before
public void init() {
/*//创建配置对象
Configuration configuration = new Configuration().configure("hibernate.cfg.xml");
//创建服务注册对象
ServiceRegistry sr = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();
//创建你会话工厂
sessionFactory = configuration.buildSessionFactory(sr);
//会话对象
session = sessionFactory.openSession();
//开启事务
transaction = session.beginTransaction();*/
// ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().configure("com/example/test/hibernate/hibernatetest/hibernate.cfg.xml").build();
ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().configure().build();

//创建会话工厂对象
sessionFactory = new MetadataSources(serviceRegistry).buildMetadata().buildSessionFactory();
//会话对象
session = sessionFactory.openSession();
//开启事物
transaction = session.beginTransaction();

}
@After
public void destory() {
transaction.commit();
session.close();
sessionFactory.close();
}
@Test
public void testStudent() {
Student s = new Student("laoqiang", "来自星星adsad", "男sdada", 234,new Date());
session.save(s);
}

}


注意点和易错点:

在配置文件中加载对象映射文件,一定注意名字和你创建文件一致。
如果你的对象映射文件创建在某个包下,在配置文件需要写路径,具体看注释的一行,如果直接是src,就不需要,否则报错。
如果你的配置文件创建在某个包下,在加载配置文件需要写路径,具体看测试类的一行,如果直接是src,就不需要,否则报错。
在测试时,由于我使用是hibernate 5,加载代码是和之前不一样,需要注意。
使用hibernate操作数据库,需要提前创建数据库。
注意:MySQL5之后跟之前的方言是不同的,org.hibernate.dialect.MySQLDialect需改为org.hibernate.dialect.MySQL5Dialec。

hibernate常用配置



表结构生成结构:

create: 每次生成新的表结构,如果表存在,会先删除,在创建,然后添加记录。
update:  在原有表上进行更新,可以保留原有测试数据。
create-drop:先创建在删除。
vaildate:  原有表结构验证,现有表结构和原有的表结构不一致,就不会创建。

hibernate执行过程



执行过程:通过Configuration对象创建,来读取hibernate配置文件,然后创建SessionFactory,来读取对象映射文件,hibernate类似jdbc的Coonection,通过session 执行 操作数据库的,开启数据库的事务。最后关键相应的操作对象。

Session对象

不建议直接使用jdbc的connection操作数据库,session可以作为操作数据库的对象。

session与connection,是多对一关系
e93b
,每个session都有一个与之对应的connection,一个connection不同时刻可以提供多个session使用。

把对象保存在关系数据库中需要调用session的各种方法,如save、update、delete、createQuery。

获取session对象方式:

openSession
getCurrentSession
如果使用第二种需要配置:

<property name="hibernate.current_session_context_class">thread</property><!-- 本地事务 -->
<property name="hibernate.current_session_context_class">jta</property><!-- 全局事务 -->

openSession与getCurrentSession区别:

1.getCurrentSession在事务提交或者回滚之后会自动关闭,而openSession需要你手动关闭。如果使用openSession而没有手动关闭,多次之后会导致连接池溢出。

2. openSession每次创建新的session对象,getCurrentSession使用现有的session对象,getCurrentSession有点单例模式的。

Transaction事务

hibernate对数据库的操作都是封装在事务中,并且默认是非自动提交的方式。所以用session保存对象时,如果不开启事务,并且手工提交事务,对象并不会真正保存在数据库中。

如果你想让hibernate像jdbc那样自动提交事务,必须调用sessionn对象dowork(),获得jdbc的connection后,设置为自动提交事务模式。(不提倡这个方法)

Student s = new Student("laoqiang", "来自星星adsad", "男sdada", 234,new Date());
session.doWork(new Work() {

public void execute(Connection arg0) throws SQLException {
// TODO Auto-generated method stub
arg0.setAutoCommit(true);
}
});
session.save(s);
session.flush();

单一主键

由某一列充当主键。

生成策略:

assigned 由java应用程序负责(手工赋值)
native 由底层数据库自动生成标识符,如果是mysql就是increment,如果是oracle就是sequence。

注意点:

assigned注意:如果实体类中设置的主键id是基本类型int的话,则可以不用赋值,系统默认值为0;如是引用类型,则默认值为null,不赋值系统则报错。
native注意:系统会自动选择该数据库对应的自动增值方式,从1开始。如果是其他引用类型,不赋值会报错

hibernate基本类型



时间易错的数据类型



如果我们需要将时间输出的类型,变成上述,只需要将hbm.xml中时间的属性类型改成对应的hibernate的映射类型,而不是采用java.util.Date。

<property name="birthday" type="date">

hibernate对象类型



clob 大文本类型

blob 大二进制数据文件

在mysql是不支持标准的sql的clob类型,在mysql用text。

下面举了一个二进制文件保存到数据库,并且读的例子:

注意:添加实体类的属性,需要手动修改hbm.xml文件,删除后在生成。

File f = new File("c:" + File.separator + "test.png");//File.separator 相当于\
System.out.println(f.getAbsolutePath());
try {
InputStream in = new FileInputStream(f);
Blob image = Hibernate.getLobCreator(session).createBlob(in, in.available());// 创建blob对象
s.setPicture(image);

} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

session.save(s);
//从数据库读取
Student s1 = (Student) session.get(Student.class, "laoqiangsdasda");//根据数据库某条记录的主键,来获取该记录
Blob image = s1.getPicture();
try {
InputStream in = image.getBinaryStream();
File f = new File("c:" + File.separator + "test111111111.png");
OutputStream out = new FileOutputStream(f);
byte[] b = new byte[in.available()];
in.read(b);
out.write(b);
in.close();
out.close();

} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}

组件属性

实体类中的某个属性属于用户自定义的类的对象。

先申明一个自定义类,可以有自己的属性,申明和持久化类一致。

package com.example.test.hibernate.hibernatetest;

public class Address {
private String post;
private String number;

public String getPost() {
return post;
}

public void setPost(String post) {
this.post = post;
}

public String getNumber() {
return number;
}

public void setNumber(String number) {
this.number = number;
}

public Address(String post, String number) {
super();
this.post = post;
this.number = number;
}

public Address() {
super();
// TODO Auto-generated constructor stub
}

}


在另一个持久化类中引用上述的对象,并且提供set、get方法。

private Address adressdetail;
public Address getAdressdetail() {
return adressdetail;
}
public void setAdressdetail(Address adressdetail) {
this.adressdetail = adressdetail;
}


配置持久化类

<component name="adressdetail" class="com.example.test.hibernate.hibernatetest.Address">
<property name="post" column="POST"/>
<property name="number" column="NUMBER"/>
</component>


注意:这个不会自动生成,需要手动写,还有这边列名是属性名的全部大写。

单表的curd操作(增删改查)

save(增)
delete(删)
update(改)
get与load(查)
Student s = new Student("laoqiangsdasda", "来自星星adsad", "男sdada", 234, new Date());
Address a = new Address("sdada", "asdasdsa");
s.setAdressdetail(a);
session.save(s);

Student s1 = session.get(Student.class,"laoqiangsdasda");
session.delete(s1);

Student s2 = session.get(Student.class,"laoqiangsdasda111");
Student s3= session.load(Student.class,"laoqiangsdasda");

System.out.println(s2.getName());

Student s4= session.get(Student.class,"laoqiangsdasda");
s4.setSex("hhhhhhhhh");
session.update(s4);


get与load区别

在不考虑缓存的情况下,get方法会在调用之后立即向数据库发出sql语句,返回持久化对象。

load方法会在调用后返回一个代理对象。

该代理对象只保存实体的主键属性,直接使用对象的非主键属性时才会发出sql语句。

查询数据库中不存在的数据时,get方法返回null,load方法抛出异常.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息