読者です 読者をやめる 読者になる 読者になる

Hibernate事始め getResultListってこれでいいのか・・・?

Java Hibernate

こんな感じでやってみたよー。

public class ProductDaoTest {

 private ProductDao dao;

 @Test
 public void test() {
  dao = new ProductDao();
  dao.save(p(1));
  dao.save(p(2));
  dao.save(p(3));
  dao.save(p(4));
  Beans<Product> products = dao.selectAll();
  System.out.println(products);
  Product product = dao.selectById(1);
  System.out.println(product);
 }

 private Product p(int id) {
  Product p = new Product();
  p.id = id;
  p.name = "product" + id;
  p.price = id * 100;
  return p;
 }
}

//Dao
public class ProductDao {

 private EntityManager manager = Persistence.createEntityManagerFactory(
   "defaultDB").createEntityManager();

 public Product selectById(int id) {
  return manager.find(Product.class, id);
 }

 @SuppressWarnings("unchecked")
 public Beans<Product> selectAll() {
  //ここがいけてなさ過ぎる
  final List<Object[]> src = manager.createNamedQuery(
    "productDao.selectAll").getResultList();
  return convert(src);
 }

 public void save(Product p) {
  EntityTransaction tx = manager.getTransaction();
  tx.begin();
  try {
   manager.merge(p);
   manager.flush();
   tx.commit();
  } catch (Exception e) {
   tx.rollback();
  }
 }
 //毎度毎度こんなの書いてられないしなぁ
 //なんかいい方法あるんだろうかね?
 private Beans<Product> convert(List<Object[]> src) {
  Beans<Product> products = new Beans<Product>(src.size());
  for (Object[] objects : src) {
   products.add(p(objects));
  }
  return products;
 }

 private Product p(Object[] objects) {
  Product product = new Product();
  product.id = (Integer) objects[0];
  product.name = (String) objects[1];
  product.price = (Integer) objects[2];
  return product;
 }
}

//Bean
//ここもアノテーションがごちゃごちゃしすぎ。
@Entity(name = "product")
@Table(name = "product")
@AccessType("field")
@NamedQueries( { 
 @NamedQuery(name = "productDao.selectAll", 
  query = "SELECT id, name, price FROM product")
})
public class Product {

 @Id
 @Column(name = "id")
 public int id;

 @Column(name = "name")
 public String name;

 @Column(name = "price")
 public int price;

 public String toString() {
  return String.format("ID[%s] 商品名[%s] 値段[%s]", 
   new Object[] { id, name, price });
 }
}

// Beans
public class Beans<T> {

 private List<T> beans;

 public Beans(int size) {
  beans = new ArrayList<T>(size);
 }

 public Beans() {
  beans = new ArrayList<T>();
 }

 public void add(final T bean) {
  beans.add(bean);
 }

 public void add(final List<T> otherBeans) {
  beans.addAll(otherBeans);
 }

 public T get(final int index) {
  return beans.get(index);
 }

 public String toString() {
  final StringBuilder builder = new StringBuilder();
  for (Iterator<T> items = beans.iterator(); items.hasNext();) {
   final T item = items.next();
   builder.append("[ ");
   builder.append(item.toString());
   builder.append(" ] ");
  }
  builder.setLength(builder.length() - 1);
  return builder.toString();
 }
}

まぁ、ノリと勢いで始めてみたんだけどAPIがどうも不思議。他にいい方法があるのかもしれないんだけど、Query#getResultList()ってListが返ってくるのね・・・。なんでこんなめんどくさいAPIなんだ・・・?そもそもNamedQueryをEntityに付けるのは決まってるんだから対象になるEntityクラスくらい判別つくと思うんですけどももももも。なんか納得いかないなぁ。単純使い方がマチガッテルヨーっていうならいいんだけどもさ。なにかご存知の方いましたらアドバイスをを。

追記:バージョンはこんな感じ

hibernate-3.2.5.ga
hibernate-entitymanager-3.3.1.ga
hibernate-annotations-3.3.0.ga

追記2:persistence.xml書き忘れてた

<?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="defaultDB"
		transaction-type="RESOURCE_LOCAL">
		<provider>org.hibernate.ejb.HibernatePersistence</provider>
		<class>net.cynipe.tera.frameworks.entity.Product</class>
		<properties>
			<property name="hibernate.dialect"
				value="org.hibernate.dialect.H2Dialect" />
			<property name="hibernate.connection.driver_class"
				value="org.h2.Driver" />
			<property name="hibernate.connection.username" value="cynipe" />
			<property name="hibernate.connection.password" value="cynipe" />
			<property name="hibernate.connection.url"
				value="jdbc:h2:~/net/cynipe/sample" />
			<property name="hibernate.hbm2ddl.auto" value="create-drop" />
			<property name="hibernate.show_sql" value="true" />
			<property name="hibernate.format_sql" value="true" />
		</properties>
	</persistence-unit>
</persistence>