Hibernate的数据查找,添加!

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介:

1.首先看一下测试数据库的物理模型

2.测试所需要的Hibernate的jar包

3.数据库的sql

复制代码
/*==============================================================*/
/* DBMS name:      MySQL 5.0                                    */
/* Created on:     2015/7/3 23:17:57                            */
/*==============================================================*/


drop table if exists books;

drop table if exists publishers;

/*==============================================================*/
/* Table: books                                                 */
/*==============================================================*/
create table books
(
   bookId               int not null auto_increment,
   publisherId          int,
   title                varchar(20),
   author               varchar(20),
   primary key (bookId)
);

/*==============================================================*/
/* Table: publishers                                            */
/*==============================================================*/
create table publishers
(
   publisherId          int not null auto_increment,
   publishName          varchar(20),
   primary key (publisherId)
);

alter table books add constraint FK_publisherToBook foreign key (publisherId)
      references publishers (publisherId) on delete restrict on update restrict;
复制代码

4.hibernate.cfg.xml文件

复制代码
<?xml version='1.0' encoding='UTF-8'?>
    <!DOCTYPE hibernate-configuration PUBLIC 
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN" 
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> 
     <!-- 正文开始 --> 
<hibernate-configuration> 
     <!--下面是数据库的基本连接信息,对一个应用来说,设置一个session-factory节点就够了,除非我们中间使用了多个数据库--> 
     <session-factory> 
         <!--用户名 --> 
         <property name="connection.username">root</property> 
         <!--url信息 --> 
         <property name="connection.url">jdbc:mysql://localhost:3306/bookstore</property> 
         <!--数据库方言信息--> 
         <property name="dialect">org.hibernate.dialect.MySQLDialect</property> 
         <!--密码 --> 
         <property name="connection.password">hjzgg5211314</property> 
         <!--数据库驱动信息 -->
         <property name="connection.driver_class">org.gjt.mm.mysql.Driver</property> 
         <!--指定Hibernate映射文件路径 --> 
         
         <!-- 字符集乱码问题   -->
         <property name="connection.useUnicode">true</property> 
         <property name="connection.characterEncoding">UTF-8</property> 
          
          <!-- 控制台输出sql语句  -->
          <property name="show_sql">true</property>
          <property name="format_sql">true</property> 
         
         <mapping resource="com/entry/books.hbm.xml" /> 
         <mapping resource="com/entry/publishers.hbm.xml" />
     </session-factory> 
</hibernate-configuration> 
复制代码

5.测试的servlet

复制代码
package com.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import java.util.Set;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.dao.MyHibernateDao;
import com.entry.Books;
import com.entry.Publishers;

/**
 * Servlet implementation class HibernateServlet
 */
@WebServlet("/HibernateServlet")
public class HibernateServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public HibernateServlet() {
        super();
        // TODO Auto-generated constructor stub
    }
    
    private void process(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setCharacterEncoding("utf-8");
        response.setContentType("text/html");
        MyHibernateDao dao = new MyHibernateDao();
        List<Books> list = dao.getAllBooks();
        PrintWriter out = response.getWriter();
        for(Books book : list){
            out.print("书名:" + book.getTitle() + "---作者:" + book.getAuthor() + "---出版社:" + book.getPublishers().getPublishName());
            out.print("<br>");
        }
        
        out.print("<br>");
        out.print("<br>");
        out.print("<br>");
        out.print("<br>");
        List<Publishers> tlist = dao.getAllPublishers();
        for(Publishers publishers : tlist){
            out.print("出版社: " + publishers.getPublishName());
            out.print("<br>");
            Set<Books> bookSet = publishers.getBooks();
            for(Books books : bookSet){
                out.print("&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp");
                out.print(books.getTitle() + " " + books.getAuthor() + "<br>");
            }
            out.print("<br>");
        }
    }

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        process(request, response);
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        process(request, response);
    }

}
复制代码

6.简单的Dao层

复制代码
package com.dao;

import java.util.List;

import org.hibernate.Session;

import com.entry.Books;
import com.entry.Publishers;
import com.hibtest1.HibernateSessionFactory;

