Hibernate(一)

orm

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

在程序中写大量SQL缺点

  1. 不同的数据库使用的SQL语法不同。
  2. 同样的功能在拨不通的数据库中有不同的实现方式。
  3. 程序过分依赖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);
	}
	
}

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

hibernate常用配置



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

hibernate执行过程




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

Session对象

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


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


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

获取session对象方式:
  1. openSession
  2. 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操作(增删改查)

  1. save(增)
  2. delete(删)
  3. update(改)
  4. 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方法抛出异常.


































































































































评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值