hibernate-添加到 Set 会导致 InvocableTargetException

发布于 2024-11-26 10:33:57 字数 5380 浏览 1 评论 0原文

迈出使用 hibernate 和 postgres 的第一步,我为实体类创建了旧式 xml 配置,并创建了一些 dao 实现,如(Manning Java Persistence with Hib)书中提到的,并创建了一个 HibernateUtil 类来创建 SessionFactory。为了测试这些,我创建了一些实体并试图通过 dao 来保存。

在此代码中,Customer 类具有一组“订单”。为了配置它,我创建了 hbm.xml 文件,如下所示。

在 demo() 方法中,我创建了实体实例并调用 saveOrUpdate () 通过 dao。 它成功运行并在 db 中创建两个客户和一个订单。但是,当我尝试将订单添加到客户时,它会导致 RuntimeException 并回滚事务。 当我尝试调试应用程序时,我发现

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

我很困惑为什么会发生这种情况。如果我不调用 addOrdersToCustomers(),则不会发生此错误。 如果我不调用该方法,那不是意味着 Customer 对象没有订单集吗?在数据库中,Order 表有一个 FK customer_id,由于 createOrders() 方法设置了 Customer,因此它已成功设置为客户的 id但是,这并不会使 Customer 的 Set Orders 字段被更新。

知道如何纠正这个问题吗? 谢谢,

Jim

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;
    }

Taking my first steps with hibernate and postgres ,I created old style xml configurations for my entity classes and created some dao implementations as mentioned in( Manning Java Persistence with Hib) book and created a HibernateUtil class to create SessionFactory .To test these ,I created some entities and tried to save through dao .

In this code,Customer class has a set of 'Order's .To configure this I created the hbm.xml files as given below..

In the demo() method ,I created the entity instances and called saveOrUpdate() through dao.
It runs successfully and creates the two customers and an order in db .However,when I try to add the order to a customer,it causes RuntimeException and rolls back the transaction.
When I tried to debug the app,I found that

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

I am confused why this occurs.This error wont occur if I don't call addOrdersToCustomers().
If I don't call that method,would it not mean the Customer object has no Set of orders?In the db,the Order table has a FK customer_id which is successfully set to the id of customer since createOrders() method sets the Customer field of Order to the customer instance.But,that doesn't make the Set orders field of Customer to be updated.

Any idea how to correct this?
thanks,

Jim

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();

        }
    }

The mappings are as follows,

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" />
...

The dao implementations have a base class

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;
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

那小子欠揍 2024-12-03 10:33:57

您的堆栈跟踪清楚地表明了原因 - 您正在尝试使用对瞬态对象的引用来保存对象。您要么需要在添加的 Order 对象上调用 save(),然后再在 Customer 上调用它,或者您需要添加一个(至少)将级联保留在 Customer 类中设置的 orders 上。在您的 xml 情况下,这将更正

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

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

Your stacktrace clearly indicates the reason -- you're trying to save an object with a reference to a transient object. You either need to call save() on your added Order object before calling it on your Customer, or you need to add an (at least) persist cascade on the orders set in your Customer class. In your xml case this would be correcting

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

to

<set name="orders" table="ORDERS" lazy="false" cascade="delete-orphan,persist">
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文