簡介:
傳統上,Hibernate的配置依賴於外部 XML 文件:數據庫映射被定義為一組 XML 映射文件,並且在啟動時進行加載。
然而現在借助新的 Hibernate Annotation 庫,即可一次性地分配所有舊映射文件——一切都會按照您的想法來定義——注釋直接嵌入到您的Java類中,並提供一種強大及靈活的方法來聲明持久性映射。即利用hibernate注解后,可不用定義持久化類對應的*.hbm.xml文件,直接以注解方式寫入在持久化類中來實現。
配置:
(1)安裝 Hibernate Annotation 第一步, 環境與jar包: 要使用 Hibernate Annotation,您至少需要具備 Hibernate 3.2和Java 5。可以從 Hibernate 站點下載 Hibernate 3.2 和 Hibernate Annotation庫。除了標准的 Hibernate JAR 和依賴項之外,您還需要 Hibernate Annotations .jar 文件(hibernate-annotations.jar)、Java 持久性 API (lib/ejb3-persistence.jar)。
@Entity @Table(name = "Dept") public class Dept { @Id @GeneratedValue /* 對於oracle想使用各自的Sequence,設置如下: @GeneratedValue(strategy =GenerationType.AUTO,generator="PROMOTION_SEQ") @SequenceGenerator(name="PROMOTION_SEQ",sequenceName="PROMOTION_SEQ") 另外: 對於自動增長后,在數據表中的相應字段,要設置字段為auto_increment. */ private Integer deptno; @Column private String deptname; @OneToMany(mappedBy="dept")
//mappedBy 屬性主要針對外鍵而言,與之對應的是.xml中的inverse屬性
//mappedBy="dept" 是把維護權交給多的一方
@LazyCollection(LazyCollectionOption.FALSE)
private Set<Emp> emps=new HashSet<Emp>();
public Integer getDeptno() { return deptno; }
public void setDeptno(Integer deptno) { this.deptno = deptno; }
public String getDeptname() { return deptname; }
public void setDeptname(String deptname) { this.deptname = deptname; }
public Set<Emp> getEmps() { return emps; }
public void setEmps(Set<Emp> emps) { this.emps = emps; } }
默認情況下,Hibernate 會將持久類以匹配的名稱映射到表和字段中。
@Entity @Table(name = "Emp") public class Emp { @Id @GeneratedValue private Integer empno; @Column private String ename;
//如果有多個cascade,可以是{CascadeType.PERSIST,CascadeType.MERGE} @ManyToOne(cascade = {CascadeType.ALL}) @JoinColumn(name = "deptno")//dept類對應外鍵的屬性:deptno private Dept dept; public Integer getEmpno() { return empno; } public void setEmpno(Integer empno) { this.empno = empno; } public String getEname() { return ename; } public void setEname(String ename) { this.ename = ename; } public Dept getDept() { return dept; } public void setDept(Dept dept) { this.dept = dept; } }
在hibernate.cfg.xml中的
<session-factory>
.....
<mapping class="cn.onetomanydouble.entity.Dept"/>
<mapping class="cn.onetomanydouble.entity.Emp"/>
</session-factory>
這里遇到一個問題:如果配置mappedBy屬性的同時加上@JoinColumn會拋出異常,所以不能同時使用@JoinColumn和mappedBy;因為@JoinColumn本身就是自己來維護外鍵,和mappedBy沖突了。--->>>希望大牛可以再詳細的解說下!
拋出的異常如下:
java.lang.ExceptionInInitializerError at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source) at java.lang.reflect.Constructor.newInstance(Unknown Source) at org.junit.runners.BlockJUnit4ClassRunner.createTest(BlockJUnit4ClassRunner.java:217) at org.junit.runners.BlockJUnit4ClassRunner$1.runReflectiveCall(BlockJUnit4ClassRunner.java:266) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.BlockJUnit4ClassRunner.methodBlock(BlockJUnit4ClassRunner.java:263) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192) Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in class path resource [applicationContext.xml]: Invocation of init method failed; nested exception is org.hibernate.AnnotationException: Associations marked as mappedBy must not define database mappings like @JoinTable or @JoinColumn: com.lizhou.entity.test.Department.employeeList at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1553) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475) at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193) at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:684) at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482) at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139) at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83) at com.lizhou.action.test.TestAction.<clinit>(TestAction.java:26) ... 22 more Caused by: org.hibernate.AnnotationException: Associations marked as mappedBy must not define database mappings like @JoinTable or @JoinColumn: com.lizhou.entity.test.Department.employeeList at org.hibernate.cfg.annotations.CollectionBinder.bind(CollectionBinder.java:493) at org.hibernate.cfg.AnnotationBinder.processElementAnnotations(AnnotationBinder.java:2156) at org.hibernate.cfg.AnnotationBinder.processIdPropertiesIfNotAlready(AnnotationBinder.java:963) at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:796) at org.hibernate.cfg.Configuration$MetadataSourceQueue.processAnnotatedClassesQueue(Configuration.java:3788) at org.hibernate.cfg.Configuration$MetadataSourceQueue.processMetadata(Configuration.java:3742) at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1410) at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1844) at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1928) at org.springframework.orm.hibernate4.LocalSessionFactoryBuilder.buildSessionFactory(LocalSessionFactoryBuilder.java:343) at org.springframework.orm.hibernate4.LocalSessionFactoryBean.buildSessionFactory(LocalSessionFactoryBean.java:431) at org.springframework.orm.hibernate4.LocalSessionFactoryBean.afterPropertiesSet(LocalSessionFactoryBean.java:416) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1612) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1549) ... 34 more
在這里再說一下,如果先保存員工后保存部門,會多出四條update語句。
Hibernate: insert into emp (deptno, ename, empno) values (?, ?, ?) Hibernate: insert into emp (deptno, ename, empno) values (?, ?, ?) Hibernate: insert into dept(dname) values (?) Hibernate: update emp set deptno=?, ename=? ,empno=? where id=? Hibernate: update emp set deptno=?, ename=? ,empno=? where id=? Hibernate: update emp set deptno=? ,empno=? where id=? Hibernate: update emp set deptno=? ,empno=? where id=?
總結:mappedBy屬性跟xml配置文件里的inverse一樣。在一對多或一對一的關系映射中,如果不表明mappedBy屬性,默認是由本方維護外鍵。但如果兩方都由本方來維護的話,會多出一些update語句,性能有一定的損耗。
解決的辦法就是在一的一方配置上mappedBy屬性,將維護權交給多的一方來維護,就不會有update語句了。
注意,配了mappedBy屬性后,不要再有@JoinColumn,會沖突!