hibernate - добавление в Set приводит к InvocationTargetException - PullRequest
0 голосов
/ 27 июля 2011

Делая мои первые шаги в hibernate и postgres, я создал конфигурации xml старого стиля для своих классов сущностей и создал несколько реализаций dao, как упомянуто в книге (Manning Java Persistence with Hib), и создал класс HibernateUtil для создания SessionFactory. Чтобы проверить их, Я создал несколько сущностей и попытался сохранить через dao.

В этом коде класс Customer имеет набор 'Order's. Чтобы настроить это, я создал файлы hbm.xml, как показано ниже..

В методе demo () я создал экземпляры сущностей и вызвал saveOrUpdate () через dao.Он успешно выполняется и создает двух клиентов и заказ в дБ. Однако, когда я пытаюсь добавить заказ к клиенту, он вызывает RuntimeException и откатывает транзакцию.При попытке отладки приложения я обнаружил, что

org.hibernate.context.ThreadLocalSessionContext.TransactionProtectionWrapper.invoke () ---> lang.reflect.Method.invoke () ---> java.lang.reflect.InvocationTargetException

Я не понимаю, почему это происходит. Эта ошибка не возникнет, если я не вызову addOrdersToCustomers ().Если я не вызову этот метод, разве это не будет означать, что у объекта Customer нет набора заказов? В db в таблице Order есть FK customer_id, который успешно устанавливается в качестве идентификатора customer, поскольку метод createOrders () устанавливает Customerполе Order для экземпляра клиента. Но это не приводит к обновлению поля Set orders клиента.

Есть идеи, как это исправить?спасибо,

Джим

public class Main {
    CustomerDao custdao;
    OrderDao orderdao;  
    Customer mark,jon;
    Order order1,order2,order3; 
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");

        public void demo()throws ParseException{
             custdao = Daofactory.getCustomerDao();
         orderdao = Daofactory.getOrderDao();
             createCustomers();
             createOrders();
             //addOrdersToCustomers();//uncommenting this causes RuntimeException
             updateEntities();
        }
        private  void updateEntities() {
            Transaction tx = null;
            Session session = HibernateUtil.getCurrentSession();
            logger.info("got session:"+session);
            try{
                tx = session.beginTransaction();
                logger.info("got transaxion:"+tx);

                custdao.saveOrUpdateCustomer(mark);         
                custdao.saveOrUpdateCustomer(jon);          
                orderdao.saveOrUpdateOrder(order1);     
                        tx.commit();
                 }catch(Exception e){
                    tx.rollback();
                 }
        }

       private void addOrdersToCustomers() {
        mark.getOrders().add(order1);
       }
       private void createCustomers() {
        mark = new Customer();
        mark.setName("mark");
        mark.setEmailAddress("mark@home");
        mark.setAddress("121,3rd avenue");
        mark.setCity("San Diego");
        mark.setState("CA");
        mark.setCountry("U.S.A");

        jon = new Customer();
        jon.setName("jon");
        jon.setEmailAddress("jon@home");
        jon.setAddress("1121 vpura");
        jon.setCity("bangalore");
        jon.setState("karnataka");
        jon.setCountry("india");

    }
    private void createOrders() throws ParseException {
        order1 = new Order();
        order1.setCustomer(mark);
        order1.setOrderNumber(Long.parseLong("111111111"));
        order1.setOrderDate(sdf.parse("2001/01/02"));
                ...  
    }
       ...
       public static void main(String[] args) throws ParseException {
        new Main().demo();

        }
    }

Отображения следующие,

public class Customer {
    private Long customer_id;
    ...        
    private Set<Order> orders;
    public Customer() {
        super();
        orders = new HashSet<Order>();
    }
    ...
}

<hibernate-mapping package="org.me.hibernatestore">
 <class name="Customer" table="CUSTOMER">
  <id column="CUSTOMER_ID" name="customer_id"  type="java.lang.Long">
  <generator class="native"/>
  </id>  
...      
    <set name="orders" table="ORDERS" lazy="false" cascade="delete-orphan">
        <key column="CUSTOMER_ID"/>
        <one-to-many class="Order" />
    </set>    
 </class>
</hibernate-mapping>

Order.java

public class Order {
    private Long order_id;
    ...
    private Customer customer;
    ...
}

Order.hbm.xml

...
<class name="Order" table="ORDERS">
    <id name="order_id" column="ORDER_ID" type="long">
        <generator class="native"/>
    </id>
    ...
    <many-to-one name="customer" class="Customer" column="CUSTOMER_ID" lazy="false" />
...

Реализации dao имеют базовый класс

public class BaseDaoImpl<T, ID extends Serializable> implements BaseDao<T,ID>{
    private Class<T> persistentClass;
    private Session session;    
    public BaseDaoImpl() {
        this.persistentClass = (Class<T>)(((ParameterizedType)this.getClass().getGenericSuperclass()).getActualTypeArguments()[0]);
    }   
    public Session getSession() {
        if (session == null){           
            return HibernateUtil.getCurrentSession();
        }       
        return session;
    }
       ...
}

HibernateUtil.java

public class HibernateUtil {    
    private static SessionFactory sessionFactory;
    static {
        try {
            sessionFactory = new Configuration().configure().buildSessionFactory();         
        }catch (Throwable ex) {
            throw new ExceptionInInitializerError(ex);
        }
    }
    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }
    public static Session getCurrentSession(){
        Session session = sessionFactory.getCurrentSession();       l
        return session;
    }

1 Ответ

1 голос
/ 27 июля 2011

Ваша трассировка стека четко указывает причину - вы пытаетесь сохранить объект со ссылкой на временный объект. Вам либо нужно вызвать save() для добавленного Order объекта, прежде чем вызывать его для вашего Customer, или вам нужно добавить (как минимум) постоянный каскад для набора orders в вашем классе Customer. В вашем xml случае это исправит

<set name="orders" table="ORDERS" lazy="false" cascade="delete-orphan">

до

<set name="orders" table="ORDERS" lazy="false" cascade="delete-orphan,persist">
...