public class MyHibernateDao {
    public List<Books> getAllBooks(){
        Session session = HibernateSessionFactory.getSession();
        List<Books> list = null;
        try{
            String hql = "from Books";
            list = session.createQuery(hql).list();
        } catch (Exception e){
            System.out.println("getAllBooks---errors");
            e.printStackTrace();
        }
        return list;
    }
    
    public List<Publishers> getAllPublishers(){
        Session session = HibernateSessionFactory.getSession();
        List<Publishers> list = null;
        try{
            String hql = "from Publishers";
            list = session.createQuery(hql).list();
        } catch (Exception e){
            System.out.println("getAllPublishers---errors");
            e.printStackTrace();
        }
        return list;
    }
}
复制代码

7.实体Publishers和它的映射文件xml

复制代码
package com.entry;

import java.io.Serializable;
import java.util.Set;

public class Publishers implements Serializable{
    private Integer publisherId;
    private String publishName;
    public Integer getPublisherId() {
        return publisherId;
    }
    public void setPublisherId(Integer publisherId) {
        this.publisherId = publisherId;
    }
    public String getPublishName() {
        return publishName;
    }
    public void setPublishName(String publishName) {
        this.publishName = publishName;
    }
    
    private Set<Books> books;
    public Set<Books> getBooks() {
        return books;
    }
    public void setBooks(Set<Books> books) {
        this.books = books;
    }
    
}
复制代码
复制代码
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping 
                PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
                "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.entry">
        <class name="Publishers" table="publishers">
            <!-- 定义持久化类的表示属性 -->
            <id name="publisherId" column="publisherId" type="java.lang.Integer">
                <!-- 定义主键生成策略 -->
                <generator class="identity"/>
            </id>
            <property name="publishName" column="publishName" type="java.lang.String"/>
            
            <!--  
                反过来看,出版社和书籍是一对多的关系,这也就意味着每个Publishers对象会引用一组Books对象。
             -->     
             <set name="books" lazy="false">
                 <key column="publisherId"/>
                 <one-to-many class="com.entry.Books"/>
             </set>
        </class>
</hibernate-mapping>
复制代码

8.实体Books和它的映射文件xml

复制代码
package com.entry;

import java.io.Serializable;

public class Books implements Serializable{
    private Integer bookId;
    private String title;
    private String author;
    private Publishers publishers;
    public Integer getBookId() {
        return bookId;
    }
    public void setBookId(Integer bookId) {
        this.bookId = bookId;
    }
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public String getAuthor() {
        return author;
    }
    public void setAuthor(String author) {
        this.author = author;
    }
    public Publishers getPublishers() {
        return publishers;
    }
    public void setPublishers(Publishers publishers) {
        this.publishers = publishers;
    }
    
    
}
复制代码
复制代码
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping 
                PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
                "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.entry">
        <class name="Books" table="books">
            <!-- 定义持久化类的表示属性 -->
            <id name="bookId" column="bookId" type="java.lang.Integer">
                <!-- 定义主键生成策略 -->
                <generator class="identity"/>
            </id>
            <property name="title" column="title" type="java.lang.String"/>
            <property name="author" column="author" type="java.lang.String"/>
            
            <many-to-one name="publishers" column="publisherId" class="com.entry.Publishers" lazy="false"/>
            <!--  
                默认lazy="true", 这样Books对象加载之后就不会立即加载关联的Publishers对象,就会发生异常
             -->
        </class>
</hibernate-mapping>
复制代码

9. HibernateSessionFactory代码

复制代码
package com.hibtest1;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;

@SuppressWarnings("deprecation")
public class HibernateSessionFactory {

    /** 
     * Location of hibernate.cfg.xml file.
     * Location should be on the classpath as Hibernate uses  
     * #resourceAsStream style lookup for its configuration file. 
     * The default classpath location of the hibernate config file is 
     * in the default package. Use #setConfigFile() to update 
     * the location of the configuration file for the current session.   
     */
    
