第一个demo


Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个全自动的orm框架,hibernate可以自动生成SQL语句,自动执行,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。 Hibernate可以应用在任何使用JDBC的场合,既可以在Java的客户端程序使用,也可以在Servlet/JSP的Web应用中使用,最具革命意义的是,Hibernate可以在应用EJB的J2EE架构中取代CMP,完成数据持久化的重任。

一:去官网http://hibernate.org/orm/releases/下载一个Hibernate的包,选择自己的需要的版本。

二:在myEclipse里创建一个java工程。

三:将下载的hibernate的包required文件中的jar包都拷贝到项目工程的lib文件夹下

      选中项目右键–>Build Path–>Add External Jars–>选择存放hibernate jar 包的路径–>选择jar包

package org.test.entity;


public class User {
private int id;
private String uname;
private int age;
private String sex;
private String city;
public int getId() {
return id; }
public void setId(int id) {
this.id = id;
}
public String getUname() {
return uname;
}
public void setUname(String uname) {
this.uname = uname;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;

}


//重写Object类下的toString()方法
public String toString(){
return “User [id=”+id+”,uname=”+uname+”,age=”+age+”,sex=”+sex+”,city=”+city+”]”;
}
}

编写映射文件User.hbm.xml

       实体类User目前还不具备持久化操作的能力,而Hibernate需要知道实体类User映射到数据库 Hibernate中的哪个表,以及类中的哪个属性对应数据库表中的哪一个字段,这些都需要在映射文件中配置。

      在实体类User所在的包中,创建一个名称为User.hbm.xml的映射文件,在该文件中定义了实体类User的属性是如何映射到user表的列上的。

我们可以下载好hibernate需要的映射文件导入到工程中去,除此之外,通常myEclipse会自己附带hibernate,所以这里记录一下如何直接在myEclipse中创建hbm.xml映射文件。

1.右键点击工程new弹出New框在框中选择XML(Basic Templates)。下一步后在.xml前加上hbm,整个文件出来之后就是“.hbm.xml”为后缀的文件,然后next


2.选择第一个单选框,点击next


3.选择第二项,然后找到我们要用的dtd,点击next,会出来一个界面,不用管它直接点击finish


4.然后User.hbm.xml映射文件就建好了

<?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>
<!– name代表实体类名 ,table代表表名 –>
<class name=”org.test.entity.User” table=”user”>
<!– name=id代表user类中属性   column=id代表的是table表中的字段–>
      <id name=”id” column=”id”>
      <generator class=”native”/><!– 主键生成策略 –>
      </id>
      <!– 其他属性使用property标签来映射 –>
<property name=”uname” column=”uname” type=”string”/>
<property name=”age” column=”age” type=”int”/>
<property name=”sex” column=”sex” type=”string”/>
<property name=”city” column=”city” type=”string”/>


</class>
</hibernate-mapping>

 第七步: 编写核心配置文件hibernate.cfg.xml

  Hibernate的映射文件反映了持久化类和数据库表的映射信息,

  而Hibernate的配置文件则主要用来配置数据库连接以及Hibernate运行时所需要的各个属性的值.

从下载解压的文件夹中选择project文件夹下的etc文件夹,打开文件夹找到hibernate.cfg.xml拖拽到项目的src目录下,根据需要修改相应配置信息

myEclipse连接数据库,可以用jdbc接口,也有另一种不用jdbc的方法:

1.window–>Open Perspctive–>MyEclipse Database Explorer–>OK


2.左侧空白处右键–>New–>输入相关信息

 在Driver name填写链接数据库的名称(这个可由自己喜好填写,建议最好和所做项目名称相关便于使用时查找)
Connection URL用于填写连接要使用mysql数据库的地址(jdbc:>[<:3306>]/<dbname>),其中localhost表示的是连接本地数据库的意思,3306是表示连接mysql数据库的端口号(不同的数据库端口号也不相同),
User name 填写数据库用户名mysql默认的是root
Password填写访问mysql数据库时的你所设置的访问密码。
点击Add JARs添加myeclipse连接mysql数据库的驱动文件,在这里添加的是mysql-connector-java-5.1.46-bin版本(可以在网上搜索下载)


3.点击Test Driver测试是否配置成功,输入访问数据库密码。


注:

      但是在测试时,出现了如下的错误,使用驱动程序执行数据库登陆时出现错误,经过检查和上网查询发现是导入自己下载的数据库jar包时,驱动文件放在了中文目录,更改了存放目录后错误解决。


因此存放驱动的文件最好是英文目录,在测试时确定mysql数据库已经打开,服务已经打开,否则测试会报错

测试成功后界面如下:


hibernate.cfg.xml

<!–
  ~ Hibernate, Relational Persistence for Idiomatic Java
  ~
  ~ License: GNU Lesser General Public License (LGPL), version 2.1 or later.
  ~ See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html&gt;.
  –>
