JPAContainer + table + annotation problems with oneToMany

Hi!

I am using JPAContainer to edit, add and delete companies (COMPANY-table) and it’s working fine. Now I am implementing staffEditor, what is for adding, deleting, editing staff of the company etc.

When a user press the add staff-button, staffEditor should open with the data of a specific company’s staff.

getApplication().getMainWindow().addWindow(
                        new StaffEditor(companyTable.getItem(companyTable
                                .getValue())));

Now I know which company’s staff I am going to show, but how I implement that (Select * from STAFF, where company_ID=‘10’;)? In Company Entity there is oneToMany relationship between company and Staff-table and Company has a Set of Staff. I would like to use JPAContainerFactory so that in staffEditor’s JPAContainer is just staff of the company in question or if there is not staff at all the new staff to be added will belong to to that company in question.

Orrrr

How can I get staff from the company and use it as a persistant unit and source of a table in staffeditor?
public StaffEditor(Item companyItem) {

Cheers,
Sami

Hi,

I assume that you are using the JPAContainer 2.0.0 snapshot as I suggested you earlier in some thread. We are currently working on some nice stuff that will really help you building Form’s for various reference fields. The magic is done by class called JPAContainerFieldFactory. If you use that field Factory (or a derived version) in Form , you’ll magically have simple fields for various reference types. A quick summery below:

@ManyToOne → single select (by default NativeSelect) listing all instances of referenced type
@ManyToMany → multi select (by default Table) listeng all instances of referenced type
@OneToMany → “master detail editor”, by default editable table
@OneToOne → subform of referenced type

A new snapshot build with initial implementations for all above fields should be in our snapshot repository soon. All this is still at experimental level, but I’d urge you to try and share you experiences. I our simple test cases the concept seams to work very nice, although there is still some fine-tuning to be done.

A very rude usage example can be checked out from our integration test project:
http://dev.vaadin.com/svn/addons/JPAContainer/trunk/jpacontainer-itest/src/main/java/com/vaadin/addon/jpacontainer/itest/fieldfactory/

cheers,
matti

Hi and thanks for quick answer!!

I am using snapshot version of the JPAContainer.

So there is no easy way to get Company’s staff-objects with JPA? Must be. Just give me all Staff-objects from table Staff where company_id is for instance 1 etc…or if I have JPAContainer, where is companys, there must be way to get one company’s staff-objects from it? I am quite sure that there is, but I just can’t do it :slight_smile: I’ll check that FieldFactoryTest-application…

edit:

I tested it but JPAContainerFieldFactory is not compiling at the moment, package declaration to JPAContainerFieldFactory is not valid and there is no more default constructor for that: JPAContainerFieldFactory jpaContainerFieldFactory = new JPAContainerFieldFactory();

Sami

Hi,

Sure there is, but the “master-detail editor” provided by the JPAContainerFieldFactory would do it for you automatically. To do it manually, you have two approaches:

  1. Use the filtering API e.g. something like this : staffContainer.addContainerFilter(new Equal(“company”, myCompanyBean));
  2. Use the new (currently being developed, so all input is welcome) QueryModifierDelegate in EntityProvider that one can use to make custom modifications to the query with standard JPA 2.0 Criteria API.

I’m quite sure your exceptions with the integration test project come are due to an old snapshot build (there is currently lots of changes going on in the project). There should be a new build available (built about two hours ago).

cheers,
matti

Hi,

I checked out the whole project 19.35 and I still get the same version where is:

import com.vaadin.addon.jpacontainer.fieldfactory.JPAContainerFieldFactory;

and


protected void editCustomer(EntityItem<Customer> entityItem) {
        if (customerForm == null) {
            customerForm = new Form();
            customerForm.setCaption("EditCustomer groups");
            JPAContainerFieldFactory jpaContainerFieldFactory = new JPAContainerFieldFactory();------>!
            jpaContainerFieldFactory.setMultiSelectType(CustomerGroup.class, TwinColSelect.class);
            customerForm.setFormFieldFactory(jpaContainerFieldFactory);
            addComponent(customerForm);
        }

Maybe I do something wrong. I just check that itest-project out as a new project to Eclipse and after that I configure it to Maven-project and then maven build. BTW how you use those applications? I tried to put class name after the URL, but I still got the window with text: JPAContainer test and playground app, add the test class name to your url to start.



And then the question:

Could you or somebody tell me how I get companyID populated in STAFF-table? In my case staff is just own object, no relationship to company at all and my foreign key column (companyID) in STAFF-table is always default aka 0. Do I even need that information if the staff is inside of the Company when I read it from the DB? I am so newbie with Vaadin and JPA…I don’t care how I solve that, but I have to show one company’s staff in one Table, now there ei every staff-objects which are in DB, no good.


COMPANY

public class Company implements java.io.Serializable {

	
	private static final long serialVersionUID = -6779355918409596943L;
	@Id
        @GeneratedValue(strategy = GenerationType.AUTO)---->AUTO INCREMENT
	@Column(name = "company_id", unique = true, nullable = false)
	private Short companyId;
	@OneToOne(cascade=CascadeType.PERSIST)
	private Address address;
	private String companyName;
	.......
	@Temporal(TemporalType.DATE)
	private Date lastUpdate;
	@OneToMany(fetch = FetchType.LAZY, mappedBy = "company",cascade=CascadeType.PERSIST)
	@JoinColumn(name="staffId") 
	private Set<Staff> staffs = new HashSet<Staff>(0);


STAFF


      
@Entity
public class Staff implements java.io.Serializable {

	@Id
        @GeneratedValue(strategy = GenerationType.AUTO)---->AUTO INCREMENT
	@Column(name = "staff_id", unique = true, nullable = false)
	private Integer staffId;
	@OneToOne(cascade=CascadeType.PERSIST)
	private Address address;
	private short addressId;
	@NotNull
	@JoinColumn(name="company_id") ---->[b]
MIten pirussa mä saan tän populoitumaan samalla kun lisään companyn ja sille yhden staffin??
[/b]
	private short companyId;
	@NotNull
    @ManyToOne (fetch = FetchType.LAZY, cascade=CascadeType.PERSIST)
	private Company company;

EntityManager em = Persistence
				.createEntityManagerFactory("adminTool")
				.createEntityManager();
		
		em.getTransaction().begin();
		
		
		Company company = new Company();
		Address address = new Address();
		Staff staff = new Staff();
		
		

		address.setAddress1("Törnintie 2");
		address.setZip("007007");
		em.persist(address);
		
		staff.setEmail("Jarkko Jytky@gmail.com");
		staff.setFirstName("Jarkko");
		staff.setLastName("Jytky");
		staff.setUserName("jajy");
		staff.setCompany(company);
		em.persist(staff);
		
		Set<Staff> staffs = new HashSet<Staff>();
		staffs.add(staff);
		
		company.setCompanyName("Nousu OY");
		company.setBusinessId("1234567");
		company.setStaffs(staffs);
		company.setAddress(address);
		company.setVatNumber("999999999");
		em.persist(company);

ARGHHHHHHH :slight_smile:
Sami

Hi Sami,

You’re almost there :slight_smile:

You should remove the companyId from your Staff class and add a reference to Company like so:


    @NotNull
    @ManyToOne
    private Company company;

Since you already have annotated staff as @OneToMany mapped by “company” in your Company class, JPA will automatically link the two together. On the database level the “company” column in the staff table will contain the company id and when you use an instance of Staff in your java code, the “company” member will be automatically populated for you.

HTH,
/Jonatan

Thanks! Now it’s working but have you an idea how auto increment fields is working? I have company and companyID is auto increment. If we still imagine, that there is that companyID-field in my Staff-bean, how can I get it when I make an add-operation to DB. Maybe I just don’t need it anymore, but just curious :slight_smile:

Sami