一.Hibernate的数据类型
Hibernate可以自动生成数据表. 在生成数据表的时候,应当保证一点,那就是数据的类型要保持一致。 在POJO中写得是Integer,那么在数据库生成的时候,是不能是varchar 类型的。 在POJO中写得是String ,那么在数据库生成的时候,是不能是int类型的。这就是如何将Java类型与数据库SQL 类型进行对应的问题。 如何对应呢? 是通过Hibernate进行对应的。 要有一个Hibernate的数据类型。 Hibernate是先将POJO即普通的java类型转换成Hibernate类型,然后将Hibernate类型转换成数据库SQL类型,这样就达到了Java类型转换成SQL类型的目的。这些类型对应关系,并非都是一对一的关系。 其他的框架,也是这个思路。
二.常用类型的生成测试
二.一 实体类
package com.yjl.pojo; import java.sql.Blob; import java.util.Date; /** @author:两个蝴蝶飞 @date: 2019年3月8日 上午10:33:16 @Description 类型转换。 */ public class Book { /** * @param id 主键编号 是int 型 * @param name 书名 是varchar 型 * @param price 价钱 是number或者float型 * @param publishDate 出版日期 是timestamp 或者date 型 * @param author 作者 是varchar 型 * @param specialPrice 是否是降价 是boolean 型 * @param description 描述 是长字段 text型 * @param bookImage 图片 是Blod 型。 开发中存储的是地址 */ private Integer id; private String name; private Double price; private Date publishDate; private String author; private Boolean specialPrice; private String description; private Blob bookImage; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Double getPrice() { return price; } public void setPrice(Double price) { this.price = price; } public Date getPublishDate() { return publishDate; } public void setPublishDate(Date publishDate) { this.publishDate = publishDate; } public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author; } public Boolean getSpecialPrice() { return specialPrice; } public void setSpecialPrice(Boolean specialPrice) { this.specialPrice = specialPrice; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public Blob getBookImage() { return bookImage; } public void setBookImage(Blob bookImage) { this.bookImage = bookImage; } @Override public String toString() { return "Book [id=" + id + ", name=" + name + ", price=" + price + ", publishDate=" + publishDate + ", author=" + author + ", specialPrice=" + specialPrice + ", description=" + description + "]"; } }
这里列举了常用的一些类型,如integer,double,string,date,blob,boolean类型。
二.二 Book.hbm.xml配置类
<?xml version="1.0" encoding="UTF-8"?> <!-- 引入相应的约束 --> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="com.yjl.pojo"> <class name="Book"> <id name="id" column="id"> <generator class="native"></generator> </id> <!--后面的type 可以写java类型,也可以写hibernate类型。 但不能写sql类型。 如果不写的话,会默认读取属性的类型,即java类型。--> <!-- 用的是java类型 --> <property name="name" column="name" type="java.lang.String"></property> <!-- 用的是java类型 --> <property name="price" column="price" type="java.lang.Double"></property> <!-- 用的是hibernate类型 --> <property name="publishDate" column="publishDate" type="timestamp"></property> <!-- 用hibernate类型 --> <property name="author" column="author" type="string"></property> <!-- 用的是java类型 --> <property name="specialPrice" column="specialPrice" type="java.lang.Boolean"></property> <!-- 用的是hibernate类型。 --> <property name="description" column="description" type="text"></property> <!-- 用的是java类型 --> <property name="bookImage" column="bookImage" type="java.sql.Blob"></property> </class> </hibernate-mapping>
不要忘记,放入到hibernate.cfg.xml配置文件中。
二.三 测试生成文件
/*测试创建表是否正确。*/ @Test public void createTest(){ Session session=HibernateUtil.getSession(); session.close(); }
二.四 测试插入
/*插入的测试*/ @Test public void saveTest(){ Session session=HibernateUtil.getSession(); Transaction transaction=session.beginTransaction(); /*创建对象。*/ Book book=new Book(); book.setName("蝴蝶飞往Java"); book.setPrice(23.5D); book.setAuthor("两个蝴蝶飞"); book.setPublishDate(new java.util.Date()); book.setSpecialPrice(true); //是否是特价 book.setDescription("也许,有的时候,就是那么一个人的存在,拯救了他的世界"); File file=new File("D:"+File.separator+"java编程思想.jpg"); InputStream input=null; try { input=new FileInputStream(file); //获取LobHelper接口 LobHelper lobHelper=session.getLobHelper(); //可以创建Blob,也可以创建Clob. LobHelper Blob blob=lobHelper.createBlob(input,input.available()); book.setBookImage(blob); } catch (Exception e) { e.printStackTrace(); } session.save(book); transaction.commit(); //要放在事务提交的后面。 try { input.close(); //关闭input } catch (IOException e) { e.printStackTrace(); } //关闭session session.close(); }
可以正确的插入进去.
数据库存储的是:
二.五 从数据库中读取
/*读取的测试*/ @Test public void readTest() throws Exception{ Session session=HibernateUtil.getSession(); Book book=session.get(Book.class,1); System.out.println(book.toString()); //将图片的信息,存储到另外一个文件下。 Blob blob=book.getBookImage(); BufferedInputStream bis=null; BufferedOutputStream bos=null; InputStream is=null; OutputStream os=null; is=blob.getBinaryStream(); bis=new BufferedInputStream(is); os=new FileOutputStream("D:"+File.separator+"java编程思想数据库读取.jpg"); bos=new BufferedOutputStream(os); int index=0; byte [] b=new byte[10240]; while((index=is.read(b))!=-1){ bos.write(b,0,index); } bis.close(); bos.close(); session.close(); }
在D盘上也显示了这张图片:
打开后,也正常显示这个图片。
三. 对应关系
有一张对应关系的表。
要注意,这种对应关系并非是一对一再对一,即1-1-1的关系。 如java类型的String,即可以转换成varchar 类型,也可以是text类型。 这个时候,在Book.hbm.xml中 type就不要写Java类型了,要写成Hibernate类型。 还有一个Double注意区分,不要将Double与Float混了,两个是不能进行相互转换的。
四. Hibernate中写入其他的元素
四.一 写入Set <String >属性
这里用 学生的例子来说吧。 如一个学生有多张图片。 这些图片保存的都是String类型,即只保存图片的路径地址。 那么这个时候,实体类简化之后,应该是这样的:
public class Student { private Integer id; private String name; /*存入其他的类型*/ private Set<String> images1; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Set<String> getImages1() { return images1; } public void setImages1(Set<String> images1) { this.images1 = images1; } }
相对应的xml配置文件是:
<hibernate-mapping package="com.yjl.pojo"> <class name="Student"> <id name="id" column="id"> <generator class="native"></generator> </id> <!-- 用的是java类型 --> <property name="name" column="name" type="java.lang.String"></property> <!-- 同样用set 标签来表示 table为要保存的表。--> <set name="images1" table="image"> <key column="stuId"></key> <!-- 这里用element 元素来表示 --> <element column="imageName" type="string"></element> </set> </class> </hibernate-mapping>
直接写生成的测试方法:
/*set 类型的测试*/ @Test public void setTest(){ Session session=HibernateUtil.getSession(); Transaction transaction=session.beginTransaction(); Set<String> imageSet=new HashSet<String>(); imageSet.add("image1.png"); imageSet.add("image2.png"); imageSet.add("image3.png"); imageSet.add("image3.png"); Student s1=new Student(); s1.setName("两个蝴蝶飞"); s1.setImages1(imageSet); session.save(s1); transaction.commit(); }
运行之后,会创建两张表。 一个表是student 表,里面只有 id,name 两个属性。 并没有任何关于图片的信息。 另外一个表是image,里面有两个属性,一个是stuId,另外一个是imageName. 这个表是没有主键的。 将对应关系放置到这个表里面了。 是无序的。
读取的测试:
/*读取的测试*/ @Test public void setReadTest(){ Session session=HibernateUtil.getSession(); Student stu=session.get(Student.class,1); Set<String> imageSet=stu.getImages1(); Iterator <String> images=imageSet.iterator(); while(images.hasNext()){ System.out.println(images.next()); } }
下面的,与其一样。
四.二 写入List <String > 属性
如果是数组的话,将其转换成List的形式。
public class Student { private Integer id; private String name; /*存入其他的类型*/ private List<String> hobby; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public List<String> getHobby() { return hobby; } public void setHobby(List<String> hobby) { this.hobby = hobby; } }
配置文件:
<hibernate-mapping package="com.yjl.pojo"> <class name="Student"> <id name="id" column="id"> <generator class="native"></generator> </id> <!-- 用的是java类型 --> <property name="name" column="name" type="java.lang.String"></property> <!-- 用list 标签来表示 --> <list name="hobby" table="hobby"> <key column="stuId"></key> <!-- 有顺序。 把顺序放置进来 --> <list-index column="hobbyIndex"></list-index> <!-- 这里用element 元素来表示 --> <element column="hobbyName" type="string"></element> </list> </class> </hibernate-mapping>
测试:
@Test public void listTest(){ Session session=HibernateUtil.getSession(); Transaction transaction=session.beginTransaction(); List<String> hobbyList=new ArrayList<String>(); hobbyList.add("编程"); hobbyList.add("五音不全的唱歌"); hobbyList.add("打游戏"); Student s1=new Student(); s1.setName("两个蝴蝶飞"); s1.setHobby(hobbyList); session.save(s1); transaction.commit(); }
点击运行之后,会生成Student 和hobby 两个表. 同样没有主键。 id顺序在后。
是有顺序的。
/*读取的测试*/ @Test public void listReadTest(){ Session session=HibernateUtil.getSession(); Student stu=session.get(Student.class,1); List<String> hobbyList=stu.getHobby(); Iterator <String> images=hobbyList.iterator(); while(images.hasNext()){ System.out.println(images.next()); } }
四.三 写入idbag<String > 属性
idbag,是映射,叫包。 是一个无序的,允许重复的集合。 没有具体的实现,只有定义。
可以用Collection,也可以用List. 这里用List进行相关的说明。 所以,实体Student.java 是不变的。 用List集合。
配置文件:
<hibernate-mapping package="com.yjl.pojo"> <class name="Student"> <id name="id" column="id"> <generator class="native"></generator> </id> <!-- 用的是java类型 --> <property name="name" column="name" type="java.lang.String"></property> <!-- 用idbag 包标签来表示 --> <idbag name="hobby" table="hobby"> <collection-id type="long" column="hobbyId"> <generator class="increment"></generator> </collection-id> <key column="stuId"></key> <!-- 这里用element 元素来表示 --> <element column="hobbyName" type="string"></element> </idbag> </class> </hibernate-mapping>
保存测试:
/*栈 bag 类型的测试*/ @Test public void bagTest(){ Session session=HibernateUtil.getSession(); Transaction transaction=session.beginTransaction(); List<String> hobbyList=new ArrayList<String>(); hobbyList.add("编程1"); hobbyList.add("五音不全的唱歌1"); hobbyList.add("打游戏1"); Student s1=new Student(); s1.setName("两个蝴蝶飞"); s1.setHobby(hobbyList); session.save(s1); transaction.commit(); }
会生成两个表。 id顺序在前。
查询时:
/*读取的测试*/ @Test public void bagReadTest(){ Session session=HibernateUtil.getSession(); Student stu=session.get(Student.class,1); List<String> hobbyList=stu.getHobby(); Iterator <String> images=hobbyList.iterator(); while(images.hasNext()){ System.out.println(images.next()); } }
四.四 写入Map <String,String> 属性
实体类:
public class Student { private Integer id; private String name; /*存入其他的类型*/ private Map<String,String> girls; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Map<String, String> getGirls() { return girls; } public void setGirls(Map<String, String> girls) { this.girls = girls; } }
配置文件:
<hibernate-mapping package="com.yjl.pojo"> <class name="Student"> <id name="id" column="id"> <generator class="native"></generator> </id> <!-- 用的是java类型 --> <property name="name" column="name" type="java.lang.String"></property> <!-- 用map 标签来表示 --> <map name="girls" table="girls"> <key column="stuId"></key> <map-key column="girlId" type="string"></map-key> <!-- 这里用element 元素来表示 --> <element column="girlName" type="string"></element> </map> </class> </hibernate-mapping>
保存测试:
@Test public void MapTest(){ Session session=HibernateUtil.getSession(); Transaction transaction=session.beginTransaction(); Map<String,String> girlList=new HashMap<String,String>(); girlList.put("Java","一个非常文静的女孩"); girlList.put("Python","一个非常聪明的女孩"); girlList.put("Go","听说很有钱的女孩"); Student s1=new Student(); s1.setName("两个蝴蝶飞"); s1.setGirls(girlList); session.save(s1); transaction.commit(); }
运行生成后: 是无序的。
查询:
@Test public void MapReadTest(){ Session session=HibernateUtil.getSession(); Student stu=session.get(Student.class,1); Map<String,String> girlList=stu.getGirls(); for(Map.Entry<String,String> m:girlList.entrySet()){ System.out.println(m.getKey()+"----"+m.getValue()); } }
这是Hibernate对Set,List,idbag和Map的常见映射。
谢谢!!!