<!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=”show_sql”>true</property>
<property name=”hibernate.dialect”>org.hibernate.dialect.MySQL5Dialect</property>
<property name=”hibernate.connection.driver_class”>com.mysql.jdbc.Driver</property>
<property name=”hibernate.connection.url”>jdbc:mysql://localhost:3306/hibernate</property>
<property name=”hibernate.connection.username”>root</property>
<property name=”hibernate.connection.password”></property>
    <property name=”format_sql”>true</property>

<mapping resource=”org/test/entity/User.hbm.xml”/>
</session-factory>
</hibernate-configuration>


第八步:编写测试类,进行测

  在项目中src下新建一个org.test.demo的包,然后再包内建立一个名为UserTest.java的文件,该文件是用来测试的类文件。

package org.test.demo;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.test.entity.User;


public class UserTest {


  //定义变量


    Configuration config;


    SessionFactory sessionFactory;


    Session session;


    Transaction transaction;


    //before表示在方法执行前执行


    @Before


    public void SetUp()


    {


      //1.加载hibernate.cfg.xml配置


      config=new Configuration().configure();


      //2.获取SessionFactory


      sessionFactory= config.buildSessionFactory();  


     //3.获得一个session


      session=sessionFactory.openSession();


      //4.开始事务


      transaction=session.beginTransaction();


    }


    //添加操作


    @Test


    public void insert()


    {    


      //5.操作


      User user=new User();


     // user.setId(1);


      user.setUname(“zhangsan”);


      user.setAge(20);


      user.setSex(“m”);


      user.setCity(“guangzhou”);


      session.save(user);


    }


    //删除操作


   
@Test
     public void delete()


     {


        //先查询


        User user=(User)session.get(User.class,1);


        //再删除
      if(user!=null)
      {
        session.delete(user);
      }
     }


    //查询操作


   
@Test
    public void select()


    {


    User user=(User)session.get(User.class, 1);


        System.out.println(user);   


    }


    //更新操作
@Test
    public void update()


    {    


    User user=new User();


      //user.setId(1);


      user.setUname(“zhangsan”);


      user.setAge(20);


      user.setSex(“m”);


      //修改地址为beijing


      user.setCity(“beijing”);


      //存在就更新,不存在就执行插入操作


      session.saveOrUpdate(user);


    }


    //After表示在方法执行结束后执行
@After
    public void closeTransaction()


    {


      //6.提交事务


      transaction.commit();


      //7.关闭资源


      session.close();


      sessionFactory.close();


    }


}




使用单元测试框架JUnit4进行单元测试,不需要main方法,就可以直接对类中的方法进行测试。@Test是用来测试的注解。


进度条 为绿色表明运行结果正确,如果为红色则表示有错误。在数据库中查询表数据,结果如图:


表明user表中数据添加成功。

测试运行select()方法后,控制台信息如图:


测试更新方法update()时,结果如图:


数据库中表数据为:


测试删除方法delete()删除id为2后,数据表为:


测试成功!

当然,在测试过程中,遇到了一些问题,也折腾了很长时间:

1.在测试更新方法update()时:


