(接上例)JPA中实现增删改查及事务控制

上例:使用EJB3的EntityBean连接数据库(http://blog.csdn.net/kunshan_shenbin/archive/2008/06/08/2525454.aspx)中介绍了如何在EJB3中使用实体Bean的方法。这次准备记录一下使用实体Bean实现增删改查及事务控制的方法。

需要修改下面几个文件:

BookDao.java

package com.cecltd.ejb3;

import java.util.List;

import com.cecltd.domain.Book;

public interface BookDao {

	public List getBookList();
	
	public Book getBook(int id);
	
	public void updateBook(Book book);
	
	public void insertBook(int id);
	
	public void deleteBook(int id);
}

BookDaoBean.java

package com.cecltd.ejb3.impl;

import java.util.List;

import javax.ejb.Remote;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import com.cecltd.domain.Book;
import com.cecltd.ejb3.BookDao;

@Stateless
@Remote(BookDao.class)
public class BookDaoBean implements BookDao {

	@PersistenceContext
    protected EntityManager em;
	
	public List getBookList() {
		
		Query query = em.createQuery("from Book order by ISBN asc");
        List list = query.getResultList();
        return list; 
	}
	
	public Book getBook(int id){
		
		return em.find(Book.class, Integer.valueOf(id));
	}
	
	@TransactionAttribute(TransactionAttributeType.REQUIRED)
	public void updateBook(Book book) {
		
		em.merge(book);
	}
	
	@TransactionAttribute(TransactionAttributeType.REQUIRED)
	public void insertBook(int id) {
		
		Book book = new Book();
		book.setNM("复制书");
		book.setCNT("复制书内容概要");
		book.setISBN(getBook(id).getISBN());
		book.setPBLDT(getBook(id).getPBLDT());
		em.persist(book);
	}

	@TransactionAttribute(TransactionAttributeType.REQUIRED)
	public void deleteBook(int id) {
		
		em.remove(getBook(id));
	}
}

EntityBeanClient.java

package test;

import java.io.UnsupportedEncodingException;
import java.sql.SQLException;
import java.util.List;
import java.util.Properties;

import javax.naming.InitialContext;
import javax.naming.NamingException;

import com.cecltd.domain.Book;
import com.cecltd.ejb3.BookDao;

public class EntityBeanClient {

	public static void main(String[] args) throws NamingException, SQLException, UnsupportedEncodingException {
		
		Properties props = new Properties();
        props.setProperty("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory");
        props.setProperty("java.naming.provider.url", "127.0.0.1:1099");
        props.setProperty("java.naming.factory.url.pkgs", "org.jboss.naming:org.jnp.interfaces");
		InitialContext ctx = new InitialContext(props);

        BookDao bookDao = (BookDao)ctx.lookup("BookDaoBean/remote");
        List list = bookDao.getBookList();
        for (int i = 0; i < list.size(); i++) {
        	Book book = (Book)list.get(i);
			System.out.println(book.getID() + "  " + book.getNM() + "  " + book.getISBN());
		}
        Book book = bookDao.getBook(1);
        book.setNM("深入浅出 Hibernate");
        bookDao.updateBook(book);
        System.out.println(bookDao.getBook(1).getNM());;
        
        System.out.println(bookDao.getBookList().size());
        bookDao.insertBook(1);
        System.out.println(bookDao.getBookList().size());
        bookDao.deleteBook(14);
        System.out.println(bookDao.getBookList().size());
	}
}

==============================================================

关于事物:JPA允许使用@TransactionAttribute 注释来定义一个事物。其参数的含义是:

1.REQUIRED:方法在一个事务中执行,如果调用的方法已经在一个事务中,则使用该事务,否则将创建一
个新的事务。
2.MANDATORY:如果运行于事务中的客户调用了该方法,方法在客户的事务中执行。如果客户没有关联到
事务中,容器就会抛出TransactionRequiredException。如果企业bean 方法必须用客户事务则采用Mandatory 属性。
3.REQUIRESNEW:方法将在一个新的事务中执行,如果调用的方法已经在一个事务中,则暂停旧的事务。在
调用结束后恢复旧的事务。
4.SUPPORTS:如果方法在一个事务中被调用,则使用该事务,否则不使用事务。
5.NOT_SUPPORTED:如果方法在一个事务中被调用,容器会在调用之前中止该事务。在调用结束后,容器
会恢复客户事务。如果客户没有关联到一个事务中,容器不会在运行入该方法前启动一个新的事务。用
NotSupported 属性标识不需要事务的方法。因为事务会带来更高的性能支出,所以这个属性可以提高性能。
6.Never:如果在一个事务中调用该方法,容器会抛出RemoteException。如果客户没有关联到一个事务中,
容器不会在运行入该方法前启动一个新的事务。
如果没有指定参数,@TransactionAttribute 注释使用REQUIRED 作为默认参数。

详细请参阅:http://blog.csdn.net/zxl315/archive/2008/04/03/2246201.aspx

==============================================================

关于实体bean中主键@GeneratedValue注释的参数:

一般需要根据数据库而定。MSSQL,MYSQL使用strategy = GenerationType.IDENTITY;而Oracle则使用GenerationType.SEQUENCE;当不能确定时,使用strategy = GenerationType.AUTO比较保险。

==============================================================

关于MYSQL中文乱码问题

因为当前使用的是中文环境,请确保mysql-ds.xml文件中connection-url属性是否有追加了characterEncoding=gbk

下面给出一个范例:

<?xml version="1.0" encoding="UTF-8"?>

<!-- $Id: mysql-ds.xml 63175 2007-05-21 16:26:06Z rrajesh $ -->
<!--  Datasource config for MySQL using 3.0.9 available from:
http://www.mysql.com/downloads/api-jdbc-stable.html
-->

<datasources>
  <local-tx-datasource>
    <jndi-name>MySqlDS</jndi-name>
    <connection-url>jdbc:mysql://127.0.0.1:3306/compass?characterEncoding=gbk</connection-url>
    <driver-class>com.mysql.jdbc.Driver</driver-class>
    <user-name>root</user-name>
    <password>root</password>
    <exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter</exception-sorter-class-name>
    <!-- should only be used on drivers after 3.22.1 with "ping" support
    <valid-connection-checker-class-name>org.jboss.resource.adapter.jdbc.vendor.MySQLValidConnectionChecker</valid-connection-checker-class-name>
    -->
    <!-- sql to call when connection is created
    <new-connection-sql>some arbitrary sql</new-connection-sql>
      -->
    <!-- sql to call on an existing pooled connection when it is obtained from pool - MySQLValidConnectionChecker is preferred for newer drivers
    <check-valid-connection-sql>some arbitrary sql</check-valid-connection-sql>
      -->

    <!-- corresponding type-mapping in the standardjbosscmp-jdbc.xml -->
    <metadata>
       <type-mapping>mySQL</type-mapping>
    </metadata>
  </local-tx-datasource>
</datasources>

其他参考资源:http://www.matrix.org.cn/thread.shtml?topicId=34877&forumId=38

你可能感兴趣的:((接上例)JPA中实现增删改查及事务控制)