I commited,

you can test it with this interface:

@Repository public interface Foo {
   MyEntity findByXXX(String xxx);
   MyEntity findById(long i);
   List<MyEntity> findByBar(int bar);
   // ...
}

look the logs you'll have the glbal jndi name ;)

- Romain

2011/7/31 Romain Manni-Bucau <[email protected]>

> Up ;)
>
> Nobody thinks it can be useful?
>
> /me still waits for some feedbacks before commiting a first version...
>
> - Romain
>
> Le 29 juil. 2011 22:37, "Romain Manni-Bucau" <[email protected]> a
> écrit :
>
> > Here is a patch:
> >
> > http://pastebin.com/4CgcLkmH
> >
> > it is a bit dirty at JNDI level but it works if you want to try:
> >
> > The repository:
> >
> > @Repository(context = @PersistenceContext(unitName = "user"))
> > public interface UserDAO {
> > User findById(long id);
> > Collection<User> findByName(String name);
> > Collection<User> findAll();
> > }
> >
> > An entity:
> >
> > @Entity
> > public class User {
> > @Id @GeneratedValue private long id;
> > private String name;
> > private int age;
> >
> > 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;
> > }
> >
> > public int getAge() {
> > return age;
> > }
> >
> > public void setAge(int age) {
> > this.age = age;
> > }
> >
> > @Override
> > public String toString() {
> > return "User{" +
> > "id=" + id +
> > ", name='" + name + '\'' +
> > ", age=" + age +
> > '}';
> > }
> > }
> >
> > A stateless to init the database:
> >
> > @Stateless
> > public class InitUserDAO {
> > @PersistenceContext private EntityManager em;
> > public void insert(User user) {
> > em.persist(user);
> > }
> > }
> >
> > The test:
> >
> > package org.superbiz.test;
> >
> > import org.junit.AfterClass;
> > import org.junit.BeforeClass;
> > import org.junit.Ignore;
> > import org.junit.Test;
> > import org.superbiz.dao.InitUserDAO;
> > import org.superbiz.dao.UserDAO;
> > import org.superbiz.model.User;
> >
> > import javax.ejb.embeddable.EJBContainer;
> > import javax.naming.Context;
> > import java.util.Collection;
> >
> > /**
> > * @author rmannibucau
> > */
> > public class QueryTest {
> > private static Context context;
> > private static UserDAO dao;
> >
> > @BeforeClass public static void init() throws Exception {
> > context = EJBContainer.createEJBContainer().getContext();
> > InitUserDAO init = (InitUserDAO)
> > context.lookup("java:global/dynamic-query/InitUserDAO");
> > dao = (UserDAO) context.lookup("java:global/openejb/Repository/" +
> > UserDAO.class.getName());
> > for (int i = 0; i < 10; i++) {
> > User u = new User();
> > u.setAge(i * 8);
> > if (i % 3 == 0) {
> > u.setName("foo");
> > } else {
> > u.setName("bar-" + i);
> > }
> > init.insert(u);
> > }
> > }
> >
> > @AfterClass public static void close() throws Exception {
> > if (context != null) {
> > context.close();
> > }
> > }
> >
> > @Test public void query() {
> > Collection<User> u1 = dao.findByName("foo");
> > Collection<User> users = dao.findAll();
> > User u2 = dao.findById(1);
> > System.out.println("\n\n" + users + "\n\n" + u1 + "\n\n" + u2);
> > }
> > }
> >
> > and the persistence.xml:
> >
> > <persistence xmlns="http://java.sun.com/xml/ns/persistence";
> > version="2.0"
> > 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_2_0.xsd";>
> > <persistence-unit name="user" transaction-type="JTA">
> > <jta-data-source>My Default DataSource</jta-data-source>
> > <class>org.superbiz.model.User</class>
> > <properties>
> > <property name="openjpa.jdbc.SynchronizeMappings"
> > value="buildSchema(ForeignKeys=true)"/>
> > </properties>
> > </persistence-unit>
> > </persistence>
> >
> > Don't hesitate to give me feedback if i should continue or not, what you
> > think should be done or not.
> >
> > - Romain
> >
> > 2011/7/29 Romain Manni-Bucau <[email protected]>
> >
> >> Hi,
> >>
> >> i discover a bit more spring data jpa and saw it was possible to create
> >> dynamically classes!!
> >>
> >> it is exactly the same than the stateless without interface excepted
> here
> >> the interface has no implementation.
> >>
> >> what do you think if we had it to OpenEJB, it is not standard but it is
> >> pretty cool.
> >>
> >> Here what i think we could do:
> >>
> >> 1. create a API to scan interfaces
> >> 1. we need persistencecontext information so we could use
>
> >> @PersistenceContext (i don't like) or add another annotation withthe
> same
> >> information (@Repository?)
> >> 2. we need a name, @Named can probably used or we can add it to
> >> @Repository
> >> 2. we scan "@Repository" interface constructing pseudo injection to
>
> >> be able to get an entitymanager
> >> 3. then we deploy it in JNDI
> >> 1. instead of binding a class we bind a proxy which manage to create
>
> >> the query from the name
> >>
> >>
> >> It is probably no clear so here some snippets:
> >>
> >> My repository:
> >>
> >> @Repository(name = "user")
> >> public interface UserDAO {
> >> User findById(long id);
> >> Collection<User> findByName(String name);
> >> Collection<User> findAll();
> >> }
> >>
> >>
> >> One very simple implementation of the invocation handler which manage
> only
> >> one condition (this version need an EntityManagerHolder which is here
> only
> >> to be able to get the em, it is just an interface with a method
> >> getEntityManager()...just to do the poc):
> >>
> >>
> >> public class QueryProxy<T> implements InvocationHandler {
> >> public static final String FIND_PREFIX = "find";
> >>
> >> private static final Map<String, List<String>> CONDITIONS = new
> >> ConcurrentHashMap<String, List<String>>();
> >>
> >> private EntityManagerHolder entityManagerHolder;
> >> private Class<T> type;
> >>
> >> public QueryProxy(EntityManagerHolder holder, Class<T> entityClass) {
> >> entityManagerHolder = holder;
> >> type = entityClass;
> >> }
> >>
> >> public Object invoke(Object proxy, Method method, Object[] args) throws
> >> Throwable {
> >> if (!method.getName().startsWith(FIND_PREFIX)) {
> >> throw new IllegalArgumentException("finder should start with
> >> find");
> >> }
> >>
> >> Query query = getQuery(entityManagerHolder.getEntityManager(),
> >> method.getName(), args);
> >> if (Collection.class.isAssignableFrom(method.getReturnType())) {
> >> return query.getResultList();
> >> }
> >> return query.getSingleResult();
> >> }
> >>
> >> private Query getQuery(EntityManager entityManager, String methodName,
> >> Object[] args) {
> >> final List<String> conditions = parseMethodName(methodName);
> >> final EntityType<T> et = entityManager.getMetamodel().entity(type);
> >> final CriteriaBuilder cb = entityManager.getCriteriaBuilder();
> >>
> >> CriteriaQuery<Object> query = cb.createQuery();
> >> Root<T> from = query.from(type);
> >> query = query.select(from);
> >>
> >> int i = 0;
> >> for (String condition : conditions) {
> >> SingularAttribute<? super T, ?> attribute =
> >> et.getSingularAttribute(condition);
> >> Path<?> path = from.get(attribute);
> >> Class<?> javaType = attribute.getType().getJavaType();
> >> if (javaType.equals(String.class)) {
> >> query = query.where(cb.like((Expression<String>) path,
> >> (String) args[i++]));
> >> } else if (Number.class.isAssignableFrom(javaType) ||
> >> javaType.isPrimitive()) {
> >> query = query.where(cb.equal(path, args[i++]));
> >> }
> >> }
> >>
> >> return entityManager.createQuery(query);
> >> }
> >>
> >> private List<String> parseMethodName(final String methodName) {
> >> List<String> parsed;
> >> if (CONDITIONS.containsKey(methodName)) {
> >> parsed = CONDITIONS.get(methodName);
> >> } else {
> >> parsed = new ArrayList<String>();
> >> String toParse = methodName.substring(FIND_PREFIX.length());
> >> // TODO
> >> if (toParse.startsWith("By")) {
> >> toParse = StringUtils.uncapitalize(toParse.substring(2));
> >> parsed.add(toParse);
> >> }
> >> CONDITIONS.put(methodName, parsed);
> >> }
> >> return parsed;
> >> }
> >> }
> >>
> >>
> >> Finally i can do:
> >>
> >> public class QueryTest {
> >> private static Context context;
> >> private static UserDAO dao;
> >>
> >> @BeforeClass public static void init() throws Exception {
> >> context = EJBContainer.createEJBContainer().getContext();
> >> dao = (UserDAO)
> >> Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
> >> new Class<?>[] { UserDAO.class },
> >> new QueryProxy((EntityManagerHolder)
> >> context.lookup("java:global/dynamic-query/EMH"), User.class));
> >>
> >>
> >> InitUserDAO init = (InitUserDAO)
> >> context.lookup("java:global/dynamic-query/InitUserDAO");
> >> for (int i = 0; i < 10; i++) {
> >> User u = new User();
> >> u.setAge(i * 8);
> >> if (i % 3 == 0) {
> >> u.setName("foo");
> >> } else {
> >> u.setName("bar-" + i);
> >> }
> >> init.insert(u);
> >> }
> >> }
> >>
> >> @AfterClass public static void close() throws Exception {
> >> if (context != null) {
> >> context.close();
> >> }
> >> }
> >>
> >> @Test public void query() {
> >> Collection<User> u1 = dao.findByName("foo");
> >> Collection<User> users = dao.findAll();
> >> User u2 = dao.findById(1);
> >> System.out.println("\n\n" + users + "\n\n" + u1 + "\n\n" + u2);
> >> }
> >> }
> >>
> >> Any thoughts? should it be added to OpenEJB (after some enhancement of
> >> course ;))?
> >>
> >>
> >> we could extend it to persist, update etc... methods
> >>
> >>
> >> - Romain
> >>
> >>
> >>
> >>
> >>
>
>

Reply via email to