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对象方式:
openSessiongetCurrentSession
如果使用第二种需要配置:
<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方法抛出异常.
相关文章推荐
- Hibernate更新某些字段的几种update方法
- Hibernate 第一例
- Hibernate org.hibernate.hql.internal.ast.QuerySyntaxException: tb_supplier is not mapp
- SSH框架之Hibernate的集合缓存、查询缓存、项目中的session管理方式
- Hibernate无法自动创建表
- Hibernate+Spring 对DAO的处理实列
- JPA &amp; Hibernate 注解
- Hibernate中的Query一些基本用法
- Hibernate相关
- Hibernate分页和投影
- hibernate与ibatis的区别详解
- ehcache + hibernate 二级缓存技术(转)
- Hibernate中Criteria的完整用法
- 【Spring+Hibernate】里出错:Write operations are not allowed in read-only mode
- hibernate用hql怎么查询某个字段
- Hibernate配置错误处理
- [置顶] Struts2 + Spring + Hibernate 视频教程
- Hibernate 的流程(Hibernate 的结构)?
- hibernate.properties配置属性详解。
- [转载]Hibernate查询解决方案 -------Jplateau