【Hibernate】(3)Hibernate单表操作

1. 单一主键

这个是在我们生成的Student.hbm.xml中配置的:

<hibernate-mapping>
	<class name="com.thr.bean.Student" table="STUDENT">
		<id name="id" type="int">
			<column name="ID" />
			<generator class="assigned" />
		</id>

我们将hbm2ddl.auto配置为update

		<property name="hbm2ddl.auto">update</property>
(1). assigned:由Java应用程序负责生成(手工赋值)

手工赋值就是我们之前所写的那种方式:

		Student s = new Student();
		s.setName("李四");
		s.setGender("男");
		s.setBirthday(new Date());
		s.setAddress("北京");
		session.save(s); // 保存对象进入数据库

这个方法执行第一次的时候是成功的,id自动给值0,但是执行第二次的时候就报错了,应为id默认还是0,就会主键冲突。

(2). native:由底层数据库自动生成标识符,如果是MySQL就是increment,如果是Oracle就是sequence,等等

使用native的,如果不置顶id的话它默认会按照从1开始的自动增涨下去,所以当执行添加两次数据后,不会报错,并且id是1、2、3这样子排列下去的。即使你手工指定了id的值,也是不起作用的,插入到数据库中的值也是按照原来的递增顺序添加的。


2. 基本类型



Student.hbm.xml文件中

		<property name="birthday" type="java.util.Date">
			<column name="BIRTHDAY" />
		</property>

java.util.Date是Java中的格式,是包括年月日时分秒的。

type类型如果是date就是只有年月日的格式。

type类型如果是time就是只有时分秒的格式。

type类型如果是timestamp就是包含年月日时分秒的格式。

date、time和timestamp这里是hibernate的数据类型。

3. 对象类型


MySQL不支持标准SQL的CLOB类型,在MySQL中,用TEXT、MEDIUMTEXT和LONGTEXT类型来表示长度超过255的长文本数据。

给之前的Student类添加一个新的属性:

	private Blob picture;

注意,这里需要导入的是java.sql.Blob类

然后需要删除我们之前的Student.hbm.xml文件,重新生成一遍,然后编写方法写入数据库:

	@Test
	public void testWriteBlob() throws Exception {
		Student s = new Student(1, "张三", "男", new Date(), "西安");
		// 先获取照片文件
		File f = new File("F:" + File.separator + "qtww.jpg");
		InputStream is = new FileInputStream(f);
		Blob image = Hibernate.getLobCreator(session).createBlob(is,
				is.available());
		s.setPicture(image);
		session.save(s);
	}
再写一个读取图片文件到本地的方法:

	@Test
	public void testReadBlob() throws Exception {
		// 这里第二个参数是学生的主键
		Student s = (Student) session.get(Student.class, 1);
		Blob image = s.getPicture();
		InputStream is = image.getBinaryStream();
		File f = new File("D:/head.jpg");
		f.createNewFile();
		OutputStream os = new FileOutputStream(f);
		byte[] buff = new byte[is.available()];
		is.read(buff);
		os.write(buff);
		is.close();
		os.close();
	}

4. 组件属性

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

增加新的Address实体类:

public class Address {

	private String postcode;
	private String phone;
	private String address;
}
生成构造方法、get和set方法

修改Student类,加入这一个属性。

修改Student.hbm.xml文件,删除原来的address属性,在<class>标签内增加:

		<component name="address" class="com.thr.bean.Address">
			<property name="postcode" column="POSTCODE"></property>
			<property name="phone" column="PHONE"></property>
			<property name="address" column="ADDRESS"></property>
		</component>
修改测试代码:

	@Test
	public void testSaveStudent() {
		// 生成学生对象
		// Student s = new Student(1, "张三", "男", new Date(), "西安");
		Student s = new Student();
		s.setId(1000);
		s.setName("李四");
		s.setGender("男");
		s.setBirthday(new Date());
		// s.setAddress("北京");
		Address address = new Address("710065", "0298856445", "西安市");
		s.setAddress(address);
		session.save(s); // 保存对象进入数据库
	}
运行后,我们发现在数据库中,新增了3个varchar字段存放我们刚才新建的那个实体类Address。


5. 单表CRUP操作实例

首先要修改策略为update。

	@Test
	public void testGetStudent() {
		Student s = (Student) session.get(Student.class, 1000);
		System.out.println(s);
	}

	@Test
	public void testLoadStudent() {
		Student s = (Student) session.load(Student.class, 1000);
		System.out.println(s);
	}

	@Test
	public void testUpdateStudent() {
		Student s = (Student) session.get(Student.class, 1000);
		s.setGender("女");
		System.out.println(s);
	}

	@Test
	public void testDeleteStudent() {
		Student s = (Student) session.get(Student.class, 1000);
		session.delete(s);
		System.out.println(s);
	}
get和load的区别:

(1). 在不考虑缓存的情况下,get方法会在调用之后立即向数据库发出sql语句,返回持久化对象。而load方法会在调用后返回一个代理对象,该代理对象只保存了实体对象的id,直到使用对象的非主键属性时才会发出sql语句。

(2). 查询数据库中不存在的数据时,get方法返回null,load方法抛出异常org.hibernate.ObjectNotFoundException。


发布了80 篇原创文章 · 获赞 0 · 访问量 5万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章