測試用的 GeneralEAO, EntityManagerHelper
雖然不知道這樣算不算 GeneralEAO, 不過這兩個 class 已經寫好幾次拿來做測試了, 很方便用.
到後來乾脆直接摳來摳去, 反正要測試的時候就可以用, 看習慣.
因為很方便, 所以記一下, 不用以後又重寫. 順便如果有不足的再改.
首先是 ThreadLocal 的 EntityManagerHelper
public class EntityManagerHelper {
private static final ThreadLocal<EntityManager> threadLocal = new ThreadLocal<EntityManager>();
private static EntityManagerFactory emf = Persistence.createEntityManagerFactory("test");
public static EntityManager getEntityManager() {
EntityManager em = threadLocal.get();
if ( em == null ) {
em = emf.createEntityManager();
threadLocal.set(em);
}
return em;
}
}
然後是 GeneralEAO
public class GeneralEAO {
private static final Logger logger = Logger.getLogger(GeneralEAO.class);
public synchronized static void create(T t) {
logger.info("create " + t);
EntityManager em = EntityManagerHelper.getEntityManager();
em.getTransaction().begin();
em.persist(t);
em.getTransaction().commit();
}
public synchronized static T find(Class extends T> cls, Object key) {
logger.info("find " + cls + " where id = " + key);
return (T) EntityManagerHelper.getEntityManager().find(cls, key);
}
public synchronized static void update(T t) {
logger.info("update " + t );
EntityManager em = EntityManagerHelper.getEntityManager();
em.getTransaction().begin();
em.merge(t);
em.getTransaction().commit();
}
public synchronized static void updateCommit(Query q) {
logger.info("update with query " + q );
EntityManager em = EntityManagerHelper.getEntityManager();
em.getTransaction().begin();
q.executeUpdate();
em.getTransaction().commit();
}
public synchronized static void delete(T t) {
logger.info("delete " + t );
EntityManager em = EntityManagerHelper.getEntityManager();
em.getTransaction().begin();
em.remove( em.merge(t) );
em.getTransaction().commit();
}
public synchronized static T undo(T t) {
logger.info("undo " + t );
EntityManager em = EntityManagerHelper.getEntityManager();
t = em.merge(t);
em.refresh( t );
return t;
}
public synchronized static Query namedQuery(String name) {
logger.info("namedQuery " + name );
return EntityManagerHelper.getEntityManager().createNamedQuery(name);
}
public synchronized static Query query(String queryString) {
logger.info("query: " + queryString );
return EntityManagerHelper.getEntityManager().createQuery(queryString);
}
public synchronized static void detachAll() {
logger.info("detach all");
EntityManagerHelper.getEntityManager().clear();
}
}
Posted at 12:53上午 八月 21, 2008 by shooeugenesea in EJB3 | 迴響[0]
SCBCD5 passed
啊? 過了? 拿到成績單還有點不敢相信.
這兩天因為考試券要到期了, 上網找看有沒有考題,
好不容易找到一份看起來還不錯的下載來看完.
裡面用 EJB3 規格書出了大概一百二十題 (結果只考一題 XD).
藉由這份考題讓我有機會去多看一下規格書,
才覺得 EJB3 in Action 完全是作者特地將 EJB3 的部份用簡單的話來描述,
實際上 EJB3 包含的東西更多更廣.
隨著看考題練習也愈來愈感覺到自己學習到的部份只是九牛一毛,
九牛一毛我還忘掉大半才慘.
EJB3 範圍這麼大, 要濃縮成 61 題選擇真的是很難.
所以裡面都在考觀念, 光是觀念就考不完了, 細節沒考很多.
所以在忘記大半的情況下, 還是用推想怎樣才合理的方式過了.
嗯...就這樣
Posted at 11:08下午 八月 09, 2008 by shooeugenesea in EJB3 | 迴響[0]
EJB3 - Tuning
private Long version;
@Version
@Column(name="VERSION")
public Long getVersion() {
return version;
}
public void setVersion(Long version) {
this.version = version;
}
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="EMPLOYEE_TYPE", discriminatorType=DiscriminatorType.STRING)
public abstract class Employee implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String name;
private String type;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
@Entity
@DiscriminatorValue(value="P")
public class Programmer extends Employee implements Serializable {
private static final long serialVersionUID = 1L;
private String programmerDesciption;
public String getProgrammerDesciption() {
return programmerDesciption;
}
public void setProgrammerDesciption(String programmerDesciption) {
this.programmerDesciption = programmerDesciption;
}
}
@Entity
@DiscriminatorValue(value="S")
public class Sales extends Employee implements Serializable {
private static final long serialVersionUID = 1L;
private String salesDescription;
public String getSalesDescription() {
return salesDescription;
}
public void setSalesDescription(String salesDescription) {
this.salesDescription = salesDescription;
}
}
private void queryAllEmployee() {
String name = "PDP";
Query q = GeneralEAO.query("from Employee e where e.name = '" + name + "'");
for (Object object : q.getResultList()) {
System.out.println(object);
}
}
有 parameter binding
private void queryAllEmployee() {
String name = "PDP";
Query q = GeneralEAO.query("from Employee e where e.name = :name");
q.setParameter("name", name);
for (Object object : q.getResultList()) {
System.out.println(object);
}
}
@Entity
@NamedQueries({@NamedQuery(name="findAllEmployee", query="from Employee")})
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="EMPLOYEE_TYPE", discriminatorType=DiscriminatorType.STRING)
public abstract class Employee implements Serializable {
private void queryAllEmployee() {
Query q = GeneralEAO.namedQuery("findAllEmployee");
for (Object object : q.getResultList()) {
System.out.println(object);
}
}
public static Query namedQuery(String name) {
return EntityManagerHelper.getEntityManager().createNamedQuery(name);
}
private void testFetchQuery( Object calendarId ) {
Query q = GeneralEAO.query("select c from XCalendar c join fetch c.calendarLob join fetch c.calendarDetails where c.id = :cid");
q.setParameter("cid", calendarId);
XCalendar c = (XCalendar) q.getSingleResult();
GeneralEAO.detachAll();
System.out.println(c.getCalendarLob());
for (XCalendarDetail xCalendarDetail : c.getCalendarDetails()) {
System.out.println(xCalendarDetail.getName());
}
}
public void test() {
String name = "TESTNAME";
List< Employee > list = eao.query("from Employee").getResultList();
for (Employee employee : list) {
employee.setName(name);
eao.update(employee);
}
}
可是這種作法會導致很多個 update SQL statement.
public void test() {
String name = "TESTNAME";
Query q = eao.query("update Employee e set e.name = :name");
q.setParameter("name", name);
q.executeUpdate();
}
@OneToMany(cascade=CascadeType.ALL, mappedBy="owner")
@OrderBy(value="price asc")
public List< Certification > getCerts() {
if ( certs == null ) {
certs = new ArrayList< Certification >();
}
return certs;
}
這樣在 SQL statement 可建立 order by certs0_.price asc 的結果. 可是 order by 的效果很花資源, 所以如果不是必需的就不要用 @OrderBy, 或是情況允許就在 order by 的欄位加上 index.
Posted at 11:55上午 八月 08, 2008 by shooeugenesea in EJB3 | 迴響[0]
只用 transactional cache 可讀 stale data 的方式
public class TestMain {
private static final Logger logger = Logger.getLogger(TestMain.class.getName());
public static void main(String[] args) {
TestMain test = new TestMain();
test.test();
}
boolean cached = false;
boolean cachedAndUpdated = false;
private void test() {
Long id = prepareData();
// new thread to wait variable cached, if true then update Employee
newThreadToUpdateEmployee( id );
// query will trigger transactional cache
queryAll();
// now can see there is transactional cache and have no DB round trip
findEmployee( id );
// let Update-Employee thread to update Employee
logger.info( "Set up cached to true." );
cached = true;
logger.info( "Wait for cachedAndUpdated.." );
// Update-Employee will set to true after Employee updated, then find Employee again
while ( true ) {
if ( cachedAndUpdated ) {
logger.info( "cachedAndUpdated is true.." );
// now it's stale data
logger.info( GeneralEAO.retrieve(Employee.class, id).toString() );
break;
}
}
// This way can read correct data
GeneralEAO.detachAll();
logger.info(GeneralEAO.retrieve(Employee.class, id).toString());
}
private void newThreadToUpdateEmployee(final Long id) {
new Thread( "Update-Employee" ) {
@Override
public void run() {
while ( true ) {
if ( cached ) {
logger.info("cached, start find..");
Employee e = GeneralEAO.retrieve(Employee.class, id);
e.setName("TESTESTEST");
GeneralEAO.update(e);
GeneralEAO.transactionCommit();
cachedAndUpdated = true;
break;
}
}
}
}.start();
}
private void findEmployee(Long id) {
logger.info( "start findEmployee.." );
logger.info( GeneralEAO.retrieve(Employee.class, id).toString() );
}
private void queryAll() {
logger.info( "start queryAll.." );
Query q = GeneralEAO.query("from Employee");
for (Object object : q.getResultList()) {
logger.info(object.toString());
}
}
private Long prepareData() {
Employee e = new Employee();
e.setName("Rock");
Certification scjp = new Certification();
scjp.setName("scjp");
scjp.setPrice(Double.valueOf(Math.random() * 100));
scjp.setOwner(e);
Certification scwcd = new Certification();
scwcd.setName("scwcd");
scwcd.setPrice(Double.valueOf(Math.random() * 100));
scwcd.setOwner(e);
Certification scbcd = new Certification();
scbcd.setPrice(Double.valueOf(Math.random() * 100));
scbcd.setName("scbcd");
scbcd.setOwner(e);
e.getCerts().add(scjp);
e.getCerts().add(scwcd);
e.getCerts().add(scbcd);
GeneralEAO.create(e);
GeneralEAO.transactionCommit();
GeneralEAO.detachAll();
return e.getId();
}
}
Posted at 01:09上午 八月 05, 2008 by shooeugenesea in EJB3 | 迴響[0]
EJB3 - Transactions
@TransactionManagement(TransactionManagementType.CONTAINER)
@Stateless
public class TestStatelessBean implements TestStatelessLocal {
@PersistenceContext
private EntityManager em;
public void createPerson() {
Person p = new Person();
p.setName("PERSON " + Calendar.getInstance().getTimeInMillis());
em.persist(p);
}
}
但這個例子就不行了, 使用了 BEAN 就需要自己控制 transaction, 所以沒有 transaction.begin 會出現 javax.persistence.TransactionRequiredException
@TransactionManagement(TransactionManagementType.BEAN)
@Stateless
public class TestStatelessBean implements TestStatelessLocal {
@PersistenceContext
private EntityManager em;
public void createPerson() {
Person p = new Person();
p.setName("PERSON " + Calendar.getInstance().getTimeInMillis());
em.persist(p);
}
}
# 用 t 代表 transaction
# 用 c 代表 caller
REQUIRED c 無 t 則建 t, c 有 t 就 join t
REQUIRED_NEW c 無 t 則建 t, c 有 t 就先 suspended 後建一 t 自己用
SUPPORTS c 無 t 則不用 t, c 有 t 就 join t
MANDATORY c 無 t 則丟 EJBTransactionRequiredException, c 有 t 就 join t
NOT_SUPPORTED c 無 t 則不用 t, c 有 t 就 suspended 然後不用 t 執行自己的程式
NEVER c 無 t 則不用 t, c 有 t 就丟 EJBException
@TransactionManagement(TransactionManagementType.CONTAINER)
@Stateless
public class TestStatelessBean implements TestStatelessLocal {
@PersistenceContext
private EntityManager em;
@Resource
SessionContext ctx;
public void createPerson() {
try {
Person p = new Person();
p.setName("PERSON " + Calendar.getInstance().getTimeInMillis());
em.persist(p);
throw new Exception();
} catch (Exception e) {
e.printStackTrace();
ctx.setRollbackOnly(); // 沒這行就會資料進 DB
}
}
}
@ApplicationException(rollback=false)
public class NotRollbackException extends Exception {}
@ApplicationException(rollback=true)
public class RollbackException extends Exception {}
@TransactionManagement(TransactionManagementType.CONTAINER)
@Stateless
public class TestStatelessBean implements TestStatelessLocal {
@PersistenceContext
private EntityManager em;
@Resource
SessionContext ctx;
public String testInterceptor() {
return "interceptor passed.";
}
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void show() throws NotRollbackException {
Person p = new Person();
p.setName("PERSON IN SHOW " + Calendar.getInstance().getTimeInMillis());
em.persist(p);
throw new NotRollbackException(); // 丟了還是 commit
}
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void createPerson() throws RollbackException {
Person p = new Person();
p.setName("PERSON IN CREATE " + Calendar.getInstance().getTimeInMillis());
em.persist(p);
throw new RollbackException(); // 丟了就不會 commit
}
}
@Resource
private UserTransaction userTransaction
private UserTransaction userTransaction;
@PostConstruct
private void postConstruct() {
try {
Context context = new InitialContext();
userTransaction = (UserTransaction) context.lookup("java:comp/UserTransaction");
System.out.println("look up UserTransaction: " + userTransaction);
} catch (NamingException ex) {
Logger.getLogger(TestStatelessBean.class.getName()).log(Level.SEVERE, "No such name: java:comp/UserTransaction", ex);
}
}
@Resource
private EJBContext context;
@Resource
private UserTransaction userTransaction;
@PostConstruct
private void postConstruct() {
userTransaction = context.getUserTransaction();
}
@TransactionManagement(TransactionManagementType.BEAN)
@Stateless
public class TestStatelessBean implements TestStatelessLocal {
@Resource
private UserTransaction userTransaction;
@PersistenceContext
private EntityManager em;
public void changePersonName() throws RollbackException {
try {
try {
userTransaction.begin();
if (personExists()) {
Person p = findPerson();
changeName(p);
}
userTransaction.commit();
} catch (Exception ex) {
userTransaction.rollback();
Logger.getLogger(TestStatelessBean.class.getName()).log(Level.SEVERE, null, ex);
}
} catch (Exception ex) {
Logger.getLogger(TestStatelessBean.class.getName()).log(Level.SEVERE, null, ex);
}
}
private void changeName(Person p) {
p.setName("KKK 123");
System.out.println(p.getName());
em.merge(p);
em.flush();
}
private Person findPerson() {
return em.find(Person.class, Long.valueOf(36));
}
private boolean personExists() {
return ((Long) em.createQuery("select COUNT(p) from Person p").getSingleResult()) > 0;
}
}
STATUS_PREPARED : 因為 two phase commit 的關係, 有個階段是所有 resource manager 都準備好要 commmit 了.
STATUS_PREPARING : 想要 commit 了, 在等待 resource manager 的 response.
Posted at 10:07下午 七月 28, 2008 by shooeugenesea in EJB3 | 迴響[0]
EJB3 - 打包EJB3
type desc 部署檔 contexts
CAR Client application archives application-client.xml Java client for EJBs
EAR Enterprise application archives application.xml Java modules
EJB-JAR EJB Java archives ejb-jar.xml Session beans, MDBs, entities, persistence.xml
RAR Resource adapter archives ra.xml Resource adapters
WAR Web application archives web.xml Web app. persistence.xml
META-INF/application.xml
TestEJB3_June2008-ejb.jar
TestEJB3_June2008-war.war
lib/derbyclient.jar
<?xml version="1.0" encoding="UTF-8"?>
<application version="5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/application_5.xsd">
<display-name>TestEJB3_June2008</display-name>
<module>
<ejb>TestEJB3_June2008-ejb.jar</ejb>
</module>
<module>
<web>
<web-uri>TestEJB3_June2008-war.war</web-uri>
<context-root>/TestEJB3_June2008-war</context-root>
</web>
</module>
</application>
if ( 為 .jar ) {
if ( 有ejb-jar.xml 或 class使用EJB3 annotation ) {
判斷為EJB-JAR (EJB-JAR Module)
} else {
if ( 是否有application-client.xml 或 manifest 中指定 Main-Class ) {
判斷為CAR (Client Application Module)
} else {
error! 未知的 module 型態
}
}
} else {
if ( 為 .war ) {
判斷為 WAR (Web Module)
} else {
if ( 為 .rar ) {
判斷為 RAR (Resource Adapter Module)
} else {
error! 未知的 module 型態
}
}
}
@PersistenceUnit(unitName = "lib/kk.jar#kk")
private EntityManagerFactory emf;
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="oraclePU" transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>jdbc/oracle</jta-data-source>
<properties>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.OracleDialect"/>
</properties>
</persistence-unit>
</persistence>
Posted at 08:45下午 七月 20, 2008 by shooeugenesea in EJB3 | 迴響[0]
EJB3 - MessageDrivenBean
@Stateless(name="SimpleStatelessBean1")
public class SimpleStatelessBean1 implements SimpleStatelessLocal {
@Resource(name="TestQueueConnectionFactory")
private ConnectionFactory connectionFactory;
@Resource(name="jms/TestQueueDestination")
private Destination destination;
public String simpleShow() {
try {
Connection conn = connectionFactory.createConnection();
Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer messageProducer = session.createProducer(destination);
TextMessage message = session.createTextMessage();
message.setText("This is text message");
messageProducer.send(message);
messageProducer.close();
session.close();
conn.close();
} catch (JMSException ex) {
throw new RuntimeException( ex );
}
return this + ":This is simple show";
}
}
java.lang.IllegalArgumentException: MQJMSRA_AS4001: setAcknowledgeMode:Invalid acknowledgeMode=DUPS_OK_ACKNOWLEDGE
的錯誤
@MessageDriven(mappedName = "jms/TestQueueDestination", activationConfig = {
@ActivationConfigProperty(propertyName = "destinationName", propertyValue = "TestQueueDestination"),
@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
@ActivationConfigProperty(propertyName = "connectionFactoryJndiName", propertyValue = "TestQueueConnectionFactory"),
@ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge")
})
public class SimpleStatelessBeanMDBBean implements MessageListener {
@PostConstruct
private void postConstruct() {
System.out.println("create.." + this);
}
public void onMessage(Message message) {
try {
TextMessage msg = (TextMessage) message;
System.out.println("Receive message:" + msg.getText());
message.acknowledge();
} catch (JMSException ex) {
throw new RuntimeException( ex );
}
}
@PreDestroy
private void preDestroy() {
System.out.println("destroy.." + this);
}
}
@MessageDriven(mappedName = "TestTopicDestination", activationConfig = {
@ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"),
@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Topic"),
@ActivationConfigProperty(propertyName = "subscriptionDurability", propertyValue = "Durable"),
@ActivationConfigProperty(propertyName = "clientId", propertyValue = "TopicMDBBean1"),
@ActivationConfigProperty(propertyName = "subscriptionName", propertyValue = "TopicMDBBean1")
})
public class TopicMDBBean1 implements MessageListener {
public void onMessage(Message message) {
try {
TextMessage msg = (TextMessage) message;
System.out.println(this + " receive " + msg.getText());
} catch (JMSException ex) {
Logger.getLogger(TopicMDBBean1.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
@MessageDriven(mappedName = "TestTopicDestination", activationConfig = {
@ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"),
@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Topic"),
@ActivationConfigProperty(propertyName = "subscriptionDurability", propertyValue = "Durable"),
@ActivationConfigProperty(propertyName = "clientId", propertyValue = "TopicMDBBean2"),
@ActivationConfigProperty(propertyName = "subscriptionName", propertyValue = "TopicMDBBean2")
})
public class TopicMDBBean2 implements MessageListener {
public void onMessage(Message message) {
try {
TextMessage msg = (TextMessage) message;
System.out.println(this + " receive " + msg.getText());
} catch (JMSException ex) {
Logger.getLogger(TopicMDBBean2.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
com.sun.messaging.jmq.util.selector.SelectorFormatException: Unknown operator: [25,is]: "booleanFlag is true"的訊息.
// MessageConsumer codes start
...
message.setLongProperty("flag", Long.valueOf(5));
...
// MessageConsumer codes end
@MessageDriven(mappedName = "TestTopicDestination", activationConfig = {
@ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"),
@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Topic"),
@ActivationConfigProperty(propertyName = "subscriptionDurability", propertyValue = "Durable"),
@ActivationConfigProperty(propertyName = "clientId", propertyValue = "TopicMDBBean3"),
@ActivationConfigProperty(propertyName = "subscriptionName", propertyValue = "TopicMDBBean3"),
@ActivationConfigProperty(propertyName = "messageSelector", propertyValue = "flag = 5")
})
public class TopicMDBBean3 implements MessageListener {
public void onMessage(Message message) {
try {
TextMessage msg = (TextMessage) message;
System.out.println(this + " receive " + msg.getText());
} catch (JMSException ex) {
Logger.getLogger(TopicMDBBean3.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
@MessageDriven(mappedName = "TestTopicDestination", activationConfig = {
@ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"),
@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Topic"),
@ActivationConfigProperty(propertyName = "subscriptionDurability", propertyValue = "Durable"),
@ActivationConfigProperty(propertyName = "clientId", propertyValue = "TopicMDBBean4"),
@ActivationConfigProperty(propertyName = "subscriptionName", propertyValue = "TopicMDBBean4")
})
public class TopicMDBBean4 implements MessageListener {
@Resource(name="TestQueueConnectionFactory")
private ConnectionFactory connectionFactory;
@Resource(name="jms/TestQueueDestination")
private Destination destination;
public void onMessage(Message message) {
try {
TextMessage msg = (TextMessage) message;
System.out.println(this + " receive " + msg.getText());
sendAgain();
} catch (JMSException ex) {
Logger.getLogger(TopicMDBBean4.class.getName()).log(Level.SEVERE, null, ex);
}
}
private void sendAgain() throws JMSException {
Connection connection = connectionFactory.createConnection();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer messageProducer = session.createProducer(destination);
TextMessage message = session.createTextMessage();
message.setText("Send message again from " + this);
messageProducer.send(message);
messageProducer.close();
session.close();
connection.close();
}
}
Posted at 09:02下午 七月 13, 2008 by shooeugenesea in EJB3 | 迴響[0]
EJB3 - Session bean
public interface TestRemote extends Remote { ... }
就算程式裡面沒寫繼承Remote, container還是會在byte code階段插入繼承Remote的動作
@Stateful(name="SimpleStatefulBean", mappedName="ejb/SimpleStatefulBean")
public class SimpleStatefulBean implements SimpleStatefulRemote {
private Logger logger = Logger.getLogger("SimpleStatefulBean");
private byte[] b = new byte[100000];
{
for ( int i = 0; i < b.length; i++ ) {
b[i] = (byte) 100;
}
}
public String simpleShow() {
return this + ":This is simple show" + b;
}
@PostConstruct
public void postConstruct() {
logger.info("create " + this);
}
@PreDestroy
public void preDestroy() {
logger.info("destroy " + this);
}
@PostActivate
public void postActivate() {
logger.info("activate " + this);
}
@PrePassivate
public void prePassivate() {
logger.info("passivate " + this);
}
@Remove
public void remove() {
logger.info("remove " + this);
}
}
放interceptor的lifecycle callback
@Stateless
@Interceptors(value={SimpleInterceptor.class})
public class SimpleStatelessBean implements SimpleStatelessLocal {
private Logger logger = Logger.getLogger("SimpleStatelessBean");
@Resource(name="TestQueueConnectionFactory")
private ConnectionFactory connectionFactory;
@Resource(name="jms/TestQueueDestination")
private Destination destination;
public String simpleShow() {
try {
Connection conn = connectionFactory.createConnection();
Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer messageProducer = session.createProducer(destination);
TextMessage message = session.createTextMessage();
message.setText("This is text message");
messageProducer.send(message);
messageProducer.close();
session.close();
conn.close();
} catch (JMSException ex) {
throw new RuntimeException( ex );
}
return this + ":This is simple show";
}
}
public class SimpleInterceptor {
Logger logger = Logger.getLogger("SimpleStatefulBeanInterceptor");
@PostConstruct
public void onCreate(InvocationContext ic) {
try {
logger.info("create " + this);
ic.proceed();
} catch (Exception ex) {
Logger.getLogger(SimpleInterceptor.class.getName()).log(Level.SEVERE, null, ex);
}
}
@AroundInvoke
public Object aroundInvoke(InvocationContext ctx) throws Exception {
logger.info(ctx + " is invoked.");
return ctx.proceed();
}
@PreDestroy
public void onDestroy(InvocationContext ic) {
try {
logger.info("destroy " + this);
ic.proceed();
} catch (Exception ex) {
Logger.getLogger(SimpleInterceptor.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
stateful bean的@PrePassivate, @PostActivate也可放interceptor
@Interceptors(value={SimpleInterceptor.class})
@Stateful(name="SimpleStatefulBean", mappedName="ejb/SimpleStatefulBean")
public class SimpleStatefulBean implements SimpleStatefulRemote {
private byte[] b = new byte[100000];
{
for ( int i = 0; i < b.length; i++ ) {
b[i] = (byte) 100;
}
}
public String simpleShow() {
return this + ":This is simple show" + b;
}
@Remove
public void remove() {
Logger.getLogger("SimpleStatefulBean").info("remove " + this);
}
}
public class SimpleInterceptor {
@PostConstruct
public void onCreate(InvocationContext ic) {
try {
Logger.getLogger(SimpleInterceptor.class.getName()).info("create " + this);
ic.proceed();
} catch (Exception ex) {
Logger.getLogger(SimpleInterceptor.class.getName()).log(Level.SEVERE, null, ex);
}
}
@PostActivate
public void onActivate(InvocationContext ic) {
try {
Logger.getLogger(SimpleInterceptor.class.getName()).info("activate " + this);
ic.proceed();
} catch (Exception ex) {
Logger.getLogger(SimpleInterceptor.class.getName()).log(Level.SEVERE, null, ex);
}
}
@PrePassivate
public void onPassivate(InvocationContext ic) {
try {
Logger.getLogger(SimpleInterceptor.class.getName()).info("passivate " + this);
ic.proceed();
} catch (Exception ex) {
Logger.getLogger(SimpleInterceptor.class.getName()).log(Level.SEVERE, null, ex);
}
}
@AroundInvoke
public Object aroundInvoke(InvocationContext ctx) throws Exception {
Logger.getLogger(SimpleInterceptor.class.getName()).info(ctx + " is invoked.");
return ctx.proceed();
}
@PreDestroy
public void onDestroy(InvocationContext ic) {
try {
Logger.getLogger(SimpleInterceptor.class.getName()).info("destroy " + this);
ic.proceed();
} catch (Exception ex) {
Logger.getLogger(SimpleInterceptor.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
@Stateless(name="SimpleStatelessBean1")
public class SimpleStatelessBean1 implements SimpleStatelessLocal { ... }
@Stateless(name="SimpleStatelessBean2")
public class SimpleStatelessBean2 implements SimpleStatelessLocal { ... }
public class SimpleStatelessServlet extends HttpServlet {
@EJB(beanName="SimpleStatelessBean1")
private SimpleStatelessLocal simpleStatelessLocal1;
@EJB(beanName="SimpleStatelessBean2")
private SimpleStatelessLocal simpleStatelessLocal2;
...
}
Posted at 09:58下午 七月 08, 2008 by shooeugenesea in EJB3 | 迴響[0]
servlet + session bean & MDB
@Local
public interface SimpleStatelessLocal {
String simpleShow();
}
@Stateless
public class SimpleStatelessBean implements SimpleStatelessLocal {
public String simpleShow() {
return this + ":This is simple show";
}
}
@MessageDriven(mappedName = "jms/TestQueueDestination", activationConfig = {
@ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"),
@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue")
})
public class SimpleStatelessBeanMDBBean implements MessageListener {
public void onMessage(Message message) {
try {
TextMessage msg = (TextMessage) message;
System.out.println("Receive message:" + msg.getText());
} catch (JMSException ex) {
throw new RuntimeException( ex );
}
}
}
public class SimpleStatelessServlet extends HttpServlet {
@EJB
private SimpleStatelessLocal simpleStatelessLocal;
/**
* Processes requests for both HTTP GET and POST methods.
* @param request servlet request
* @param response servlet response
*/
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
request.setAttribute("result", "sessionID:" + request.getSession().getId() + ":" + simpleStatelessLocal.simpleShow() );
RequestDispatcher dispatcher = request.getRequestDispatcher("index.jsp");
dispatcher.forward(request, response);
}
// doGet, doPost call processRequest
}
@Remote
public interface SimpleStatefulRemote {
String simpleShow();
}
@Stateful(name="SimpleStatefulBean", mappedName="ejb/SimpleStatefulBean")
public class SimpleStatefulBean implements SimpleStatefulRemote {
public String simpleShow() {
return this + ":This is simple show";
}
}
public class SimpleStatefulServlet extends HttpServlet {
/**
* Processes requests for both HTTP GET and POST methods.
* @param request servlet request
* @param response servlet response
*/
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
response.setContentType("text/html;charset=UTF-8");
InitialContext ctx = new InitialContext();
SimpleStatefulRemote simpleStatefulLocal = (SimpleStatefulRemote) ctx.lookup("ejb/SimpleStatefulBean");
request.setAttribute("result", "sessionID:" + request.getSession().getId() + ":" + simpleStatefulLocal.simpleShow());
RequestDispatcher dispatcher = request.getRequestDispatcher("index.jsp");
dispatcher.forward(request, response);
} catch (NamingException ex) {
throw new ServletException( ex );
}
}
//doGet, doPost call processRequest
}
Posted at 10:50下午 六月 29, 2008 by shooeugenesea in EJB3 | 迴響[0]
簡單測試session bean的HttpClient
package testhttpclient;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.logging.Logger;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.WindowConstants;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.math.NumberUtils;
/**
*
* @author Isaac
*/
public class TestHttpClient {
// Used to add urls you want to test
private String[] urls = new String[]{
"http://localhost:8081/June2008-war/SimpleStatefulServlet",
"http://localhost:8081/June2008-war/SimpleStatelessServlet"
};
public static void main(String[] args) {
TestHttpClient test = new TestHttpClient();
test.test();
}
private void test() {
JTextArea jTextAreaResponse = new JTextArea(30, 80);
JPanel jPanelUrl = prepareJPanelUrl(jTextAreaResponse);
JPanel jPanelMain = prepareJPanelMain(jPanelUrl, jTextAreaResponse);
show(jPanelMain);
}
private JPanel prepareJPanelMain(JPanel jPanelUrl, JTextArea jTextAreaResponse) {
JPanel jPanelMain = prepareJPanel();
JScrollPane jScrollPane = new JScrollPane();
jScrollPane.setViewportView(jTextAreaResponse);
jPanelMain.add(jPanelUrl, BorderLayout.NORTH);
jPanelMain.add(jScrollPane, BorderLayout.CENTER);
return jPanelMain;
}
private JPanel prepareJPanelUrl(JTextArea jTextAreaResponse) {
JComboBox jComboBoxUrl = new JComboBox();
JTextField jTextFieldRequestTimes = new JTextField(5);
JButton jButtonSubmit = new JButton("Submit");
jTextFieldRequestTimes.addKeyListener(new FormSubmitHandler(jComboBoxUrl, jTextAreaResponse, jTextFieldRequestTimes));
jComboBoxUrl.setEditable(true);
jComboBoxUrl.setModel(new DefaultComboBoxModel(urls));
jComboBoxUrl.addActionListener(new FormSubmitHandler(jComboBoxUrl, jTextAreaResponse, jTextFieldRequestTimes));
jButtonSubmit.addActionListener(new FormSubmitHandler(jComboBoxUrl, jTextAreaResponse, jTextFieldRequestTimes));
JPanel jPanelBtn = prepareJPanel();
jPanelBtn.add(jTextFieldRequestTimes, BorderLayout.WEST);
jPanelBtn.add(jButtonSubmit, BorderLayout.EAST);
JPanel jPanelUrl = prepareJPanel();
jPanelUrl.add(jComboBoxUrl, BorderLayout.CENTER);
jPanelUrl.add(jPanelBtn, BorderLayout.EAST);
return jPanelUrl;
}
private JPanel prepareJPanel() {
JPanel jPanel = new JPanel();
jPanel.setLayout(new BorderLayout());
return jPanel;
}
private void show(JPanel jPanelMain) {
JFrame f = new JFrame();
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.getContentPane().setLayout(new BorderLayout());
f.getContentPane().add(jPanelMain, BorderLayout.CENTER);
f.pack();
f.setVisible(true);
}
}
class FormSubmitHandler extends KeyAdapter implements ActionListener {
private JComboBox jComboBoxUrl;
private JTextArea jTextAreaResponse;
private JTextField jTextFieldRequestTimes;
public FormSubmitHandler(final JComboBox jComboBoxUrl, final JTextArea jTextAreaResponse, final JTextField jTextFieldRequestTimes) {
if ( jComboBoxUrl == null || jTextAreaResponse == null || jTextFieldRequestTimes == null ) {
throw new IllegalArgumentException("All parameters can't be null.");
}
this.jComboBoxUrl = jComboBoxUrl;
this.jTextAreaResponse = jTextAreaResponse;
this.jTextFieldRequestTimes = jTextFieldRequestTimes;
}
public void actionPerformed(ActionEvent e) {
doSubmit();
}
@Override
public void keyPressed(KeyEvent e) {
if ( e.getKeyCode() == KeyEvent.VK_ENTER ) {
doSubmit();
}
}
private void doSubmit() {
String requestTimesText = jTextFieldRequestTimes.getText();
int requestTimes = NumberUtils.isNumber(requestTimesText) ? NumberUtils.toInt(requestTimesText) : 1;
jTextAreaResponse.setText(HttpRequester.request(jComboBoxUrl.getSelectedItem().toString(), requestTimes));
}
}
class HttpRequester {
public static String request(String url, int requestTimes) {
String response = "";
for (int i = 0; i < requestTimes; i++) {
Logger.getLogger(HttpRequester.class.getName()).info("Run " + (i + 1) + " times");
try {
HttpClient client = new HttpClient();
PostMethod method = new PostMethod(url);
client.executeMethod(method);
response = IOUtils.toString(method.getResponseBodyAsStream());
method.releaseConnection();
client = null;
} catch (Exception ex) {
Logger.getLogger(HttpRequester.class.getName()).info(HttpRequester.class.getName() + " has exception " + ex + " and break for loop.");
ex.printStackTrace();
break;
}
}
return response;
}
}
Posted at 11:09下午 六月 28, 2008 by shooeugenesea in EJB3 | 迴響[0]
EJB3 - JPA - Query
@Entity
@NamedQuery(name=Programmer.JPQL_FIND_ALL_PROGRAMMER, query="from Programmer")
public class Programmer implements Serializable {...}
@Entity
@NamedQueries(
@NamedQuery(name=Programmer.JPQL_FIND_ALL_PROGRAMMER, query="from Programmer")
)
public class Programmer implements Serializable {...}
@Entity
@NamedQueries({
@NamedQuery(name=Programmer.JPQL_FIND_ALL_PROGRAMMER, query="from Programmer"),
@NamedQuery(name=Programmer.JPQL_FIND_ALL_PROGRAMMER, query="from Programmer")
})
public class Programmer implements Serializable {...}
Query q = em.createNamedQuery(Programmer.JPQL_FIND_ALL_PROGRAMMER);
Query q = em.createQuery("from Programmer");
private void useParametericQuery() {
EntityManager em = EntityManagerHelper.getEntityManager();
Query q = em.createQuery("select p from Programmer p where p.id >= ?100 AND p.id <= ?70");
/* 如果指定錯誤, 例如放65.
* 會出現java.lang.IllegalArgumentException:
* org.hibernate.QueryParameterException:
* could not locate named parameter [65] */
q.setParameter(70, Long.valueOf(100));
q.setParameter(100, Long.valueOf(50));
List< Programmer > resultList = q.getResultList();
for (Programmer programmer : resultList) {
System.out.println(programmer.getId() + ":" + programmer.getName());
}
}
private void useNamedParametericQuery() {
EntityManager em = EntityManagerHelper.getEntityManager();
Query q = em.createQuery("select p from Programmer p " +
"where p.id >= :lowerID and p.id <= :higherID");
q.setParameter("lowerID", Long.valueOf(30));
q.setParameter("higherID", Long.valueOf(80));
List< Programmer > resultList = q.getResultList();
for (Programmer programmer : resultList) {
System.out.println(programmer.getId() + ":" + programmer.getName());
}
}
private void useNoResultExceptionQuery(String pname) {
EntityManager em = EntityManagerHelper.getEntityManager();
Query q = em.createQuery("select p from Programmer p where p.name = :pname");
q.setParameter("pname", pname);
try {
System.out.println(q.getSingleResult());
} catch ( NoResultException nre ) {
System.out.println("no result");
nre.printStackTrace();
} catch ( NonUniqueResultException nure ) {
System.out.println("not unique result");
nure.printStackTrace();
}
}
private void usePaginationQuery() {
EntityManager em = EntityManagerHelper.getEntityManager();
Query q = em.createNamedQuery(Programmer.JPQL_FIND_ALL_PROGRAMMER);
q.setMaxResults(10);
int resultCount = 0;
while ( true ) {
q.setFirstResult(resultCount);
List< Programmer > resultList = q.getResultList();
if ( resultList.size() == 0) {
System.out.println("result end..");
break;
}
resultCount += resultList.size();
System.out.println("getResultList...");
for (Programmer programmer : resultList) {
System.out.println(programmer.getName());
}
System.out.println("next page...");
}
}
private void useAutoCommit() {
EntityManager em = EntityManagerHelper.getEntityManager();
// 如果沒有begin就不會馬上有AUTO COMMIT的效果, 就是有 INSERT 的 statement
em.getTransaction().begin();
System.out.println("transaction begin");
prepareProgrammer(em, 999); // 在這新增一筆Programmer但沒commit
System.out.println("prepare programmer finished");
Query q = em.createQuery("from Programmer");
System.out.println("prepare Query instance");
// 到 getResultList 才會 auto-commit 然後 select
// 這時候 query 的結果會是處理完entity的結果
List< Programmer > resultList = q.getResultList();
System.out.println("getResultList");
for (Programmer programmer : resultList) {
System.out.println(programmer.getName());
}
// 可是如果最後沒執行commit還是不會把entity的處理放進DB
em.getTransaction().commit();
}
private void useNotAutoCommit() {
EntityManager em = EntityManagerHelper.getEntityManager();
em.getTransaction().begin();
System.out.println("transaction begin");
prepareProgrammer(em, 999);
System.out.println("prepare programmer finished");
Query q = em.createQuery("from Programmer");
q.setFlushMode(FlushModeType.COMMIT);
System.out.println("prepare Query instance");
// 這時候query的結果不會包含新增的Programmer, 因為FlushMode改為COMMIT
List< Programmer > resultList = q.getResultList();
System.out.println("getResultList");
for (Programmer programmer : resultList) {
System.out.println(programmer.getName());
}
}
UPDATE entityName indentifierVariable
SET single_value_path_expression1 = value1, ...
single_value_path_expressionN = valueN
WHERE where_clause
private void useUpdateQuery() {
EntityManager em = EntityManagerHelper.getEntityManager();
Query q = em.createQuery("update Programmer p set " +
"p.name = 'QQ 100' where p.name = 'QQ 999'");
// 執行Query的update需要transaction
em.getTransaction().begin();
q.executeUpdate();
em.getTransaction().commit();
}
DELETE entityName indentifierVariable
WHERE where_clause
private void useDeleteQuery() {
EntityManager em = EntityManagerHelper.getEntityManager();
Query q = em.createQuery("delete Certification c where c.name like 'SCWCD%'");
// 沒有transaction會
// javax.persistence.TransactionRequiredException: Executing an update/delete query
em.getTransaction().begin();
q.executeUpdate();
em.getTransaction().commit();
}
@Entity(name="Programmer2")
@Table(name="CERTIFICATION")
@NamedQueries({
@NamedQuery(name=Certification.JPQL_FIND_ALL_CERT, query="from Certification as c")
})
public class Certification implements Serializable { ... }
FROM Certification AS c, 其中的 c 就是identifier variable
SELECT, UPDATE, DELETE, FROM, WHERE, GROUP, HAVING, ORDER, BY, ASC, DESC
JOIN, OUTER, INNER, LEFT, FETCH
DISTINCT, OBJECT, NULL, TRUE, FALSE, NOT, AND, OR, BETWEEN, LIKE, IN, AS,
UNKNOWN, EMPTY, MEMBER, OF, IS, NEW, EXISTS, ALL, ANY, SOME
AVG, MAX, MIN, SUM, COUNT, MOD, UPPER, LOWER, TRIM, POSITION, CHARACTER_LENGTH,
CHAR_LENGTH, BIT_LENGTH, CURRENT_TIME, CURRENT_DATE, CURRENT_TIMESTAMP
from Programmer p where p.certs is not empty
.
+, -
+, -, *, /
=, >, >=, <=, <>,
[not] bewteen, [not] like, [not] in, is [not] null, is [not] empty, [not] member [of]
NOT, AND, OR
private void useQueryBetween() {
EntityManager em = EntityManagerHelper.getEntityManager();
Query q = em.createQuery("from Certification c where c.createDate between ?0 and ?1");
Calendar date1 = Calendar.getInstance(); date1.set(1998, 0, 1);
Calendar date2 = Calendar.getInstance(); date2.set(2000, 0, 1);
q.setParameter(0, date1);
q.setParameter(1, date2);
List< Certification > list = q.getResultList();
q = em.createQuery("select count(c) from Certification c " +
"where c.createDate between ?0 and ?1");
q.setParameter(0, date1);
q.setParameter(1, date2);
Long count = (Long) q.getSingleResult();
System.out.println(Long.valueOf(list.size()).equals(count)); // true
}
private void useQueryIn() {
EntityManager em = EntityManagerHelper.getEntityManager();
Query q = em.createQuery("from Certification c where" +
" c.name in ('SCJP 0', 'SCJP 1', 'SCJP 2')");
List< Certification > list = q.getResultList();
for (Certification certification : list) {
System.out.println(certification.getName());
}
q = em.createQuery("from Certification c " +
"where c.name not in ('SCJP 0', 'SCJP 1', 'SCJP 2')");
list = q.getResultList();
for (Certification certification : list) {
System.out.println(certification.getName());
}
q = em.createQuery("from Certification c " +
"where c.programmer in (from Programmer p where p.id > 600)");
list = q.getResultList();
for (Certification certification : list) {
System.out.println(certification.getName() +
":" + certification.getProgrammer().getId());
}
q = em.createQuery("from Certification c where " +
"c.name in (select c.name from c where c.id > 600)");
list = q.getResultList();
for (Certification certification : list) {
System.out.println(certification.getId() + ":" + certification.getName());
}
}
private void useQueryLike() {
EntityManager em = EntityManagerHelper.getEntityManager();
Query q = em.createQuery("from Certification c where c.name like '%_P_9_'");
List< Certification > list = q.getResultList();
for (Certification cert : list) {
System.out.println(cert.getName());
}
q = em.createQuery("from Certification c where c.name not like '%_P_9_'");
list = q.getResultList();
for (Certification cert : list) {
System.out.println(cert.getName());
}
}
TRUE AND null = UNKNOWN
FALSE AND null = FALSE
Null AND null = UNKNOWN
TRUE OR null = TRUE
Null OR null = UNKNOWN
FALSE OR null = UNKNOWN
NOT null = UNKNOWN
private void useQueryNull() {
EntityManager em = EntityManagerHelper.getEntityManager();
Query q = em.createQuery("from Certification c where c.name is null");
List< Certification > list = q.getResultList();
for (Certification certification : list) {
System.out.println(certification.getName());
}
q = em.createQuery("from Programmer p where p.certs is empty");
List< Programmer > programmers = q.getResultList();
for (Programmer programmer : programmers) {
System.out.println(programmer.getName() + ":" + programmer.getCerts().size());
}
}
entity_expression [NOT] MEMBER [OF] collection_value_path_expression, 如下所示
private void useQueryMember() {
EntityManager em = EntityManagerHelper.getEntityManager();
Certification c = em.find(Certification.class, Long.valueOf(114));
Query q = em.createQuery("from Programmer p where ?0 member of p.certs");
q.setParameter(0, c);
List< Programmer > list = q.getResultList();
for (Programmer programmer : list) {
System.out.println(programmer.getCerts().contains(c));
}
}
private void useJPQLStringFunction() {
EntityManager em = EntityManagerHelper.getEntityManager();
Query q = em.createQuery("from Certification c where " +
"CONCAT('scwcd ', '14') = LOWER(c.name) ");
List< Certification > list = q.getResultList();
for (Certification certification : list) {
System.out.println(certification.getName());
}
// substring第一個字母index就是一, 不像java從0開始
q = em.createQuery("from Certification c where " +
"UPPER(SUBSTRING('abcscwcd 14123', 4, 8)) = UPPER(c.name)");
list = q.getResultList();
for (Certification cert : list) {
System.out.println(cert.getName());
}
q = em.createQuery("from Certification c where " +
"UPPER(TRIM(BOTH ' ' FROM ' scwcd 14 ')) = UPPER(c.name)");
list = q.getResultList();
for (Certification cert : list) {
System.out.println(cert.getName());
}
q = em.createQuery("from Certification c where " +
"UPPER(TRIM(LEADING ' ' FROM ' scwcd 14')) = UPPER(c.name)");
list = q.getResultList();
for (Certification cert : list) {
System.out.println(cert.getName());
}
q = em.createQuery("from Certification c where " +
"UPPER(TRIM(TRAILING ' ' FROM 'scwcd 14 ')) = UPPER(c.name)");
list = q.getResultList();
for (Certification cert : list) {
System.out.println(cert.getName());
}
q = em.createQuery("from Certification c where " +
"UPPER(TRIM(BOTH 'a' FROM 'aaaascwcd 14aaaaaaaaa')) = UPPER(c.name)");
list = q.getResultList();
for (Certification cert : list) {
System.out.println(cert.getName());
}
q = em.createQuery("from Certification c where LENGTH(c.name) = 8");
list = q.getResultList();
for (Certification cert : list) {
System.out.println(cert.getName());
}
// LOCATE第一個字index也是1
q = em.createQuery("from Certification c where LOCATE('wcd', LOWER(c.name)) = 3");
list = q.getResultList();
for (Certification cert : list) {
System.out.println(cert.getName());
}
}
private void useJPQLArithmeticFunction() {
EntityManager em = EntityManagerHelper.getEntityManager();
// ABS 絕對值
Query q = em.createQuery("from Certification c where ABS(c.id) = 100");
List< Certification > list = q.getResultList();
for (Certification certification : list) {
System.out.println(certification.getName());
}
// SQRT 平方根
q = em.createQuery("from Certification c where SQRT(c.id) = 10");
list = q.getResultList();
for (Certification certification : list) {
System.out.println(certification.getName());
}
// MOD 餘數
q = em.createQuery("from Certification c where c.id = MOD(1100, 1000)");
list = q.getResultList();
for (Certification certification : list) {
System.out.println(certification.getName());
}
// SIZE 量
q = em.createQuery("from Programmer p where SIZE(p.certs) > 2");
List< Programmer > programmers = q.getResultList();
for (Programmer programmer : programmers) {
System.out.println(programmer.getName());
}
}
private void useJPQLTemporalFunction() {
EntityManager em = EntityManagerHelper.getEntityManager();
// 從DB 取DATE
Query q = em.createQuery("select distinct CURRENT_DATE from Certification");
System.out.println(q.getSingleResult());
// 無法使用CURRENT_TIME, 會有
//java.sql.SQLException: ORA-00904: "CURRENT_TIME": invalid identifier
q = em.createQuery("select distinct CURRENT_TIME from Certification");
System.out.println(q.getSingleResult());
// 從DB取得TIMESTAMP
q = em.createQuery("select distinct CURRENT_TIMESTAMP from Certification");
System.out.println(q.getSingleResult());
}
private void useJPQLSelect() {
EntityManager em = GeneralEAO.getEntityManager();
Query q = null;
// simple select clause
q = em.createQuery("select p from Programmer p, Address a where a.employee.id = p.id");
List< Programmer > simpleProgrammer = q.getResultList();
for (Programmer programmer : simpleProgrammer) {
System.out.println(programmer.getName());
}
// select distinct
q = em.createQuery("select distinct(p) from Programmer p, " +
"Address a where a.employee.id = p.id");
List< Programmer > distinctProgrammer = q.getResultList();
for (Programmer programmer : distinctProgrammer) {
System.out.println(programmer.getName());
}
// select single property
q = em.createQuery("select p.name from Programmer p where " +
"p.payment = (select max(p.payment) from Programmer p)");
List< String > oneProp = q.getResultList();
for (String name : oneProp) {
System.out.println(name);
}
// select two property
q = em.createQuery("select p.name, p.payment from Programmer p " +
"where p.payment = (select max(p.payment) from Programmer p)");
List< Object[] > twoProp = q.getResultList();
for (Object[] objects : twoProp) {
String name = (String) objects[0];
Double payment = (Double) objects[1];
System.out.println(name + ":" + payment);
}
// select association entity
q = em.createQuery("select n.owner.name, n from NoteBook n where " +
"n.owner.payment = (select MAX(p.payment) from Programmer p)");
List< Object[] > twoProp2 = q.getResultList();
for (Object[] objects : twoProp2) {
String name = (String) objects[0];
NoteBook noteBook = (NoteBook) objects[1];
System.out.println(name + ":" + noteBook.getMachineNumber() +
":" + noteBook.getOwner().getName());
}
// 書上好像說不能select collection的, 不過測試還正常
// select collection entities
q = em.createQuery("select p.addressList from Programmer p");
List< Address > addressList = q.getResultList();
for (Address address : addressList) {
System.out.println(address.getStreet());
}
// 這樣就會有錯, 因為除了collection以外又加一個single-value
try {
q = em.createQuery("select p.name, p.addressList from Programmer p");
List< Object > nameAddressList = q.getResultList();
for (Object object : nameAddressList) {
System.out.println(object);
}
} catch (Exception e) {
System.out.println("select p.name, p.addressList has " +
"exception because can't select single-value and collections." + e);
}
// new entity.StringObject傳入的參數試過不能是null, 而且要有對映的建構子. 型態也要一樣 如下:
// < code >
// public class StringObject {
//
// private String str1;
// private String str2;
// private Double double3;
//
// public StringObject(String str1, String str2, Double double3) {
// < /code >
// 這裡的StringObject不用是entity也不用mapping到DB.
q = em.createQuery("select new entity.StringObject(p.name, p.lang, p.payment)" +
" from Programmer p");
List< StringObject > stringObjectList = q.getResultList();
for (StringObject stringObject : stringObjectList) {
System.out.println(stringObject.getStr1());
System.out.println(stringObject.getStr2());
System.out.println(stringObject.getDouble3());
}
// Employee是abstract super class, 透過JPQL搜尋可取得subclass
List< Employee > employeeList = em.createQuery("from Employee").getResultList();
for (Employee employee : employeeList) {
System.out.println(employee);
}
}
AVG: Return Double
COUNT: Return Long
MAX: Return persistence field type
MIN: Return persistence field type
SUM: Return Long or Double
private void useAggregateFunctions() {
EntityManager em = EntityManagerHelper.getEntityManager();
/* 若放AVG(p.name)或SUM(p.name) 會
* javax.persistence.PersistenceException:
* org.hibernate.exception.SQLGrammarException:
* could not execute query */
Query q = em.createQuery(
"select AVG(p.id), MAX(p.id), MIN(p.id), SUM(p.id), COUNT(p), " +
"MAX(p.name), MIN(p.name), COUNT(p.name) " +
"from Employee p");
Object[] o = (Object[]) q.getSingleResult();
Double idAvg = (Double) o[0];
Long idMax = (Long) o[1];
Long idMin = (Long) o[2];
Long idSum = (Long) o[3];
Long idCnt = (Long) o[4];
String nameMax = (String) o[5];
String nameMin = (String) o[6];
Long nameCnt = (Long) o[7];
System.out.println("avg:" + idAvg);
System.out.println("idMax:" + idMax);
System.out.println("idMin:" + idMin);
System.out.println("idSum:" + idSum);
System.out.println("idCnt:" + idCnt);
System.out.println("nameMax:" + nameMax);
System.out.println("nameMin:" + nameMin);
System.out.println("nameCnt:" + nameCnt);
}
private void useGroupByAndHaving() {
EntityManager em = EntityManagerHelper.getEntityManager();
Query q = em.createQuery("select c.owner.name, COUNT(c.id) from " +
"Certification c group by c.owner.name");
List< Object[] > resultList = q.getResultList();
for (Object[] result : resultList) {
String ownerName = (String) result[0];
Long count = (Long) result[1];
System.out.println(ownerName + " has " + count + " certs.");
}
q = em.createQuery("select c.owner.name, COUNT(c.id) from " +
"Certification c group by c.owner.name having COUNT(c.id) = 4");
resultList = q.getResultList();
for (Object[] result : resultList) {
String ownerName = (String) result[0];
Long count = (Long) result[1];
System.out.println(ownerName + " has " + count + " certs.");
}
q = em.createQuery("select c.owner.name, COUNT(c.id) from " +
"Certification c where c.id < 40 group by c.owner.name " +
"having COUNT(c.id) = 4");
resultList = q.getResultList();
for (Object[] result : resultList) {
String ownerName = (String) result[0];
Long count = (Long) result[1];
System.out.println(ownerName + " has " + count + " certs.");
}
}
private void useOrderBy() {
EntityManager em = EntityManagerHelper.getEntityManager();
Query q = em.createQuery("from Sales s order by s.id desc, s.performance asc");
List< Sales > list = q.getResultList();
for (Sales sales : list) {
System.out.println(sales.getId() + ":" + sales.getPerformance());
}
/* 書上說這樣是不對的, 因為order by s.id沒包括在select clause中.
* 不過Hibernate試過還可以 */
q = em.createQuery("select s.performance from Sales s order by s.id desc");
List< Double > performanceList = q.getResultList();
for (Double performance : performanceList) {
System.out.println(performance);
}
}
private void useSubQuery() {
EntityManager em = EntityManagerHelper.getEntityManager();
// normal subquery
Query q = em.createQuery("select c.owner from Certification c " +
"where c.owner = (from Employee e where e.id = 9)");
List< Employee > employeeList = q.getResultList();
for (Employee employee : employeeList) {
System.out.println(employee.getName());
}
// IN : 檢查是否在subquery中
q = em.createQuery("select c.owner from Certification c " +
"where c.owner in (from Employee e where e.id < 50)");
employeeList = q.getResultList();
for (Employee employee : employeeList) {
System.out.println(employee.getName());
}
// EXISTS : 檢查是否有資料存在
q = em.createQuery("select c.owner from Certification c " +
"where exists (from Employee e where e.id = c.owner.id)");
employeeList = q.getResultList();
for (Employee employee : employeeList) {
System.out.println(employee.getName());
}
// ANY : 只要與任一筆相比較符合即可. 可搭配 =, >, >=, <, <=, < >
q = em.createQuery("select c.owner from Certification c " +
"where c.owner.id > ANY(select e.id from Employee e where e.id < 20)");
employeeList = q.getResultList();
for (Employee employee : employeeList) {
System.out.println(employee);
}
// SOME : 只要與任一筆相比較符合即可. 可搭配 =, >, >=, <, <=, < >
q = em.createQuery("select c.owner from Certification c " +
"where c.owner.id > SOME(select e.id from Employee e where e.id > 700)");
employeeList = q.getResultList();
for (Employee employee : employeeList) {
System.out.println(employee);
}
// ALL : 必須與所有的資料比較相符. 可搭配 =, >, >=, <, <=, < >
q = em.createQuery("select c.owner from Certification c " +
"where c.owner.id > ALL(select e.id from Employee e where e.id < 700)");
employeeList = q.getResultList();
for (Employee employee : employeeList) {
System.out.println(employee);
}
}
private void useJoin() {
EntityManager em = EntityManagerHelper.getEntityManager();
// theta-join
Query q = em.createQuery("select ae.name from " +
"AnotherEmployee ae, Certification c where ae.id = c.owner.id group by ae.name");
List< String > nameList = q.getResultList();
for (String name : nameList) {
System.out.println(name);
}
// inner join . "inner" is optional.
q = em.createQuery("select e from Employee e inner join e.noteBook");
List< Employee > employeeList = q.getResultList();
for (Employee employee : employeeList) {
System.out.println(employee.getId() +
" noteBook is null: " + (employee.getNoteBook() == null));
}
// inner join. "inner" and "as" is optional
q = em.createQuery("select n from Employee e inner join e.noteBook as n");
List< NoteBook > noteBookList = q.getResultList();
for (NoteBook noteBook : noteBookList) {
System.out.println(noteBook.getOwner().getId());
}
// outer join.
q = em.createQuery("select e from Employee e left outer join e.noteBook");
employeeList = q.getResultList();
for (Employee employee : employeeList) {
System.out.println(employee.getId() +
" noteBook is null: " + (employee.getNoteBook() == null) );
}
/* both join 會有java.lang.IllegalArgumentException:
* org.hibernate.hql.ast.QuerySyntaxException:
* unexpected token: both near line 1, column 33
* [select e from entity.Employee e both join e.noteBook] */
q = em.createQuery("select e from Employee e both join e.noteBook");
employeeList = q.getResultList();
for (Employee employee : employeeList) {
System.out.println(employee.getId() + " noteBook is null: " +
(employee.getNoteBook() == null) );
}
/**
* right outer join 有 java.lang.UnsupportedOperationException:
* join type not supported by OracleJoinFragment (use Oracle9Dialect)
*/
q = em.createQuery("select e from Employee e right outer join e.noteBook");
employeeList = q.getResultList();
for (Employee employee : employeeList) {
System.out.println(employee.getId() + " noteBook is null: " +
(employee.getNoteBook() == null) );
}
/**
* 用join fetch可直接透過Query取得lazy的相關型態
* reference: http://edocs.bea.com/kodo/docs41/full/html/ejb3_langref.html
* #ejb3_langref_fetch_joins
*/
q = em.createQuery("select e from Employee e inner join fetch e.certs");
employeeList = q.getResultList();
em.clear(); // 這樣才可以知的detach
for (Employee employee : employeeList) {
System.out.println(employee.getCerts());
}
}
private void useUpdateDelete() {
EntityManager em = EntityManagerHelper.getEntityManager();
Query q = em.createQuery("update Programmer p set p.lang = :lang");
q.setParameter("lang", "Java");
/**
* 沒transaction會有javax.persistence.TransactionRequiredException:
* Executing an update/delete query
*/
em.getTransaction().begin();
System.out.println("update..." + q.executeUpdate() + " records");
em.getTransaction().commit();
q = em.createQuery("delete NoteBook n where n.id < :lowID");
q.setParameter("lowID", Long.valueOf(200));
em.getTransaction().begin();
System.out.println("delete..." + q.executeUpdate() + " records");
em.getTransaction().commit();
}
private void useNativeSQL() {
EntityManager em = EntityManagerHelper.getEntityManager();
// simple native sql
Query q = em.createNativeQuery("select e.EMPLOYEE_ID, e.EMPLOYEE_TYPE, " +
"e.NAME from EMPLOYEE e");
List< Object[] > objAryList = q.getResultList();
for (Object[] objAry : objAryList) {
BigDecimal id = (BigDecimal) objAry[0];
String type = (String) objAry[1];
String name = (String) objAry[2];
System.out.println(id + ":" + type + ":" + name);
}
// native sql with parameters
q = em.createNativeQuery("select e.EMPLOYEE_ID, e.EMPLOYEE_TYPE, e.NAME " +
"from EMPLOYEE e where e.EMPLOYEE_ID = :id");
q.setParameter("id", Long.valueOf(1));
objAryList = q.getResultList();
for (Object[] objAry : objAryList) {
BigDecimal id = (BigDecimal) objAry[0];
String type = (String) objAry[1];
String name = (String) objAry[2];
System.out.println(id + ":" + type + ":" + name);
}
// 指定所選的class, 注意雖然SQL只說要select EMPLOYEE_ID, 透過Query卻可取出整個owner.
// 不過這種方式會有一次只能指定一個entity的問題
q = em.createNativeQuery("select NOTE_BOOK_ID, SERIAL_NO, EMPLOYEE_ID " +
"from NOTE_BOOK where NOTE_BOOK_ID = 200", NoteBook.class);
List< NoteBook > noteBookList = q.getResultList();
for (NoteBook noteBook : noteBookList) {
System.out.println(noteBook.getId() + ":" + noteBook.getSerialNO() +
":" + noteBook.getOwner());
}
/**
* 透過指定SqlResultSetMapping即可同時用native sql取得兩種entity
* @SqlResultSetMapping(name="allNoteBooksAndCertifications",
* entities={
* @EntityResult(entityClass=NoteBook.class),
* @EntityResult(entityClass=Certification.class)})
*/
q = em.createNativeQuery("select * from NOTE_BOOK n, CERTIFICATION c " +
"where n.EMPLOYEE_ID = c.EMPLOYEE_ID and c.CERTIFICATION_ID = 202"
, "allNoteBooksAndCertifications");
objAryList = q.getResultList();
for (Object[] objAry : objAryList) {
NoteBook noteBook = (NoteBook) objAry[0];
Certification cert = (Certification) objAry[1];
System.out.println(noteBook);
System.out.println(cert);
}
/**
* 透過在NoteBook上設定named query
* @NamedNativeQueries({
* @NamedNativeQuery(name="all204NoteBook",
* query="select * from NOTE_BOOK where NOTE_BOOK_ID = 204",
* resultClass=NoteBook.class),
* @NamedNativeQuery(name="204NoteBooksAnd202Certifications",
* query="select * from NOTE_BOOK n, CERTIFICATION c " +
* "where n.EMPLOYEE_ID = c.EMPLOYEE_ID" +
* " and c.CERTIFICATION_ID = 202",
* resultSetMapping="allNoteBooksAndCertifications")
* })
*/
q = em.createNamedQuery("all204NoteBook");
noteBookList = q.getResultList();
for (NoteBook noteBook : noteBookList) {
System.out.println(noteBook);
}
q = em.createNamedQuery("204NoteBooksAnd202Certifications");
objAryList = q.getResultList();
for (Object[] objAry : objAryList) {
NoteBook noteBook = (NoteBook) objAry[0];
Certification cert = (Certification) objAry[1];
System.out.println(noteBook);
System.out.println(cert);
}
}
Posted at 01:58上午 六月 27, 2008 by shooeugenesea in EJB3 | 迴響[0]
EJB3 - JPA - CRUD
@Stateless
public class TestPersistWithoutTransactionBean implements TestPersistWithoutTransactionLocal {
@PersistenceContext(unitName="persistence_oracle", type=PersistenceContextType.TRANSACTION) EntityManager em;
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public String persistWithoutTransaction() {
String exceptionString = "run persist without transaction";
try {
Programmer p = new Programmer();
p.setName("Joe");
em.persist(p);
} catch (TransactionRequiredException tre) {
Logger.getLogger(TestPersistWithoutTransactionBean.class).error(tre);
tre.printStackTrace();
}
return exceptionString;
}
}
private void test() {
Programmer p = new Programmer();
p.setName("Joe");
Certification c = new Certification();
c.setCertName("SCJP");
c.setOwner(p);
p.getCerts().add(c);
GeneralEAO.createWithoutTransaction(p);
System.out.println("after create without transaction");
GeneralEAO.hereIsTransactionCommit(); // 在這行會commit
}
public static void addCertIntoDetachedProgrammer(Long programmerId) {
Programmer p = EntityManagerHelper.getEntityManager().find(Programmer.class, programmerId);
Certification c = new Certification();
c.setCertName("addCertIntoDetachedProgrammer");
// 由於Programmer已經在DB中, 所以要把PROGRAMMER_ID會是設定到Certification
// 如果沒設定, CERTIFICATION.PROGRAMMER_ID 會是 null
c.setOwner(p);
EntityManagerHelper.getEntityManager().persist(c);
GeneralEAO.transactionCommit();
}
我把method改成如下. 這樣看起來沒問題, 但如果兩邊都沒設定cascade, 且Programmer不是一個已經存進db的資料就會出現 org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: entity.Certification.owner -> entity.Programmer的錯誤.
public static void addCert(Programmer p) {
Certification c = new Certification();
c.setCertName("addCert");
c.setOwner(p);
//可確保Programmer一定會被存��DB
EntityManagerHelper.getEntityManager().persist(c);
GeneralEAO.transactionCommit();
}
public static Programmer findProgrammer(Long id) {
return EntityManagerHelper.getEntityManager().find(Programmer.class, id);
}
public static void test() {
Programmer javaP = ProgrammerEAO.createProgrammer();
ProgrammerPK pk = new ProgrammerPK();
pk.setName(javaP.getProgrammerPK().getName());
pk.setProgrammerID(javaP.getProgrammerPK().getProgrammerID());
Programmer p = ProgrammerEAO.findProgrammer( pk );
System.out.println(p == javaP); // true
}
@Entity
public class Programmer implements Serializable {
private static final long serialVersionUID = 1L;
private ProgrammerPK programmerPK;
private String lang;
@EmbeddedId
public ProgrammerPK getProgrammerPK() {
return programmerPK;
}
public void setProgrammerPK(ProgrammerPK programmerPK) {
this.programmerPK = programmerPK;
}
@Column(name="LANG")
public String getLang() {
return lang;
}
public void setLang(String lang) {
this.lang = lang;
}
}
@Embeddable
public class ProgrammerPK implements java.io.Serializable {
private UUID programmerID;
private String name;
@Column(name="NAME")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Column(name="PROGRAMMER_ID")
public UUID getProgrammerID() {
return programmerID;
}
public void setProgrammerID(UUID programmerID) {
this.programmerID = programmerID;
}
}
public static void test() {
Programmer saveP = createProgrammer();
ProgrammerPK pk = new ProgrammerPK();
pk.setName(saveP.getName());
pk.setProgrammerID(saveP.getProgrammerID());
Programmer findP = findProgrammer(pk);
System.out.println(findP == saveP);
}
@IdClass(ProgrammerPK.class)
@Entity
public class Programmer implements Serializable {
private String lang;
private UUID programmerID;
private String name;
@Id
@Column(name="LANG")
public String getLang() {
return lang;
}
public void setLang(String lang) {
this.lang = lang;
}
@Id
@Column(name="PROGRAMMER_ID")
public UUID getProgrammerID() {
return programmerID;
}
public void setProgrammerID(UUID programmerID) {
this.programmerID = programmerID;
}
@Column(name="NAME")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class ProgrammerPK implements java.io.Serializable {
private UUID programmerID;
private String name;
@Column(name="NAME")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Column(name="PROGRAMMER_ID")
public UUID getProgrammerID() {
return programmerID;
}
public void setProgrammerID(UUID programmerID) {
this.programmerID = programmerID;
}
@Override
public boolean equals(Object obj) {
if ( obj == null || !(obj instanceof ProgrammerPK) ) {
return false;
}
ProgrammerPK pk = (ProgrammerPK) obj;
return pk.getName().equals(getName()) && pk.getProgrammerID().equals(getProgrammerID());
}
@Override
public int hashCode() {
return super.hashCode();
}
}
// 改變取得的entity會由EntityManager確認改變sync進db
public static void changeStudentName(Long id) {
Student s = EntityManagerHelper.getEntityManager().find(Student.class, id);
if ( s != null ) { s.setName("KKK"); }
}
// 這個method會因為clear了, EntityManager的entity都detach, 使後來即使有transaction也不會改名為KKK
public static void main(String[] args) {
Long sid = createStudent();
EntityManager em = EntityManagerHelper.getEntityManager();
Student s = em.find(Student.class, sid);
em.clear();
s.setName("KKK");
GeneralEAO.transactionCommit();
}
// 這個method加上merge後使detach的entity重新attach了, 就會把改變後的結果放進DB.
public static void main(String[] args) {
Long sid = createStudent();
EntityManager em = EntityManagerHelper.getEntityManager();
Student s = em.find(Student.class, sid);
em.clear();
s.setName("KKK");
em.merge(s);
GeneralEAO.transactionCommit();
}
若merge一個不存在的entity會產生IllegalArgumentException, 不過我用Hibernate去試卻會自己去判斷如果不存在的entity就insert.
public static void main(String[] args) {
EntityManager em = EntityManagerHelper.getEntityManager();
Student saveS = new Student();
saveS.setName("Isaac");
em.persist(saveS);
GeneralEAO.transactionCommit();
em.clear(); // detach
Student findS = em.find(Student.class, saveS.getId());
findS.setName("2");
// 有這行就會java.lang.IllegalArgumentException:
// Removing a detached instance entity.Student#1
em.clear();
em.remove(findS);
GeneralEAO.transactionCommit();
}
public static void main(String[] args) {
EntityManager em = EntityManagerHelper.getEntityManager();
Student saveS = new Student();
saveS.setName("Isaac");
em.persist(saveS);
GeneralEAO.transactionCommit();
em.clear(); // detach
Student findS = em.find(Student.class, saveS.getId());
findS.setName("2");
em.clear();
// 如果加上merge就算detach了還是可以正常remove
em.remove(em.merge(findS));
GeneralEAO.transactionCommit();
}
public static void main(String[] args) {
Long pid = createProgrammer();
EntityManager em = EntityManagerHelper.getEntityManager();
Programmer findP = em.find(Programmer.class, pid);
int certSize = findP.getCerts().size();
for ( int i = 0; i < certSize; i++ ) {
Certification cert = findP.getCerts().get(0);
em.remove( cert );
findP.getCerts().remove( cert );
}
GeneralEAO.transactionCommit();
}
public static void main(String[] args) {
Long pid = createProgrammer();
EntityManager em = EntityManagerHelper.getEntityManager();
Programmer findP = em.find(Programmer.class, pid);
GeneralEAO.clear();
int certSize = findP.getCerts().size();
System.out.println("before remove:" + certSize);
for ( int i = 0; i < certSize; i++ ) {
Certification cert = findP.getCerts().get(0);
em.remove( em.merge(cert) );
findP.getCerts().remove( cert );
}
System.out.println("before merge:" + findP.getCerts().size());
GeneralEAO.clear();
findP = em.merge(findP);
em.refresh( findP );
System.out.println("after merge" + findP.getCerts().size());
GeneralEAO.transactionCommit();
}
void < METHOD >()的格式
void < METHID > (Object)的格式
< persistence-unit name="persistence">
...
< default-entity-listeners>
aaa.bb.Ccc.class
< /default-entity-listeners>
@Entity
@Table(name="EMPLOYEE2")
@Inheritance(strategy=InheritanceType.JOINED)
@EntityListeners({EmployeeListener.class})
@DiscriminatorColumn(name="EMPLOYEE_TYPE", length=1)
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String name;
private List< Address> addressList = new ArrayList< Address>();
@Id
@Column(name="EMPLOYEE_ID")
@GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@OneToMany(cascade=CascadeType.ALL,mappedBy="employee")
public List< Address> getAddressList() {
return addressList;
}
public void setAddressList(List< Address> addressList) {
this.addressList = addressList;
}
@Column(name="NAME")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
@Entity
@Table(name = "PROGRAMMER")
@DiscriminatorValue(value = "P")
public class Programmer extends Employee implements Serializable {
private static final long serialVersionUID = 1L;
private String lang;
@Column(name="LANG")
public String getLang() {
return lang;
}
public void setLang(String lang) {
this.lang = lang;
}
}
@Entity
@Table(name="SALES")
@ExcludeDefaultListeners
@ExcludeSuperclassListeners
@DiscriminatorValue(value="S")
public class Sales extends Employee implements Serializable {
private static final long serialVersionUID = 1L;
private String product;
@Column(name="PRODUCT")
public String getProduct() {
return product;
}
public void setProduct(String product) {
this.product = product;
}
@PostPersist
@PrePersist
@PostLoad
@PreUpdate
@PostUpdate
@PreRemove
@PostRemove
public void monitorSales() {
System.out.println("Monitor sales product:" + getProduct());
}
}
public class EmployeeListener {
@PostPersist
@PrePersist
@PostLoad
@PreUpdate
@PostUpdate
@PreRemove
@PostRemove
public void monitor(Object o) {
System.out.println("EmployeeListener monitor class: " + o.getClass());
}
}
Posted at 11:58下午 六月 15, 2008 by shooeugenesea in EJB3 | 迴響[1]
EJB3 - JPA - ORM
@Column(name = "LOB_XML", columnDefinition="clob")
@Lob
public byte[] getSecondaryTable() {
return secondaryTable;
}
@Entity
@Table(name="MY_USER")
@SecondaryTable(name="USER_PICTURES", pkJoinColumns=@PrimaryKeyJoinColumn(name="USER_ID"))
public class MyUser implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private BillingInfo billingInfo;
private byte[] picture;
public void setId(Long id) {
this.id = id;
}
@Id
@Column(name="USER_ID")
@GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
return id;
}
@Column(name="PICTURE", table="USER_PICTURES")
@Lob
@Basic(fetch=FetchType.LAZY)
public byte[] getPicture() {
return picture;
}
public void setPicture(byte[] picture) {
this.picture = picture;
}
@OneToOne(cascade=CascadeType.ALL)
@JoinColumn(name="USER_BILLING_ID", referencedColumnName="BILLING_ID")
public BillingInfo getBillingInfo() {
return billingInfo;
}
public void setBillingInfo(BillingInfo billingInfo) {
this.billingInfo = billingInfo;
}
}
create table USER_PICTURES (PICTURE blob, USER_ID number(19,0) not null, primary key (USER_BILLING_ID))
這段SQL錯誤的地方很明顯, 就在指定的PK不是USER_PICTURES的PK, 而是@OneToOne的FK. 去看source, 好像是在準備SQL statement的時候, 準備到SecondaryTable時, 跑去取org.hibernate.mapping.Constraint的columns, 應該存在的是SecondaryTable的PK, 取到的卻是OneToOne的column.
@Id
@Column(name="USER_ID")
@SequenceGenerator(
name="USER_SEQUENCE_GENERATOR", sequenceName="USER_SEQUENCE",
initialValue=1, allocationSize=1
)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator="USER_SEQUENCE_GENERATOR")
public Long getId() {
return id;
}
這樣就會建立一個sequence. create sequence USER_SEQUENCE
create sequence hibernate_sequence
@Id
@Column(name="USER_ID")
@TableGenerator(
name="USER_TABLE_GENERATOR", table="SEQUENCE_GENERATOR_TABLE",
pkColumnName="SEQUENCE_NAME", valueColumnName="SEQUENCE_VALUE",
pkColumnValue="USER_SEQUENCE", initialValue=1, allocationSize=100
)
@GeneratedValue(strategy = GenerationType.TABLE, generator="USER_TABLE_GENERATOR")
public Long getId() {
return id;
}
這樣就會建一個table來放PK value
create table SEQUENCE_GENERATOR_TABLE (
SEQUENCE_NAME varchar2(255), SEQUENCE_VALUE number(10,0)
)
再
insert into SEQUENCE_GENERATOR_TABLE (SEQUENCE_NAME, SEQUENCE_VALUE)
VALUES ('USER_SEQUENCE', 1)
@Embeddable
public class EmbeddedEntity implements Serializable, RegistedEntity {
private static final long serialVersionUID = 1L;
private Calendar embeddedTime;
@Column(name="EMBEDDED_TIME")
@Temporal(TemporalType.TIMESTAMP)
public Calendar getEmbeddedTime() {
return embeddedTime;
}
public void setEmbeddedTime(Calendar embeddedTime) {
this.embeddedTime = embeddedTime;
}
}
@Entity
@Table(name = "ONE")
public class OneTable implements Serializable {
...
@Embedded
public EmbeddedEntity getEmbeddedEntity() {
return embeddedEntity;
}
...
}
@Embedded
@AttributeOverrides(@AttributeOverride(
name = "embeddedTime",
column = @Column(name = "DIFF_EMBEDDED_TIME"))
)
public EmbeddedEntity getDifferentColumnEmbeddedEntity() {
return differentColumnEmbeddedEntity;
}
@OneToOne(cascade=CascadeType.ALL)
@JoinColumn(name="ANOTHER_ONE", referencedColumnName="ID")
public AnotherOneTable getAnotherOne() {
return anotherOne;
}
這樣在主entity會有個ANOTHER_ONE欄位, mapping到AnotherOneTable這個entity的ID欄位.
< relationship field/property name >_< name of referenced primary key column >
如以下範例
@OneToOne(cascade=CascadeType.ALL)
@JoinColumn
public AnotherOneTable getAnotherOne() {
return anotherOne;
}
這樣就會在主table建立一個column: anotherOne_id mapping到AnotherOneTable這個entity的id欄位.
@Entity
@Table(name = "PARENT")
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(discriminatorType=DiscriminatorType.STRING, name="CHILD_TYPE", length=1)
public class Parent implements Serializable {
...
}
@Entity
@Table(name="GOOD_CHILD")
@DiscriminatorValue(value="G")
@PrimaryKeyJoinColumn(name="ID")
public class GoodChild extends Parent implements java.io.Serializable {
...
}
@Entity
@Table(name="USERS")
@SecondaryTable(name="USER_PICTURES", pkJoinColumns=@PrimaryKeyJoinColumn(name="USER_ID"))
public class MyUser implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private byte[] picture;
public void setId(Long id) {
this.id = id;
}
@Id
@Column(name="USER_ID")
@GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
return id;
}
@Column(name="PICTURE", table="USER_PICTURES")
@Lob
@Basic(fetch=FetchType.LAZY)
public byte[] getPicture() {
return picture;
}
public void setPicture(byte[] picture) {
this.picture = picture;
}
}
@Entity
@Table(name = "EMPLOYEE")
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String name;
private Address address;
public void setId(Long id) {
this.id = id;
}
@Id
@Column(name = "EMPLOYEE_ID")
@GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
return id;
}
@OneToOne(cascade=CascadeType.ALL)
@PrimaryKeyJoinColumn // 如果PK和referencedColumn名稱一樣就不用指定名稱
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
@Column(name="NAME")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
@Entity
@Table(name = "ADDRESS")
public class Address implements Serializable {
private static final long serialVersionUID = 1L;
private Long employeeId;
private String street;
@Id
@Column(name="EMPLOYEE_ID")
public Long getEmployeeId() {
return employeeId;
}
public void setEmployeeId(Long employeeId) {
this.employeeId = employeeId;
}
@Column(name="STREET")
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
}
這樣用hibernate自動建立的schema中address會少了FK constraint, 所以我又自己加了一個constraint
alter table address add constraint FK13246123456 foreign key (employee_id) references employee這段書上的說明不多, 不曉得我加了FK constraint之後是不是書上說的@PrimaryKeyJoinColumn使用模式
@Entity
public class Programmer implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String name;
private Set< Certification> certs = new HashSet();
public void setId(Long id) {
this.id = id;
}
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
return id;
}
@OneToMany(cascade=CascadeType.ALL, mappedBy="owner")
public Set< Certification> getCerts() {
return certs;
}
public void setCerts(Set< Certification> certs) {
this.certs = certs;
}
@Column(name="NAME")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
@Entity
public class Certification implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String certName;
private Programmer owner;
public void setId(Long id) {
this.id = id;
}
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
return id;
}
@Column(name="CERT_NAME")
public String getCertName() {
return certName;
}
public void setCertName(String certName) {
this.certName = certName;
}
@ManyToOne
@JoinColumn(name="PROGRAMMER_ID")
public Programmer getOwner() {
return owner;
}
public void setOwner(Programmer owner) {
this.owner = owner;
}
}
@Entity
@Table(name="COMPONENT")
public class Component implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private Component parent;
private List< Component> children = new ArrayList< Component>();
public void setId(Long id) {
this.id = id;
}
@Id
@Column(name="COMPONENT_ID")
@GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
return id;
}
@ManyToOne
@JoinColumn(name="PARENT_COMPONENT_ID", referencedColumnName="COMPONENT_ID")
public Component getParent() {
return parent;
}
public void setParent(Component parent) {
this.parent = parent;
}
@OneToMany(mappedBy="parent", cascade=CascadeType.ALL)
public List< Component> getChildren() {
return children;
}
public void setChildren(List< Component> children) {
this.children = children;
}
}
@Entity
@Table(name="SALES")
public class Sales implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String name;
private List< Product> products = new ArrayList< Product>();
public void setId(Long id) {
this.id = id;
}
@Id
@Column(name = "SALES_ID")
@GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
return id;
}
@Column(name = "NAME")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
// 沒設定mappedBy就會是unidirectional
@ManyToMany(mappedBy="sales", cascade=CascadeType.ALL)
public List< Product> getProducts() {
return products;
}
public void setProducts(List< Product> products) {
this.products = products;
}
}
@Entity
@Table(name = "PRODUCT")
public class Product implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String name;
private List< Sales> sales = new ArrayList< Sales>();
public void setId(Long id) {
this.id = id;
}
@Id
@Column(name = "PRODUCT_ID")
@GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
return id;
}
@Column(name = "NAME")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@ManyToMany(cascade=CascadeType.ALL)
@JoinTable(name = "PRODUCT_SALES", // PRODUCT_SALES是中間的table
// name是中間table的column, 若和現有column同名就不用referencedColumnName
joinColumns = @JoinColumn(name = "PRODUCT_ID"),
inverseJoinColumns = @JoinColumn(name = "SALES_ID")
)
public List< Sales> getSales() {
return sales;
}
public void setSales(List< Sales> sales) {
this.sales = sales;
}
}
public enum EmployeeType {
P, // Programmer
S // Sales
}
@Entity
@Table(name = "EMPLOYEE")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="EMPLOYEE_TYPE", length=1, discriminatorType=DiscriminatorType.STRING)
public abstract class Employee implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String name;
private EmployeeType employeeType;
public void setId(Long id) {
this.id = id;
}
@Id
@Column(name = "EMPLOYEE_ID")
@GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
return id;
}
@Column(name="NAME")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Column(name="EMPLOYEE_TYPE", insertable=false, updatable=false)
@Enumerated
public EmployeeType getEmployeeType() {
return employeeType;
}
public void setEmployeeType(EmployeeType employeeType) {
this.employeeType = employeeType;
}
}
@Entity
@DiscriminatorValue(value="P")
public class Programmer extends Employee implements Serializable {
private static final long serialVersionUID = 1L;
private String lang;
@Column(name="LANG")
public String getLang() {
return lang;
}
public void setLang(String lang) {
this.lang = lang;
}
}
@Entity
@DiscriminatorValue(value="S")
public class Sales extends Employee implements Serializable {
private static final long serialVersionUID = 1L;
private String product;
@Column(name="PRODUCT")
public String getProduct() {
return product;
}
public void setProduct(String product) {
this.product = product;
}
}
@Entity
@Table(name = "EMPLOYEE")
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name="EMPLOYEE_TYPE", length=1, discriminatorType=DiscriminatorType.STRING)
public abstract class Employee implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String name;
private EmployeeType employeeType;
public void setId(Long id) {
this.id = id;
}
@Id
@Column(name = "EMPLOYEE_ID")
@GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
return id;
}
@Column(name="NAME")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Column(name="EMPLOYEE_TYPE")
@Enumerated(EnumType.STRING)
public EmployeeType getEmployeeType() {
return employeeType;
}
public void setEmployeeType(EmployeeType employeeType) {
this.employeeType = employeeType;
}
}
@Entity
@Table(name="PROGRAMMER")
@DiscriminatorValue(value="P")
@PrimaryKeyJoinColumn(name="EMPLOYEE_ID")
public class Programmer extends Employee implements Serializable {
private static final long serialVersionUID = 1L;
private String lang;
@Column(name="LANG")
public String getLang() {
return lang;
}
public void setLang(String lang) {
this.lang = lang;
}
}
@Entity
@Table(name="SALES")
@DiscriminatorValue(value="S")
@PrimaryKeyJoinColumn(name="EMPLOYEE_ID")
public class Sales extends Employee implements Serializable {
private static final long serialVersionUID = 1L;
private String product;
@Column(name="PRODUCT")
public String getProduct() {
return product;
}
public void setProduct(String product) {
this.product = product;
}
}
Posted at 01:25上午 六月 05, 2008 by shooeugenesea in EJB3 | 迴響[0]
EJB3 - JPA - 取得EntityManager的方式
< persistence-unit name="persistence_oracle" transaction-type="JTA">
< provider>org.hibernate.ejb.HibernatePersistence< /provider>
< jta-data-source>jdbc/oracle< /jta-data-source>
< properties>
< property name="hibernate.dialect" value="org.hibernate.dialect.OracleDialect"/>
< property name="hibernate.hbm2ddl.auto" value="create"/>
< /properties>
< /persistence-unit>
< /persistence>
@Stateless
public class TestEntityManager implements ITestEntityManager {
@PersistenceContext(unitName="persistence_oracle" ) EntityManager em;
}
< persistence-unit name="persistence_oracle" transaction-type="JTA">
< provider>org.hibernate.ejb.HibernatePersistence< /provider>
< jta-data-source>jdbc/oracle< /jta-data-source>
< properties>
< property name="hibernate.dialect" value="org.hibernate.dialect.OracleDialect"/>
< property name="hibernate.hbm2ddl.auto" value="create"/>
< /properties>
< /persistence-unit>
< /persistence>
@Stateless
public class TestEntityManager implements ITestEntityManager {
@PersistenceUnit(unitName="persistence_oracle") EntityManagerFactory emf;
public EntityManager getAppManagedEntityManager() {
return emf.createEntityManager();
}
}
< persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
< persistence-unit name="persistence" transaction-type="RESOURCE_LOCAL">
< provider>org.hibernate.ejb.HibernatePersistence< /provider>
< class>com.isaac.entities.Address< /class>
< class>com.isaac.entities.IdentityID< /class>
< properties>
< property name="hibernate.show_sql" value="true"/>
< property name="hibernate.dialect" value="org.hibernate.dialect.OracleDialect"/>
< property name="hibernate.connection.username" value="sys as sysdba"/>
< property name="hibernate.connection.driver_class" value="oracle.jdbc.driver.OracleDriver"/>
< property name="hibernate.connection.password" value="shooeugenesea"/>
< property name="hibernate.connection.url" value="jdbc:oracle:thin:@localhost:1521:orcl"/>
< property name="hibernate.cache.provider_class" value="org.hibernate.cache.NoCacheProvider"/>
< property name="hibernate.hbm2ddl.auto" value="update"/>
< /properties>
< /persistence-unit>
< /persistence>
public class TestEntityManager {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("persistence");
public EntityManager getEntityManager() {
return emf.createEntityManager();
}
}
public class TestThreadLocal {
private static EntityManagerFactory emf;
public static final ThreadLocal< EntityManager > threadLocal = new ThreadLocal< EntityManager >();
public static EntityManagerFactory getEntityManagerFactory() {
if ( emf == null ) {
emf = Persistence.createEntityManagerFactory("persistence");
}
return emf;
}
public static EntityManager getEntityManager() {
EntityManager em = threadLocal.get();
if ( em == null ) {
em = emf.createEntityManager();
threadLocal.set(em);
}
return em;
}
}
Posted at 02:56上午 五月 18, 2008 by shooeugenesea in EJB3 | 迴響[0]
EJB3 - JPA - 一種設定GlassFish CMT的方式
Connection Pool和JDBC Resource如果沒有這樣設定,
而是在persistence.xml設定hibernate.XXX的 property的話, 會出現
RAR5117 : Failed to obtain/create connection from connection pool
[ OraclePool ]. Reason : Connection could not be allocated because:
Invalid Oracle URL specified: OracleDataSource.makeURL
RAR5114 : Error allocating connection : [Error in allocating a connection.
Cause: Connection could not be allocated because:
Invalid Oracle URL specified: OracleDataSource.makeURL]
這樣的錯誤.
如果沒有integrate JDBC driver,
會出現找不到OracleResultSet的ClassDefNotFound錯誤.
然後就會很悶, 因為明明連import OracleResultSet都沒問題了啊?
其實就是因為沒有設定在server上的關係.
< persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
< persistence-unit name="persistence_oracle" transaction-type="JTA">
< provider>org.hibernate.ejb.HibernatePersistence< /provider>
< jta-data-source>jdbc/oracle< /jta-data-source>
< properties>
< property name="hibernate.dialect" value="org.hibernate.dialect.OracleDialect"/>
< /properties>
< /persistence-unit>
< /persistence>
@Entity(name="T_USER")
public class User implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String name;
private Integer age;
public void setId(Long id) {
this.id = id;
}
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
return id;
}
@Override
public String toString() {
return "jpa.User[id=" + id + "][name= " + name + " ][age="+ age +"]";
}
@Column(name="NAME")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Column(name="AGE")
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
@Local
public interface ITestEntityManager {
EntityManager getEntityManager();
void createUser();
}
@Stateless
@TransactionManagement(TransactionManagementType.CONTAINER)
public class TestEntityManager implements ITestEntityManager {
@PersistenceContext(unitName="persistence_oracle") EntityManager em;
public EntityManager getEntityManager() {
return em;
}
public void createUser() {
User user = new User();
user.setName("111111111111111");
user.setAge(new Integer(999));
em.persist(user);
}
}
Posted at 01:16上午 五月 12, 2008 by shooeugenesea in EJB3 | 迴響[0]