Specify the sequence:
package com.liguoliang.jee.vo; /** * Represents Client. * @author Guoliang * */ @Entity @Table (name="Client") public class Client { @Id @Column(name="id") @SequenceGenerator(name="my_seq", sequenceName="CLIENT_ID_SEQUENCE") @GeneratedValue(strategy = GenerationType.SEQUENCE ,generator="my_seq") private int id; @Column(name="name") String name; public Client() { // TODO Auto-generated constructor stub } //.... }
Code before change:
/** * insert new client. * @param client */ @Insert("INSERT INTO CLIENT(name) VALUES (#{name})") @Options(useGeneratedKeys=true, keyProperty="id") void insert(Client client);
1. Directly Remove @Options(useGeneratedKeys=true, keyProperty=”id”)
2. Replace @Options with @SelectKey:
/** * insert new client. * @param client */ @Insert("INSERT INTO CLIENT(name) VALUES (#{name})") @SelectKey( keyProperty = "id", before = true, resultType = Integer.class, statement={" select CLIENT_ID_SEQUENCE.nextval AS id from dual"} ) void insert(Client client);
Spring doesn’t directly manage transactions, it comes with a selection of transaction managers, such as: DataSourceTransactionManager, HibernateTransactionManager, JpaTransactionManager etc,.
There are two way to manage transaction in Spring: based on programming or configuration. no matter which way we choose, we always need to define the beans needed:
Here we define a transactionManager using hibernateTransactionManager, and a transaction template:
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="globalRollbackOnParticipationFailure" value="false" />
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="txTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="transactionManager"></property>
</bean>
‘sessionFactory’ bean configuration: http://liguoliang.com/2012/using-spring-jdbc-template/
And now, I’ll show you the the two transaction management ways:
@Autowired private TransactionTemplate txTemplate; /** * Insert new user using transactionTemplate. * @param user */ public void insertUserByTxTemplate(final User user) { txTemplate.execute(new TransactionCallback() { @Override public Void doInTransaction(TransactionStatus txStatus) { try { Session session = sessionFactory.getCurrentSession(); session.save(user); throw new RuntimeException("Exception throwed!"); } catch (Exception e) { txStatus.setRollbackOnly(); } return null; } }); }
Manage transaction using txTemplate.execute().
using annotation
/** * Insert new user using transaction manager. * @param user */ @Transactional(propagation=Propagation.REQUIRED, readOnly=false, rollbackFor=RuntimeException.class) public void insertUser(User user) { Session session = sessionFactory.getCurrentSession(); // SessionFactoryUtils.openSession(sessionFactory); user.setLogin_name(user.getName()); session.save(user); // throw new RuntimeException("RunTimeException for Transaction testing..."); }
If you are using STS(SpringSource tool suite) you can see there is an indicator:
Links:
Spring Transaction – automatic rollback of previous db updates when one db update failes
Spring’s @Transactional does not rollback on checked exceptions
Transaction strategies: Understanding transaction pitfalls
Here is a simple example about configuration of Spring3 and Hibernate4.
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost/mini-liguoliang.com" />
<property name="username" value="root" />
<property name="password" value="password" />
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="packagesToScan" value="com.liguoliang.spring.po"></property>
<property name="hibernateProperties">
<props>
<prop key="dialect">org.hibernate.dialect.MySQLDialect</prop>
</props>
</property>
</bean>
<context:component-scan base-package="com.liguoliang.spring"></context:component-scan>
package com.liguoliang.spring.po; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; @Entity @javax.persistence.Table(name="ACCT_USER") public class User { @javax.persistence.Id @GeneratedValue(strategy = GenerationType.AUTO) private int id; private String name; private String login_name; public String getLogin_name() { return login_name; } public void setLogin_name(String login_name) { this.login_name = login_name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String toString() { return "User - " + name + " [" + id + "]"; } }
Note the annotation: @Entity
package com.liguoliang.spring; import java.io.File; import java.util.Date; import javax.persistence.Entity; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistryBuilder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.orm.hibernate4.SessionFactoryUtils; import org.springframework.stereotype.Repository; import com.liguoliang.spring.po.User; @Repository public class UserHibernateDAO { private SessionFactory sessionFactory; @Autowired public UserHibernateDAO(SessionFactory sessionFactory) { this.sessionFactory = sessionFactory; } public User getUserByID(int id) { Session session = SessionFactoryUtils.openSession(sessionFactory); return (User) session.get(User.class, id); } }
We need a hibernateBean instance:
package com.liguoliang.spring.web; @Controller @RequestMapping(value="/spring/user") public class ControllerUser { @Autowired private UserHibernateDAO userHibernateDAO; @RequestMapping(value={"", "list"}) public String list(Model model) { // We just print the user info in the console. System.out.println("userName: " + userHibernateDAO.getUserByID(10).toString()); return "userList"; } }
When list() is called, user with the id ’10’ will be loaded by the hibernateDAO, and printed in the console.
http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html
Figure 9.2 Data Access Object sequence diagram
The BusinessObject represents the data client. It is the object that requires access to the data source to obtain and store data. A BusinessObject may be implemented as a session bean, entity bean, or some other Java object, in addition to a servlet or helper bean that accesses the data source.
The DataAccessObject is the primary object of this pattern. The DataAccessObject abstracts the underlying data access implementation for the BusinessObject to enable transparent access to the data source. The BusinessObject also delegates data load and store operations to the DataAccessObject.
This represents a data source implementation. A data source could be a database such as an RDBMS, OODBMS, XML repository, flat file system, and so forth. A data source can also be another system (legacy/mainframe), service (B2B service or credit card bureau), or some kind of repository (LDAP).
This represents a Transfer Object used as a data carrier. The DataAccessObject may use a Transfer Object to return data to the client. The DataAccessObject may also receive the data from the client in a Transfer Object to update the data in the data source.
在Hibernate 或一些类似框架中, 常常会有这样一个无聊的问题: Cascade与Inverse的区别.
但事实上这个问题首先需要承认他们有相同点,才能有类似的问题, 但这两者之间我个人认为几乎没有关系 – 他们是不同的两个事物.
Cascade意在是否在一方变化时, 另外关系一方是否随之变化
而Inverse则说明该关系由哪一方负责维系
—-我不认为他们有什么区别 以为他们根本没有相似之处
Cascade常见的两种:
ALL – 非常强的关系, 通常为拥有型, 如 学生拥有地址, 在学生保存时, 其地址也被保存, 当被删除时, 地址也随之删除
PERSIS – 较强的关系, 如学生跟科目, 当新的科目保存时, 学生也被保存, 但删除科目时, 学生信息并不随之删除.
Inverse:
默认为False.
当关系为一对多时, inverse应设置为true, 意味有对方负责维系关系
// Proudly powered by Apache, PHP, MySQL, WordPress, Bootstrap, etc,.