0.注意unsaved-value是个很重要的属性。Hibernate通过这个属性来判断一个对象应该save还是update,如果这个对象的id是unsaved-value的话,那说明这个对象不是 persistence object要save(insert);如果id是非unsaved-value的话,那说明这个对象是persistence object(数据库中已存在),只要update就行了。
1、
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Initialization of bean failed; nested exception is org.hibernate.MappingException: Repeated column in mapping for entity: com.xindeco.myregister.pojo.MyRegisterInfo column: password (should be mapped with insert="false" update="false")
出错原因:1、数据库的字段值和javaBean中的属性类型不统一。对于基本类型,要用wrapper类型而不是primitive类型。2、hibernate的配置文件xxx.hbm.xml中的属性配置不为空,而数据库中的字段却为空。3.两个字段对应同一列,如:password 和repassword同时对应数据库表中的password一列,同时update和insert都设为true。
xml文件如下:
<property name="password"
type="java.lang.String"
update="true"
insert="true"
access="property"
column="password"
length = "32"
/>
<property name="repassword"
type="java.lang.String"
update="false"
insert="false"
access="property"
column="password"
length = "32"
/>
解决的方法:
将repassword的insert和update设为false。
2.
org.springframework.dao.InvalidDataAccessApiUsageException: Write operations are not allowed in read-only mode (FlushMode.NEVER) - turn your Session into FlushMode.AUTO or remove 'readOnly' marker from transaction definition
错误原因:
在application.xml文件中deleteRegister方法以delete开头,并没有被设定为可更改的,应如下设置:
<!--为事物创建代理类,并指定方法的事物类型-->
<bean id="baseTxProxy" lazy-init="true" abstract="true" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager">
<ref bean="transactionManager"/>
</property>
<property name="transactionAttributes">
<props>
<prop key="add*">PROPAGATION_REQUIRED</prop>
<prop key="cancel*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
加上一行
<prop key="delete*">PROPAGATION_REQUIRED</prop>
3.session---connection
4.one-to-one小结:
one-to-one在hibernate中可以用来作为两张表之间的主键关联,这也是hibernate中主键关联的一种用法,这样在一张表中的ID,在生成另外一张表的同时回自动插入到相应的ID字段中去,相应的XML文件设置比较简单,举例如下:
<!-- 建立一对一的到Address的映射,这个是写在User的XML配置文件中的 -->
<!-- 相应的User bean(PO)中也要添加属性 com.xx.Address address-->
<one-to-one name="address" cascade="all" class="com.xx.Address"/>
<!-- cascade的属性设置不再重复了,可以查看hibernate文档 -->
<!-- 建立一对一的到User的映射,这个是写在Address的XML配置文件中的 -->
<!-- 相应的Address bean(PO)中也要添加属性 com.xx.User user--> -->
<one-to-one name="user" class="com.xx.User" constrained="true"/>
为了在Address中使用User中的主键ID值,我们需要设置Address中的主键生成规则,如下所示,采用foreign关键字
<id column="ID" name="id" type="long" unsaved-value="0">
<generator class="foreign">
<param name="property">user</param>
</generator>
</id>
这里需要注意的是property的属性值必须与上面到User的映射所填写的name属性值一致,这样就完成了one-to-one的映射关系。
上面的过程都很简单,下面我来说说这里需要注意的地方:
1. 在设置属性ID的时候必须注意字段的长度,如笔者这样使用oracle的sequence来生成ID,其长度有14位之长,则应选择hibernate类型long,对应的实体中应选择Long,这样不会出现溢出的情况。
2. 在测试的时候必须要注意这两张表之间因为已经存在了一对一的关系,所以我们不能只写
user.setAddress(address);
而忽略了
address.setUser(user);
这样在做插入的时候会报出attempted to assign id from null one-to-one property: address的错误,这一点初学者会经常犯,笔者也是其中之一。
3. 如果不写cascade="all"或者写成cascade="none"的话,即使你写了
user.setAddress(address);
address.setUser(user);
也不会发生任何事情,只有user会被存储。
4. one-to-one的效率问题-------one-to-one在查询时,总是查出和主表关联的表,而且one-to-one的lazy属性只有false proxy no-proxy三种,没有true。outer-join="false"也只是徒增查询语句条数,把本来的一条sql语句变成多条。所以在one-to-one这种一对一的关系不是很强的情况下(one-to-one关系强即总是查出这所有的几个关联表),或者是在一张表中存在多个one-to-one的情况下,使用最好one-to-many来代替one-to-one。
关于父子关系(all-delete-orphan)
当关联双方存在父子关系,就可以在 set 处设定 cascade 为 all-delete-orphan
所谓父子关系,即指由父方控制子方的持久化圣明周期,子方对象必须和一个父方对象关联。如果删除父方对象,应该级联删除所有关联的子方对象;如果一个子方对象不再和一个父方对象关联,应该把这个子方对象删除。
all-deleteorphan 的能力:
1. 当保存或更新父方对象时,级联保存或更新所有关联的子方对象,相当于 cascade 为 save-update
2. 当删除父方对象时,级联删除所有关联的子方对象,相当于 cascade 为 delete
3. 删除不再和父方对象关联的所有子方对象
解除父子关系的 java 语句例如:
customer.getOrders().remove(order);
order.setCustomer(null);
tx.commit();
如果 cascade 属性取默认值 null,当解除父子关系时,会执行如下 sql:
update ORDER set CUSTOMER_ID=null where ID=2
如果要把它也删掉,则设置:
<set name="orders" cascade="all-delete-orphan" inverse="true">
<key column="CUSTOMER_ID" />
<one-to-many class="mypack.Order" />
再运行时就会执行:delete from ORDERS where CUSTOMER_ID=2 and ID=2;
cascade几种取值:
save-update: 级联保存(load以后如果子对象发生了更新,也会级联更新). 但它不会级联删除
delete: 级联删除, 但不具备级联保存和更新
all-delete-orphan: 在解除父子关系时,自动删除不属于父对象的子对象, 也支持级联删除和级联保存更新.
all: 级联删除, 级联更新,但解除父子关系时不会自动删除子对象.
delete-orphan:删除所有和当前对象解除关联关系的对象
none:...
级联保存和级联更新总是集合在一起的, 所以没单独的save 或 updata