    private static String CONFIG_FIEL_LOACTION = "/hibernate.cfg.xml";
    private static String configFile = CONFIG_FIEL_LOACTION;
    private static final ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();
    private static org.hibernate.SessionFactory sessionFactory;
    private static Configuration configuration = new Configuration();
    private static ServiceRegistry serviceRegistry; 
    /**
        在回话工厂类HibernateSessionFactory中, 首先通过一次静态代码块来启动Hibernate,该代码块只在HibernateSessionFactory类被加载时执行一次,
        用于建立sessionFactory。即SessionFactory是线程安全的,只能被实例化一次。
        在静态代码块中通过创建Configuration对象并调用其configure()方法读取Hibernate配置文件hibernate.cfg.xml信息,从而进行配置信息的管理。然后
        创建SessionFactory实例,在Hibernate4.0版本之前,该实例创建工作由Configuration对象的buildSessionFactory()方法来完成。而Hibernater4.0
        版本之后,创建SessionFactory实例的方法有所改变,Hibernate 增加了一个注册ServiceRegistryBuilder类。要生成一个注册机对象,然后所有的生成
        SessionFactory的对象向注册机注册一下再使用。生成方法还config.buildSessionFactory()方法,只不过加了一个注册机的参数。
    */
    static {
        try {
            configuration.configure(configFile);
            serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry();
            sessionFactory = configuration.buildSessionFactory(serviceRegistry);
        } catch (Exception e) {
            System.err.println("%%%% Error Creating SessionFactory %%%%" + e);
            e.printStackTrace();
        }
    }
    
    private HibernateSessionFactory() {
    }
    
    /**
     * Returns the ThreadLocal Session instance.  Lazy initialize
     * the <code>SessionFactory</code> if needed.
     *    
     * 由于sessionFactory是线程安全的,因而同一个SessionFactory实例可以被多个线程共享,即多个并发线程可以同时访问一个SesisonFactory并
     * 获得Session的实例。但由于Session不是线程安全的,如果多个并发线程同时操作同一个Session对象,就可能出现一个线程在进行数据库操作,而另一个
     * 线程将Session对象关闭的情况,从而出现异常。如何才能保证线程安全呢?这就要求SessionFactory能够针对不同的线程创建不同的Session对象,即
     * 需要对Session进行有效的管理,Hibernate中使用ThreadLocal对象来维护和管理Session实例。
     * 
     * ThreadLocal是线程局部变量,线程局部变量高效的为每一个使用它的线程提供单独的线程局部变量的副本。为了实现为每个线程维护一个变量的副本,ThreadLocal
     * 类提供了一个Map结构,是key值用来保存线程的ID, value用来保存一个Session实例的副本。这样多线程并发操作时,实在与自己绑定的Session实例副本上进行
     * 的,从而避免多个线程横在同一个Session实例上操作是可能导致的数据异常。
     *    
     * 在HibernaterSessionFctory类的getSession()方法中,首先调用ThreadLocal类的get()方法获得当前线程的Session对象,然后判断当前线程是否已存在
     * Session对象或者对象未打开,在判断SessionFactory对象是否为空,如果SeesionFctory对象不存在,先调用rebuildSessionFactory()方法创建SesionFactory,
     * 如果SessionFactory对象已经存在,则调用SessionFactory对象的openSession()方法创建Session对象。创建完Session对象后,还需要调用ThreadLocal的set()
     * 方法为该线程保存Session对象。
     * 
     *  @return Session
     *  @throws HibernateException
     */
    public static Session getSession() {
        Session session = (Session) threadLocal.get();
        try{
            if (session == null || !session.isOpen()) {
                if (sessionFactory == null) {
                    rebuildSessionFactory();
                }
                session = (sessionFactory != null) ? sessionFactory.openSession()
                        : null;
                threadLocal.set(session);
            }
        } catch (HibernateException e){
            System.err.println("%%%% Error Creating getSession %%%%" + e);
            e.printStackTrace();
        }
        return session;
    }

    /**
     *  Rebuild hibernate session factory
     *
     */
    public static void rebuildSessionFactory() {
        synchronized(sessionFactory){
            try {
                configuration.configure(configFile);
                serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry();
                sessionFactory = configuration.buildSessionFactory(serviceRegistry);
            } catch (Exception e) {
                System.err.println("%%%% Error rebuildSessionFactory %%%%" + e);
                e.printStackTrace();
            }
        }
    }