错误信息:javax.persistence.OptimisticLockException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
at org.hibernate.internal.ExceptionConverterImpl.wrapStaleStateException(ExceptionConverterImpl.java:212)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:86)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:155)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:162)
at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1441)
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:491)
at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:3201)
at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2411)
at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:467)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:146)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access 100 ( J d b c R e s o u r c e L o c a l T r a n s a c t i o n C o o r d i n a t o r I m p l . j a v a : 38 ) < b r >< s p a n s t y l e =" w h i t e s p a c e : p r e ; ">< / s p a n > a t o r g . h i b e r n a t e . r e s o u r c e . t r a n s a c t i o n . b a c k e n d . j d b c . i n t e r n a l . J d b c R e s o u r c e L o c a l T r a n s a c t i o n C o o r d i n a t o r I m p l TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:220)
at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:68)
at org.test.demo.UserTest.closeTransaction(UserTest.java:143)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod 1. r u n R e f l e c t i v e C a l l ( F r a m e w o r k M e t h o d . j a v a : 47 ) < b r >< s p a n s t y l e =" w h i t e s p a c e : p r e ; ">< / s p a n > a t o r g . j u n i t . i n t e r n a l . r u n n e r s . m o d e l . R e f l e c t i v e C a l l a b l e . r u n ( R e f l e c t i v e C a l l a b l e . j a v a : 12 ) < b r >< s p a n s t y l e =" w h i t e s p a c e : p r e ; ">< / s p a n > a t o r g . j u n i t . r u n n e r s . m o d e l . F r a m e w o r k M e t h o d . i n v o k e E x p l o s i v e l y ( F r a m e w o r k M e t h o d . j a v a : 44 ) < b r >< s p a n s t y l e =" w h i t e s p a c e : p r e ; ">< / s p a n > a t o r g . j u n i t . i n t e r n a l . r u n n e r s . s t a t e m e n t s . R u n A f t e r s . e v a l u a t e ( R u n A f t e r s . j a v a : 33 ) < b r >< s p a n s t y l e =" w h i t e s p a c e : p r e ; ">< / s p a n > a t o r g . j u n i t . r u n n e r s . P a r e n t R u n n e r . r u n L e a f ( P a r e n t R u n n e r . j a v a : 271 ) < b r >< s p a n s t y l e =" w h i t e s p a c e : p r e ; ">< / s p a n > a t o r g . j u n i t . r u n n e r s . B l o c k J U n i t 4 C l a s s R u n n e r . r u n C h i l d ( B l o c k J U n i t 4 C l a s s R u n n e r . j a v a : 70 ) < b r >< s p a n s t y l e =" w h i t e s p a c e : p r e ; ">< / s p a n > a t o r g . j u n i t . r u n n e r s . B l o c k J U n i t 4 C l a s s R u n n e r . r u n C h i l d ( B l o c k J U n i t 4 C l a s s R u n n e r . j a v a : 50 ) < b r >< s p a n s t y l e =" w h i t e s p a c e : p r e ; ">< / s p a n > a t o r g . j u n i t . r u n n e r s . P a r e n t R u n n e r 3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner 1. s c h e d u l e ( P a r e n t R u n n e r . j a v a : 63 ) < b r >< s p a n s t y l e =" w h i t e s p a c e : p r e ; ">< / s p a n > a t o r g . j u n i t . r u n n e r s . P a r e n t R u n n e r . r u n C h i l d r e n ( P a r e n t R u n n e r . j a v a : 236 ) < b r >< s p a n s t y l e =" w h i t e s p a c e : p r e ; ">< / s p a n > a t o r g . j u n i t . r u n n e r s . P a r e n t R u n n e r . a c c e s s 000(ParentRunner.java:53)
at org.junit.runners.ParentRunner 2.evaluate(ParentRunner.java:229)<br><span style="white-space:pre;"> </span>at org.junit.runners.ParentRunner.run(ParentRunner.java:309)<br><span style="white-space:pre;"> </span>at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)<br><span style="white-space:pre;"> </span>at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)<br><span style="white-space:pre;"> </span>at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)<br><span style="white-space:pre;"> </span>at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)<br><span style="white-space:pre;"> </span>at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)<br><span style="white-space:pre;"> </span>at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)<br>Caused by: org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1<br><span style="white-space:pre;"> </span></span></p><p><span style="font-size:14px;">直观翻译过来是:批量更新从更新0返回意外的行数;实际的行数0;预期:1</span></p><p><span style="font-size:14px;">这样的问题,不注意的话也挺无所适从:这个问题是主键一开始设置为自增长,而在我插入数据时又设置了ID值导致的。</span></p><p><span style="font-size:14px;">我的解决方法是插入数据时,不重新设置Id值,数据库会自动给出一个自增长的id值。</span></p><p><span style="font-size:14px;"><br></span></p><p><span style="font-size:14px;">2.测试删除方法delete()时,</span></p><p><span style="font-size:14px;"><img src="https://img-blog.csdn.net/20180505233125831?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2xpbmJpdWJpdWJpdQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70" alt=""><br></span></p><p><span style="font-size:14px;">错误信息:</span></p><p><span style="font-size:14px;">java.lang.IllegalArgumentException: attempt to create delete event with null entity<br><span style="white-space:pre;"> </span>at org.hibernate.event.spi.DeleteEvent.&lt;init&gt;(DeleteEvent.java:31)<br><span style="white-space:pre;"> </span>at org.hibernate.internal.SessionImpl.delete(SessionImpl.java:927)<br><span style="white-space:pre;"> </span>at org.test.demo.UserTest.delete(UserTest.java:91)<br><span style="white-space:pre;"> </span>at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)<br><span style="white-space:pre;"> </span>at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)<br><span style="white-space:pre;"> </span>at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)<br><span style="white-space:pre;"> </span>at java.lang.reflect.Method.invoke(Method.java:498)<br><span style="white-space:pre;"> </span>at org.junit.runners.model.FrameworkMethod 1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner 3. r u n ( P a r e n t R u n n e r . j a v a : 238 ) < b r >< s p a n s t y l e =" w h i t e s p a c e : p r e ; ">< / s p a n > a t o r g . j u n i t . r u n n e r s . P a r e n t R u n n e r 1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access 000 ( P a r e n t R u n n e r . j a v a : 53 ) < b r >< s p a n s t y l e =" w h i t e s p a c e : p r e ; ">< / s p a n > a t o r g . j u n i t . r u n n e r s . P a r e n t R u n n e r 2.evaluate(ParentRunner.java:229)at org.junit.runners.ParentRunner.run(ParentRunner.java:309)at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)