    /**
     *  Close the single hibernate session instance.
     *
     *  @throws HibernateException
     */
    public static void closeSession(){
        Session session = (Session) threadLocal.get();
        threadLocal.set(null);
        try{
            if (session != null && session.isOpen()) {
                session.close();
            }
        } catch(HibernateException e){
            System.err.println("%%%% Error closeSession %%%%" + e);
            e.printStackTrace();
        }
    }

    /**
     *  return session factory
     *
     */
    public static org.hibernate.SessionFactory getSessionFactory() {
        return sessionFactory;
    }
    /**
     *  return hibernate configuration
     *
     */
    public static Configuration getConfiguration() {
        return configuration;
    }
    
    public static void setConfigFile(String configFile){
        HibernateSessionFactory.configFile = configFile;
    }

}
复制代码

一.上述代码可以简单的完成数据的查找

二.Hibernate添加数据

方法1.主控方为“一”的一方添加数据,默认, 注意“多”的一方的外键publisherId是允许空值的情况

在MyHibernateDao.java中添加如下的方法,用来进行级联数据的添加

复制代码
//添加数据
    public void save(Publishers publisher){
        Session session = HibernateSessionFactory.getSession();
        Transaction tran = session.beginTransaction();
        session.save(publisher);
        tran.commit();
        session.close();
    }
复制代码

 在HibernateServlet.java中添加如下代码,进行数据添加

复制代码
//添加数据
        Books book1 = new Books();
        book1.setAuthor("李xx");
        book1.setTitle("数学");
        Books book2 = new Books();
        book2.setAuthor("hxx");
        book2.setTitle("语文");
        
        Publishers publisher = new Publishers();
        publisher.setPublishName("hjzgg");
        publisher.getBooks().add(book1);
        publisher.getBooks().add(book2);
        dao.save(publisher);
         
        PrintWriter out = response.getWriter();
        List<Books> list = dao.getAllBooks();
        out.print(list.size() + "<br>");
        for(Books book : list){
            out.print("书名:" + book.getTitle() + "---作者:" + book.getAuthor() + "---出版社:" + book.getPublishers().getPublishName());
            out.print("<br>");
        }
        
        out.print("<br>");
        out.print("<br>");
        out.print("<br>");
        out.print("<br>");
复制代码

publishers.hbm.xml代码更改如下:

 <set name="books" lazy="false" cascade="save-update">
                 <key column="publisherId"/>
                 <one-to-many class="com.entry.Books"/>
             </set>

 

注意如果 “多”的一方的外键publisherId是不允许空值的情况,会出现如下异常, 那么更改的地方就多了一些

%%%% Error Creating SessionFactory %%%%org.hibernate.MappingException: Repeated column in mapping for entity: com.entry.Books column: publisherId (should be mapped with insert="false" update="false")
org.hibernate.MappingException: Repeated column in mapping for entity: com.entry.Books column: publisherId (should be mapped with insert="false" update="false")

更改如下:

books.hbm.xml文件:

<many-to-one name="publishers" column="publisherId" class="com.entry.Publishers" lazy="false"
                    insert="false" update="false"/>

publishers.hbm.xml文件:

<set name="books" lazy="false" cascade="save-update">
                 <key column="publisherId" not-null="true"/>
                 <one-to-many class="com.entry.Books"/>
             </set>

方法2.主控方为“多”的一方添加数据,利用invers属性,将控制权进行反转,这样添加数据相对来说更为高效, 代码更改如下:

首先在HibernateServlet.java中添加如下代码,进行数据添加

复制代码
//添加数据, 主控方为“多”
        Books book1 = new Books();
        book1.setAuthor("李xx");
        book1.setTitle("数学");
        Books book2 = new Books();
        book2.setAuthor("hxx");
        book2.setTitle("语文");
        
        Publishers publisher = new Publishers();
        publisher.setPublishName("hjzgg");
        book1.setPublishers(publisher);
        book2.setPublishers(publisher);
        dao.saveBooks(book1);
        dao.saveBooks(book2);
复制代码

然后修改books.hbm.xml文件:

<many-to-one name="publishers" column="publisherId" class="com.entry.Publishers" lazy="false"
                    cascade="save-update"/>

接着修改publishers.hbm.xml文件:

 <set name="books" lazy="false" cascade="save-update" inverse="true">
                 <key column="publisherId" not-null="true"/>
                 <one-to-many class="com.entry.Books"/>
             </set>

最后在MyHibernateDao.java中添加如下代码:

复制代码
//添加数据, 主控方为“多”
    public void saveBooks(Books book){
        Session session = HibernateSessionFactory.getSession();
        Transaction tran = session.beginTransaction();
        session.save(book);
        tran.commit();
        session.close();
    }
复制代码









本文转自 小眼儿 博客园博客,原文链接:http://www.cnblogs.com/hujunzheng/p/4620260.html,如需转载请自行联系原作者
相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
7月前
|
XML Java 数据库连接
Spring Boot的数据访问之Spring Data JPA以及Hibernate的实战(超详细 附源码)
Spring Boot的数据访问之Spring Data JPA以及Hibernate的实战(超详细 附源码)
138 0
|
3月前
|
Java 数据库连接 API
解锁高效开发秘籍:深入探究 Hibernate 如何优雅处理一对多与多对多关系,让数据映射再无烦恼!
【9月更文挑战第3天】Hibernate 是 Java 领域中最流行的 ORM 框架之一,广泛用于处理实体对象与数据库表之间的映射。尤其在处理复杂关系如一对多和多对多时,Hibernate 提供了丰富的 API 和配置选项。本文通过具体代码示例,展示如何使用 `@OneToMany`、`@JoinColumn`、`@ManyToMany` 和 `@JoinTable` 等注解优雅地实现这些关系,帮助开发者保持代码简洁的同时确保数据一致性。
56 4
|
4月前
|
XML JSON Java
使用IDEA+Maven搭建整合一个Struts2+Spring4+Hibernate4项目,混合使用传统Xml与@注解,返回JSP视图或JSON数据,快来给你的SSH老项目翻新一下吧
本文介绍了如何使用IntelliJ IDEA和Maven搭建一个整合了Struts2、Spring4、Hibernate4的J2EE项目,并配置了项目目录结构、web.xml、welcome.jsp以及多个JSP页面,用于刷新和学习传统的SSH框架。
96 0
使用IDEA+Maven搭建整合一个Struts2+Spring4+Hibernate4项目,混合使用传统Xml与@注解,返回JSP视图或JSON数据,快来给你的SSH老项目翻新一下吧
|
4月前
|
Java 数据库连接 数据库
从零到精通:揭秘 Hibernate 构建持久层服务的全过程,你离数据持久化大师还有多远?
【8月更文挑战第31天】本文详细介绍了如何从零开始使用 Hibernate 构建一个持久层服务。首先,通过在 Maven 项目中添加必要的依赖,确保项目具备使用 Hibernate 的条件。接着,配置 `hibernate.cfg.xml` 文件以连接 MySQL 数据库,并设置了基本属性。然后定义了一个简单的 `User` 实体类及其映射关系。此外,还创建了一个 `HibernateUtil` 工具类来管理 `SessionFactory`。
42 0
|
4月前
|
Java 数据库连接 数据库
强强联手!JSF 与 Hibernate 打造高效数据访问层,让你的应用如虎添翼,性能飙升!
【8月更文挑战第31天】本文通过具体示例详细介绍了如何在 JavaServer Faces (JSF) 应用程序中集成 Hibernate,实现数据访问层的最佳实践。首先,创建一个 JSF 项目并在 Eclipse 中配置支持 JSF 的服务器版本。接着,添加 JSF 和 Hibernate 依赖,并配置数据库连接池和 Hibernate 配置文件。然后,定义实体类 `User` 和 DAO 类 `UserDAO` 处理数据库操作。
64 0
|
Oracle Java 关系型数据库
hibernate在分层架构中修改数据(update)时遇到的问题!!
hibernate在分层架构中修改数据(update)时遇到的问题!!
|
缓存 Java 数据库连接
hibernate+oracle+servlet实现插入数据的时候,不立马显示!!
hibernate+oracle+servlet实现插入数据的时候,不立马显示!!
|
Java 数据库连接
Java:hibernate-validator验证数据
Java:hibernate-validator验证数据
113 0
|
SQL Java 数据库连接
hibernate 根据某一列数据去重
hibernate 根据某一列数据去重